Utilisation de resload_Protect#?
Théorie
Dans certaines situations, il est très utile d'être informé quand le programme
installé accède à certaines zones de la mémoire.
Avec la fonction resload_Protect#?, il est
possible de protéger certaines parties de la mémoire contre la lecture et/ou
l'écriture du processeur. "Protéger" veut dire que chaque accès à une région
de la mémoire protégée créera un Access Fault exception avec comme résultat
un message approprié généré par WHDLoad. Si vous déclarez une partie de la
mémoire comme protégée en utilisant la fonction resload_Protect#? WHDLoad modifiera les
"affected page descriptor" dans l'arbre de traduction MMU.
Maintenant chaque accès à cette page protégée, le CPU provoquera un Access Fault
exception. Cette exception est traitée dans WHDLoad qui en vérifiera la raison.
Si c'était un accès à une page protégée mais que l'accès ne touche pas à la
mémoire protégée, cet accès sera émulé, et le programme continuera à fonctionner
normalement. Autrement, WHDLoad quittera avec un message approprié. Si l'accès
était un accès à des "instructions stream" (par ex. le CPU essaye de charger
le code), ce sera toujours émulé, en d'autres termes, les fonctions resload_Protect#? affecteront seulement
la lecture et l'écriture des données. Le fait est que chaque accès à une page
protégée (actuellement la taille de la page est de $1000) produira un Access Fault,
même si la partie protégée n'est que de 1 octect, en conséquence la vitesse
d'exécution du programme pourra ralentir énormément. Spécialement si une partie du
code se trouve dans la même page. Si le programme dépend de la vitesse d'exécution,
il se peut que le programme ne fontionnera pas avec de la mémoire protégée.
Exemple: checksums en dehors du code
Si vous installez un jeu en utilisant WHDLoad, vous devez patcher les routines
originales du loader dans le jeu, dans un même temps, elles utiliseront WHDLoad
pour charger les données du jeu. Quelques jeux exécutent des sommes de contrôle
en dehors du code pour détecter si le code original a été modifié. Ces détections
peuvent être dures à trouver. Mais rien n'est plus facile qu'en utilisant les
fonctions resload_Protect#? dans WHDLoad.
Ce que devez faire n'est d'autre que de protéger en lecture les octets que vous
avez changés dans le code du jeu. Maintenant chaque routine qui essayera de calculer
un checksum et lira votre code patché, provoquera un Access Fault.
Vous saurez donc où la routine se trouve.
Limitations
Vous ne devez pas protéger une page de mémoire où le pointeur de pile superviseur
(SSP) se trouve. Si vous
faites cela, et qu'une exception se produit, il y aura un "Double Bus Fault"
car le CPU sera incapable d'écrire le stackframe de l'exception. Après un
Double Bus Fault, un reset de l'ordinateur doit être effectué. WHDLoad s'assure qu'il n'y pas de conflit entre la zone protégée et le SSP et quitte, mais il ne peut rien faire si le changement de SSP se fait par la suite.
- 68020 + 68851
- Ce hardware n'est pas supporté actuellement
- 68030
- Les transfers de 3-Byte ne sont pas supportés et provoqueront un vrai Access
Fault, de tels transfers se produisent s'il y a un accès à un mot long à une
adresse impaire dans une frontière de page (ex. "tst.l ($fff)" où la page est protégée
à partir de $1000), parce que c'est une instruction invalide sur 68000, vous
ne la verrez probablement pas.
- Les transfers bloqués causés par tas, cas ou cas2 ne sont pas supportés et créeront
un vrai Access Fault, ce n'est pas un problème car les transferts bloqués ne sont
pas supportés par le hardware Amiga.
- 68040
- Ce hardware n'est pas supporté actuellement
- 68060
- L'accès aux données non alignées ne sont pas supportés et provoqueront un
vrai Access Fault, un tel accès est un accès qui couvre 2 pages (dont une est
au moins protégée), par exemple "tst.l ($ffe)" affecte la page $0..$fff et la
page $1000..$1fff, cette limitation est un vrai problème et fait que la fonction
resload_Protect est parfois inutile. J'essayerai peut-être de supporter ceci
mais c'est difficile.
- L'accès aux instructions stream non alignés ne sont pas supportés et créeront
un vrai Access Fault si toutes les deux pages affectées sont protégées. La
plupart du temps, ceci devrait être évité.
- Les transfers bloqués causés par tas, cas ou cas2 ne sont pas supportés et créeront
un vrai Access Fault, ce n'est pas un problème car les transferts bloqués ne sont
pas supportés par le hardware Amiga.
- Les instructions qui se trouvent dans la page protégée (et donc
émulés) et les accès à l'octet superviseur du registre d'état sera mal
exécuté, ces instructions verront toujours le bit du mode trace à 1 et les
masques d'interruption à 7, aucune modification de l'octet superviseur
ne sera faite (l'octet superviseur restera intacte).
- Les instructions movem peuvent accéder à une mémoire sans provoquer un
Access Fault exception, ceci est possible car seulement le 1er accès sera
vérifié.
- Move16 et les opérations à double précision (FPU) ne sont pas supportés
et créeront un vrai Access Fault.
- Un "move (mem),(mem)" avec un chevauchement de l'adresse de la source et de
la destination généreront un Access Fault car le "non alignement" ne sera pas
exécuté correctement. Par exemple "move.l ($ffc),($ffe)" où la page
$1000..$1fff est protégée et la mémoire avant exécution contient ($ffc)=$11112222,
($1000)=$33334444, après exécution, $1000 contiendra $11114444 au lieu de $22224444