OVH Cloud OVH Cloud

Adesse retour des fonctions

9 réponses
Avatar
yarocco
Bonjour,
Je cherche comment sont enregistrer les adresses de retour des fonctions.
Exemple : on a une fonction qui en appelle une autre, pour retourner a
la premiere, en ASM, cela se traduit par un RET. Seulement, j'aimerais
savoir ou est stocke l'adresse qu'il va appeller lors du RET.
Je suppose qu'elle est sur la pile, mais comment il (il : le processeur
ou le compilo ??) gere ces adresses : y'a t-il une methode lors du
stockage pour qu'on puisse les retrouver lors d'un debug ou d'un dump de
la pile ??

J'espere avoir ete clair.
Merci d'avance

9 réponses

Avatar
AMcD®
yarocco wrote:
Bonjour,
Je cherche comment sont enregistrer les adresses de retour des
fonctions. Exemple : on a une fonction qui en appelle une autre, pour
retourner a la premiere, en ASM, cela se traduit par un RET.
Seulement, j'aimerais savoir ou est stocke l'adresse qu'il va
appeller lors du RET. Je suppose qu'elle est sur la pile, mais comment il
(il : le
processeur ou le compilo ??) gere ces adresses : y'a t-il une methode
lors du stockage pour qu'on puisse les retrouver lors d'un debug ou
d'un dump de la pile ??

J'espere avoir ete clair.
Merci d'avance



L'adresse de retour est empilée sur la pile. Lorsque la fonction retourne,
elle saute simplement à cette adresse de retour.

Par exemple

0100 call yo
0105 mov bx,10

quand t'apelles yo, 0105 est pushed dans la pile.

Lorsque t'arrives à la fin de yo, au ret, la valeur dans la pile pointée par
esp est popped dans eip et donc, tu reviens en 0105. Faut juste faire gaffe
que esp pointe au bon endroit.

--
AMcD®

http://arnold.mcdonald.free.fr/
Avatar
Pierre Maurette
yarocco a écrit :
Bonjour,
Je cherche comment sont enregistrer les adresses de retour des fonctions.
Exemple : on a une fonction qui en appelle une autre, pour retourner a
la premiere, en ASM, cela se traduit par un RET. Seulement, j'aimerais
savoir ou est stocke l'adresse qu'il va appeller lors du RET.
Je suppose qu'elle est sur la pile, mais comment il (il : le processeur
ou le compilo ??) gere ces adresses : y'a t-il une methode lors du
stockage pour qu'on puisse les retrouver lors d'un debug ou d'un dump de
la pile ??


La réponse n'est pas simple, d'abord parce qu'elle n'est pas simple,
ensuite parce qu'elle n'est pas unique.
Situons-nous en Windows/x86. L'adresse de retour est effectivement
déposée au sommet (sic) de la pile juste avant l'appel. Il est de la
responsabilité du programmeur de gérer la pile pour faire en sorte que
chaque empilement corresponde à un dépilement et que au moment du REt,
ce soit bien l'adresse de retour qui se situe en haut de la pile. En
fait, ce qui se pratique le plus souvent est plus compliqué. Au moment
de l'appel d'un sous-programme, on trouve au sommet (sic) de la pile les
paramètres passés (en fait des variables locales), l'adresse de retour,
puis de le place pour les variables locales. En fait, le compilateur
peut très bien placer ces dernières avant ou après l'adresse de retour.
Les premières instructions vont sauver le pointeur de pile ESP dans un
pointeur de pile annexe EBP, qui restera fixe dans la fonction (=
sous-programme). Ainsi, les paramètres, variables locale et adresse de
retour sont obtenus *dans la fonction* par un déplacement immuable par
rapport à EBP. Le mécanisme d'appel (éventuellement récursif) fait en
sorte que non seulement ESP mais également EBP est restauré au RET. Il
faut se prendre un peu la tête, mais tout ça se comporte très bien.
Chercher avec Google par "cadre de pile" ou "stack frame". L'assembleur
x86 met à la disposition des compilateurs des instructions de très haut
niveau, ENTER et LEAVE, destiné à faciliter cette gestion. Au moins une
des deux est trop puissante, donc trop couteuse, les cadres de pile se
codent très bien à la main.
--
Pierre
Avatar
adebaene
yarocco wrote:
Bonjour,
Je cherche comment sont enregistrer les adresses de retour des


fonctions.
Exemple : on a une fonction qui en appelle une autre, pour retourner


a
la premiere, en ASM, cela se traduit par un RET. Seulement,


j'aimerais
savoir ou est stocke l'adresse qu'il va appeller lors du RET.
Je suppose qu'elle est sur la pile, mais comment il (il : le


processeur
ou le compilo ??) gere ces adresses : y'a t-il une methode lors du
stockage pour qu'on puisse les retrouver lors d'un debug ou d'un dump


de
la pile ??



L'adresse de retour utilisée par le RET est placée sur la pile au
moment du CALL. La structure de la pile pour un appel de fonction est
"plus ou moins" standard (comprendre que le compilateur peut parfois
optimiser certaines parties). On appelle ca une "stack frame". Un coup
de Google dessus te donnera plein de renseignements sur le sujet.
C'est en détectant ces stack frames sur la pile qu'un debugger peut
afficher la call stack d'un programme en mode pas à pas. Tu noteras
qu'en mode release ou optimisé, le debugger peut parfois ne pas
retrouver les stack frame, et dans ce cas il ne peut pas remonter plus
haut dans la pile d'appels.

Arnaud
Avatar
Vincent Burel
"yarocco" wrote in message
news:41e7bee8$0$15692$
Bonjour,
Je cherche comment sont enregistrer les adresses de retour des fonctions.
Exemple : on a une fonction qui en appelle une autre, pour retourner a
la premiere, en ASM, cela se traduit par un RET. Seulement, j'aimerais
savoir ou est stocke l'adresse qu'il va appeller lors du RET.
Je suppose qu'elle est sur la pile, mais comment il (il : le processeur
ou le compilo ??) gere ces adresses : y'a t-il une methode lors du
stockage pour qu'on puisse les retrouver lors d'un debug ou d'un dump de
la pile ??



bon, je crois que tout le monde a expliqué le RET...
ajoutons alors la fenetre CALL STACK dans le menu View / Debug Window de
VC++ qui permet d'avoir la pile d'appel sous les yeux : très pratique.

VB
Avatar
yarocco
Vincent Burel wrote:
"yarocco" wrote in message
news:41e7bee8$0$15692$

Bonjour,
Je cherche comment sont enregistrer les adresses de retour des fonctions.
Exemple : on a une fonction qui en appelle une autre, pour retourner a
la premiere, en ASM, cela se traduit par un RET. Seulement, j'aimerais
savoir ou est stocke l'adresse qu'il va appeller lors du RET.
Je suppose qu'elle est sur la pile, mais comment il (il : le processeur
ou le compilo ??) gere ces adresses : y'a t-il une methode lors du
stockage pour qu'on puisse les retrouver lors d'un debug ou d'un dump de
la pile ??




bon, je crois que tout le monde a expliqué le RET...
ajoutons alors la fenetre CALL STACK dans le menu View / Debug Window de
VC++ qui permet d'avoir la pile d'appel sous les yeux : très pratique.

VB





Merci a tous.
Et je connais deja la fenetre de la pile :)
Mais la je voudrais faire un "hook" sur une procedure de TObject (dans
Delphi, c'est l'ancetre de tous les objets), donc je fais pointer
l'adresse de son call vers ma procedure, mais apres il faudrait quand
meme que je lui redonne la main et c'est ca que je ne sais pas faire, vu
que je ne sais pas ou retourner :)
Avatar
Vincent Burel
"yarocco" wrote in message
news:41e9bd8f$0$12293$
Vincent Burel wrote:
> "yarocco" wrote in message
> news:41e7bee8$0$15692$
>
>>Bonjour,
>>Je cherche comment sont enregistrer les adresses de retour des


fonctions.
>>Exemple : on a une fonction qui en appelle une autre, pour retourner a
>>la premiere, en ASM, cela se traduit par un RET. Seulement, j'aimerais
>>savoir ou est stocke l'adresse qu'il va appeller lors du RET.
>>Je suppose qu'elle est sur la pile, mais comment il (il : le processeur
>>ou le compilo ??) gere ces adresses : y'a t-il une methode lors du
>>stockage pour qu'on puisse les retrouver lors d'un debug ou d'un dump de
>>la pile ??
>
>
> bon, je crois que tout le monde a expliqué le RET...
> ajoutons alors la fenetre CALL STACK dans le menu View / Debug Window de
> VC++ qui permet d'avoir la pile d'appel sous les yeux : très pratique.
>
> VB
>
>

Merci a tous.
Et je connais deja la fenetre de la pile :)



Ben oui ! :-)

Mais la je voudrais faire un "hook" sur une procedure de TObject (dans
Delphi, c'est l'ancetre de tous les objets),



ha ouai, et pourquoi pas surcharger .... ou je ne sais pas , faudrait
demander à des kador de Delphi...

donc je fais pointer
l'adresse de son call vers ma procedure, mais apres il faudrait quand
meme que je lui redonne la main et c'est ca que je ne sais pas faire, vu
que je ne sais pas ou retourner :)



peut-être votre prototype de procedure n'est pas bon, vérifier la convention
d'appel de votre procédure, qu'elle corresponde à celle des methode de
l'objet TObject. Sinon tracez l'appelle à la procédure initiale de TObject
et regardez comment donc le retour est organisé... notons l'éxistence de la
fenêtre Disassembly dans le menu View / Debug Window de VC++ qui vous
permettra de passer sur le code ASM en mode debug / trace... :-)

VB
Avatar
Pierre Maurette
yarocco a écrit :
[...]
Merci a tous.
Et je connais deja la fenetre de la pile :)
Mais la je voudrais faire un "hook" sur une procedure de TObject (dans
Delphi, c'est l'ancetre de tous les objets), donc je fais pointer
l'adresse de son call vers ma procedure, mais apres il faudrait quand
meme que je lui redonne la main et c'est ca que je ne sais pas faire, vu
que je ne sais pas ou retourner :)


Sous Delphi (et dans d'autres langages), durant toute la procédure,
l'adresse de retour, celle que le RET trouvera, est en [EBP + 4]. Toute
procédure (que "Optimisation" et/ou "Cadres de pile" soient ou non
cochés) commence par:
push ebp
mov ebp, esp
(EBP ne doit normalement pas changer au cours de la procédure, c'est par
rapport à lui que sont accédées variables locales et paramètres).
Encore faut-il connaître l'adresse de la méthode hookée, pour la placer
en [EBP + 4]. Normalement, c'est faisable, quoi que pas toujours simple,
même pour des méthodes virtuelles ou dynamiques. Mais vous ne posez pas
la question ...
Je trouve votre problème intéressant, mais on manque sérieusement
d'éléments. Comment atterrissez-vous dans votre procédure ? Les
fonctions API comme SteWindowsHookEx() ne sont pas utilisables ici, et
ne posent pas se genre de problème.
Ce serait gentil de préciser votre problème. Vous pouvez même poster un
bout de code (en privé si vous voulez, mon email est valide). J'ai
Delphi 7 installé, il me semble avoir lu qu'à partir de 8 il n'y aplus
d'asm, donc c'est baisé.
C'est marrant, pouvoir obtenir rapidement l'ensemble des adresses de la
Call Stack est un classique en ... débogage crapuleux ;-).
--
Pierre
Avatar
Pierre Maurette
Vincent Burel a écrit :
[...]
peut-être votre prototype de procedure n'est pas bon, vérifier la convention
d'appel de votre procédure, qu'elle corresponde à celle des methode de
l'objet TObject. Sinon tracez l'appelle à la procédure initiale de TObject
et regardez comment donc le retour est organisé... notons l'éxistence de la
fenêtre Disassembly dans le menu View / Debug Window de VC++ qui vous
permettra de passer sur le code ASM en mode debug / trace... :-)


Delphi propose une fenêtre CPU (menu "Voir" ou Ctrl + Alt + C)
excellente. Malheureusement et étrangement la version gratuite ne
propose pas les registres FPU (et autres MMX, SSE etc.).
Une option du lieur permet d'inclure les "Informations de débogage
TD32", qui est librement téléchargeable.
--
Pierre
Avatar
yarocco
Pierre Maurette wrote:
yarocco a écrit :
[...]

Merci a tous.
Et je connais deja la fenetre de la pile :)
Mais la je voudrais faire un "hook" sur une procedure de TObject (dans
Delphi, c'est l'ancetre de tous les objets), donc je fais pointer
l'adresse de son call vers ma procedure, mais apres il faudrait quand
meme que je lui redonne la main et c'est ca que je ne sais pas faire,
vu que je ne sais pas ou retourner :)



Sous Delphi (et dans d'autres langages), durant toute la procédure,
l'adresse de retour, celle que le RET trouvera, est en [EBP + 4]. Toute
procédure (que "Optimisation" et/ou "Cadres de pile" soient ou non
cochés) commence par:
push ebp
mov ebp, esp
(EBP ne doit normalement pas changer au cours de la procédure, c'est par
rapport à lui que sont accédées variables locales et paramètres).



Ok, Merci pour ces details


Je trouve votre problème intéressant, mais on manque sérieusement
d'éléments. Comment atterrissez-vous dans votre procédure ? Les
fonctions API comme SteWindowsHookEx() ne sont pas utilisables ici, et
ne posent pas se genre de problème.
Ce serait gentil de préciser votre problème. Vous pouvez même poster un
bout de code (en privé si vous voulez, mon email est valide). J'ai
Delphi 7 installé, il me semble avoir lu qu'à partir de 8 il n'y aplus
d'asm, donc c'est baisé.
C'est marrant, pouvoir obtenir rapidement l'ensemble des adresses de la
Call Stack est un classique en ... débogage crapuleux ;-).



Justement, j'essayes aussi de recuperer la pile de mon prog en code (pas
en debug simple :)) mais j'arrive pas :(
Sinon, pour voir ce que l'on avait fait a l'epoque (enfin y'a pas trop
longtps quand mm:)) :
http://www.phidels.com/php/forum/forum.php3?forumtable=posts&mode=showpost&postidu633
La, je voulais essayer une nouvelle technique mais je bloque completement.
Au fait, je travaille sous D7, D8 : meme pas essaye et D9 est vraiment
trop lourd pour mon PC.