J'ai écrit un programme "dangereux" en C++ qui saute d'une pile à l'autre. L'objectif est de passer du niveau le plus bas d'une pile d'appels à un appelant, de faire quelque chose, puis de redescendre à chaque fois en sautant tous les appels entre les deux. Je le fais en changeant manuellement l'adresse de base de la pile (réglage %ebp
) et en sautant à une adresse d'étiquette. Cela fonctionne totalement, avec gcc et icc à la fois, sans aucune corruption de pile du tout. Le jour où cela a fonctionné était une journée fraîche.Que fait le registre PIC (% ebx)?
Maintenant, je prends le même programme et le réécrit en C, et cela ne fonctionne pas. Plus précisément, il ne fonctionne pas avec gcc v4.0.1 (Mac OS). Une fois que je suis passé au nouveau cadre de pile (avec le pointeur de base de la pile correctement défini), les instructions suivantes s'exécutent, juste avant un appel à fprintf
. La dernière instruction ci-tombe en panne ici, déréférencement NULL:
lea 0x18b8(%ebx), %eax
mov (%eax), %eax
mov (%eax), %eax
Je l'ai fait un peu de débogage, et je l'ai compris que le registre en mettant %ebx
manuellement lorsque je passe des cadres de pile (en utilisant une valeur j'ai observé avant de partir la fonction en premier lieu), je répare le bug. J'ai lu que ce registre traite du "code indépendant de la position" dans gcc.
Qu'est-ce qu'un code indépendant de la position? Comment fonctionne le code indépendant de la position? À quoi ce registre pointe-t-il? PIC est le code qui est déplacé dynamiquement lorsqu'il est chargé.
Vous pouvez considérer setjmp/longjmp pour obtenir cette fonctionnalité sans avoir à utiliser directement% ebx. –
En général, oui, vous avez raison. Dans ce cas, je dois pouvoir passer à un appelant, exécuter une autre fonction, puis revenir à l'appelé. Avec setjmp/longjmp, la pile de l'appelé serait écrasée par l'autre fonction. –