Question

J'ai écrit un programme « dangereux » en C ++ qui saute avant et en arrière d'un cadre de pile à l'autre. L'objectif est d'être saut de niveau le plus bas d'une pile d'appel à un appelant, faire quelque chose, puis revenir en arrière à nouveau, chaque fois que sauter tous les appels inbetween.

Je fais cela en modifiant manuellement l'adresse de base de la pile (réglage %ebp) et de sauter à une adresse de l'étiquette. Il fonctionne totalement, avec gcc et icc les deux, sans corruption de pile du tout. Le jour cela a fonctionné était une journée fraîche.

Maintenant, je prends le même programme et réécrivant en C, et il ne fonctionne pas. Plus précisément, il ne fonctionne pas avec gcc v4.0.1 (Mac OS). Une fois que je saute sur le nouveau cadre de la pile (avec le pointeur de base de la pile correctement réglée), les instructions suivantes exécutent, être juste avant un appel à fprintf. La dernière instruction se bloque ici la liste, NULL déréférencement:

lea    0x18b8(%ebx), %eax
mov    (%eax), %eax
mov    (%eax), %eax

Je l'ai fait une mise au point, et je l'ai compris que en réglant le registre de %ebx manuellement lorsque je passe des cadres de pile (en utilisant une valeur j'ai observé avant de quitter la fonction en premier lieu), je corriger le bug. J'ai lu que cette traite de registre avec « position code indépendant » dans gcc.

Quelle est la position du code indépendant? Comment fonctionne la position de code indépendant? Pour ce qui est ce pointage de registre?

Était-ce utile?

La solution

PIC est un code qui est déplacé de façon dynamique lors de son chargement. Le code qui est non-PIC a sauter et adresses appel est réglé au moment de la liaison. PIC a une table qui fait référence à tous les endroits où ces valeurs existent, comme un .dll.

Lorsque l'image est chargée, le chargeur va mettre à jour dynamiquement ces valeurs. D'autres systèmes de référence une valeur de données qui définit une « base » et l'adresse cible est décidée en effectuant des calculs sur la base. La base est généralement fixé par le chargeur à nouveau.

Enfin, d'autres systèmes utilisent divers trampolines qui font appel à des décalages connus relatifs. Les décalages relatifs contiennent du code et / ou des données qui sont mises à jour par un chargeur.

Il existe différentes raisons pour lesquelles différents régimes sont choisis. Certains sont rapides lorsqu'il est exécuté, mais plus lent à charger. Certains sont rapides à charger, mais ont moins de performances d'exécution.

Autres conseils

points de EBX au tableau mondial de décalage. Voir cette référence à propos de PIC sur i386 . Le lien explique ce PIC est une façon dont EBX est utilisé.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top