Utilizzo di resload_Protect#?
Teoria
Esistono molte situazioni in cui può tornare utile di venire informati quando il programma installato accede ad alcune
specifiche locazioni di memoria.
Con le funzioni resload_Protect#? è possibile proteggere alcune locazioni di
memoria dalla lettura e/o scrittura da parte del processore. Proteggere significa che ogni accesso in questa area protetta
causerà un Access Fault exception che farà apparire un apposito requester di WHDLoad. Se una certa area di memoria viene
dichiarata come protetta mediante l'utilizzo di una funzione resload_Protect#?,
WHDLoad modificherà i relativi descrittori di pagina nel translation tree della MMU. Da questo momento ad ogni accesso
alla pagina protetta la CPU causerà un Access Fault exception. L'exception handler all'interno di WHDLoad verificherà la
ragione di questa eccezione.
Se la ragione è stato un accesso ad una pagina protetta ma questo accesso non coincide con l'area
protetta, l'accesso verrà emulato, e proseguirà la normale esecuzione del programma. Altrimenti WHDLoad terminerà con un
appropriato requester. Se l'accesso è stato effettuato nell'instruction stream (flusso di istruzioni) (per esempio la cpu
tenta di caricare codice) verrà sempre emulato, o in altre parole le funzioni resload_Protect#? funzionano solamente al caricamento/salvataggio di dati.
Il fatto che ogni accesso ad una pagina protetta (la dimensione della pagina attualmente è $1000) causerà un access fault,
anche se l'area protetta è grande un solo byte, l'esecuzione del programma subirà un notevole degrado in velocità.
Specialmente se parti di codice sono localizzate nella stessa pagina. Se il programma dipende dalla velocità di
esecuzione, c'è la possibilità che giri in modo diverso dal normale. Quindi è possibile che qualche programma non funzioni
in modalità protetta.
Esempio: checksum sul codice
Se installi un gioco con WHDLoad devi patchare le routine del loader originale di modo che utilizzino WHDLoad per caricare i
dati del gioco. Qualche gioco esegue un controllo del checksum di qualche parte del codice per verificare se il codice
originale è stato modificato. Queste routine di verifica possono a volte essere difficili da scovare. Ma utilizzando le
funzioni resload_Protect#? in WHDLoad niente è più semplice da fare. Tutto quello
che dovrai fare è di proteggere i byte che hai modificato nel codice dei giochi dalla lettura. D'ora in poi ogni routine
che tenterà di eseguire un checksum e leggerà il tuo codice modificato causerà un access fault. A questo punto saprai dove
si nasconde questa routine.
Limitazioni
Non devi proteggere la pagina di memoria dove punta l'SSP. Se lo farai, ed avverrà un'eccezione, il tutto risulterà in un
Double Bus Fault perché la CPU non sarà capace di scrivere l'exception stackframe. Dopo un Double Bus Fault si può solo
resettare per continuare l'esecuzione. WHDLoad controlla se ci sono confilitti nell'area protetta con il SSP e terminerà l'esecuzione se ne troverà, ma questo non sarà di aiuto se il SSP cambierà in seguito.
- 68020 + 68851
- questo hardware non è attualmente supportato
- 68030
- i trasferimenti a 3-Byte non sono supportati e causeranno un Access Fault reale, questi trasferimenti avvengono se
si accede ad una longword ad un indirizzo dispari all'interno di una pagina (ad esempio "
tst.l ($fff)
"
dove la pagina a $1000 è protetta), poiché questo tipo di accesso non è valido su un 68000 probabilmente non vedrai mai
cose del genere
- i locked transfers causati da
tas
, cas
o cas2
non sono supportati
e causeranno un Access Fault reale, anche se questo non è un problema visto che i locked tranfers non sono supportati
dall'hardware Amiga
- 68040
- questo hardware non è attualmente supportato
- 68060
- gli accessi disallineati al flusso dei dati non sono supportati e causeranno un Access Fault reale, un accesso
disallineato è un accesso che coincide con due pagine (e almeno una di queste è protetta); per esempio
"
tst.l ($ffe)
" accede alla pagina $0..$fff e alla pagina $1000..$1fff, questa limitazione è un vero problema
e renderà resload_Protect a volte praticamente inutilizzabile, forse in futuro tenterò di supportare questo tipo di
accesso ma la faccenda è complessa
- gli accessi disallineati al flusso delle istruzioni non sono supportati e causeranno un Access Fault reale se entrambe
le pagine a cui si tenta di accedere sono protette, il più delle volte questa situazione dovrebbe essere evitabile
- i locked transfers generati da
tas
o cas
non sono supportati e causeranno un Access Fault
reale, anche questo non è un problema visto che in ogni caso non sono supportati dall'hardware Amiga
- le istruzioni site in una pagina protetta (che perciò verranno emulate) e che accedono alla parte supervisore dello
status register non verranno correttamente eseguite, queste istruzioni vedranno sempre il trace bit (bit di traccia) come 1
e l'interrupt priority mask come 7; ogni modifica alla porzione supervisore non sortirà alcun effetto (rimarrà immutata)
- l'istruzione
movem
può accedere ad un'area protetta senza generare un Access Fault exception, questo è
possibile perché verrà verificata la coincidenza con l'area protetta solo del primo accesso (word o longword)
move16
e le operazioni in doppia precisione (FPU) non sono supportate e causeranno un Access Fault reale
- un "
move (mem),(mem)
" con gli indirizzi sorgente e destinazione sovrapposti genereranno un Access Fault
perché il disallineamento verrà eseguito in maniera non corretta, per esempio "move.l ($ffc),($ffe)
"
dove la pagina $1000..$1fff è protetta e la memoria prima dell'esecuzione contiene ($ffc)=$11112222, ($1000)=$33334444,
dopo l'esecuzione $1000 conterrà $11114444 e non $22224444