2010-02-22 3 views
3

En regardant le désassemblage (avec une trace d'instruction) de ld.so installé dans Ubuntu 9.04, je jure que les données sont stockées sous le pointeur de la pile (c'est-à-dire au-delà de la pile). Cela me semble fou, mais c'est peut-être plus commun que je ne le pense. Est-ce que cela arrive souvent?Stocker des données sous le pointeur de la pile?

Voici ce que je vois:

ebp: 0xBF8269E8, esp: 0xBF8269DC

c98:  8b 45 f0    mov -0x10(%ebp),%eax 
c9b:  8d 14 06    lea (%esi,%eax,1),%edx 
c9e:  8b 83 28 03 00 00  mov 0x328(%ebx),%eax 
ca4:  3b 50 04    cmp 0x4(%eax),%edx 
+0

Pouvons-nous avoir un peu plus de contexte? La valeur stockée à -0x10 (% ebp) est-elle utilisée plus tard dans la fonction? Pourrait-il être un paramètre de fonction? – zildjohn01

Répondre

1

Ce que vous mène exactement à croire ce genre de choses est stockée sous le pointeur de la pile . Tout ce que je peux voir est un décalage négatif de ebp qui est le pointeur cadre.

Ceci est généralement utilisé comme un pointeur vers le prochain cadre de pile à partir du courant pour un certain nombre de raisons.

  • De chaque côté de ebp sont les paramètres transmis pour cette fonction (ci-dessus) et ebp habitants pour cette fonction (ci-après ebp). L'utilisation de -0x10(%ebp) signifie simplement que vous faites quelque chose avec une variable locale.
  • Il est facile de revenir à la précédente pile en chargeant %esp avec %ebp et en revenant.

Bien sûr, vous peut être frapper quelque chose ci-dessous %esp mais cela dépendra des données en cours de chargement, qui ne sont pas réellement montré dans votre échantillon.

Un « diagramme » peut aider:

 +------------------------+ 
    | Parameters passed to x | 
    +------------------------+ 
    | Return address   | 
%ebp +------------------------+ 
    | Locals for x   | 
%esp +------------------------+ 

Ma mémoire de c'est rouillé (l'instruction spécifique peut ne pas être exacte, mais ils devraient être assez bon pour indiquer le concept derrière elle), mais la fonction typique séquence d'appel est:

  • appelant pousse paramètres sur la pile (push, push, ...). L'appelant pousse le courant %ebp sur la pile (push %ebp).
  • l'appelant charge %ebp avec %esp% (mov %ebp, %esp).
  • appelant appelle callee (call XYZ). Callee alloue de l'espace aux locaux (sub %esp,N). Callee peut alors utiliser (%ebp+N) pour les paramètres, (%ebp-N) pour les locaux.

Et, pour le retour:

  • charges callee %esp avec %ebp (mov %esp, %ebp).
  • callee retourne à l'appelant (ret).
  • L'appelant affiche la précédente %ebp de la pile (pop %ebp). L'appelant nettoie la section des paramètres (add %esp,N).
+0

Merci. La plupart de cela je pense que je savais (bien que ce soit un bon résumé). Il est logique que vous alliez aussi bas que (% ebp-N) (ou peut-être N-4 puisqu'il y a un appel dedans), ce qui vous maintient dans les limites du pointeur de la pile en cours. Mais dans l'exemple que je cite, -0x10 (% ebp) regarderait dans la mémoire 4 octets au-dessous du pointeur actuel de pile (0xBF8269D8, tandis que esp est 0xBF8269DC). C'est quelque chose que je n'ai pas vu, et je voulais une vérification de santé mentale pour voir si cette trace représente quelque chose de raisonnable. – Duc

1

Les gestionnaires de signaux doivent pouvoir créer une trame de pile à tout moment. Par conséquent, vous devez toujours suivre le protocole de pile de votre ABI.

Sur PowerPC, un certain nombre d'octets (un demi-kilo-octet?) Sont réservés en dessous du pointeur de la pile. (Bien sûr, cela peut varier d'une plate-forme à l'autre.) Les gestionnaires de signaux doivent alors gaspiller autant d'espace pour ne pas interférer avec quoi que ce soit. L'avantage étant l'élimination du magasin + soustraire et ajouter des instructions qui créeraient un cadre pour de très petites fonctions de feuille.

Questions connexes