Je me pose la question de savoir si il est possible, depuis une
fonction quelconque, de retrouver l'adresse de l'objet qui a appel=E9
cette fonction. Par exemple, dans le code suivant :
void bar() {
// ... some magic code ...
}
class A {
public:
void foo() {bar();}
};
int main(int argc, char** argv) {
A a;
a.foo();
return 0;
}
je voudrais que bar() soit capable de m'=E9crire un truc du genre
"caller address: 0x1234abcd", o=F9 0x1234abcd est l'adresse de 'a' (i.e.
ce que me sortirait un "cout << this << endl;" depuis n'importe quelle
fonction de A).
Une contrainte forte (sinon la solution est triviale !), c'est que je
ne veux surtout pas modifier la signature de bar(), ni imposer
d'autres contraintes (ou alors le moins possible ?) sur A.
Bon, avant d'en dire plus, quelques pr=E9cisions :
- d'abord, c'est pas un vrai cas d'usage, c'est principalement pour
satisfaire ma curiosit=E9 (pas la peine de me dire que c'est du code pas
propre et tout, quoi :-) ) ;
- ensuite, j'utilise g++/Linux et une solution sp=E9cifique =E0 g++ (ce
qui me semble in=E9vitable, au moins sur la piste o=F9 je suis parti de
manipulation de la pile d'appel...) m'ira tr=E8s bien ;
- finalement, je suis bien conscient que rien ne me dit que bar() est
appel=E9e depuis un objet et qu'il y a sans doute plein d'autres cas
plus compliqu=E9s, mais pour la discussion on dira que =E7a n'est pas pire
que mon exemple...
J'ai trouv=E9 les fonctions backtrace(), backtrace_symbols() de g++ qui
me permettent d'inspecter la pile d'appels, ce qui est d=E9j=E0 =E7a. En
m'inspirant, par exemple, du code ici :
http://stackoverflow.com/questions/77005/how-to-generate-a-stacktrace-when-=
my-gcc-c-app-crashes
j'arrive facilement =E0 faire en sorte que bar() =E9crive "caller:
A::foo()".
Je me dis que je devrais pouvoir aller plus loin et exploiter
l'adresse de retour qui est fournie par backtrace() (ce qui doit =EAtre
la m=EAme que __builtin_return_address, je suppose ?) pour essayer de
retrouver le pointeur "this", vu qu'il doit =EAtre quelque part dans les
arguments de A::foo() (en dernier avec g++, je crois - mais vu que
A::foo() n'a pas d'arguments, =E7a doit aussi =EAtre le premier ici...).
Je n'y connais pas grand chose en compilation, assembleur... et j'ai
beaucoup de mal =E0 suivre ce que j'arrive =E0 trouver sur internet =E0
propos de esp, esb et autres registres, mais il me semble bien
qu'autour de la __builtin_return_address ou de la
__builtin_frame_address, il doit y avoir l'adresse des param=E8tres de
la fonction, non ?
Malheureusement, j'ai essay=E9 d'afficher la valeur de 'this', ainsi que
les valeurs du pointeur fourni par backtrace() plus ou moins de 0 =E0
100, pour la frame courante, la frame parente, en d=E9r=E9f=E9ren=E7ant deu=
x
fois (si le pointeur indique l'adresse d'un registre qui lui-m=EAme
contient l'adresse de 'this' ?)... Mais toutes les tortures auxquelles
j'ai pu penser n'ont jamais r=E9ussies =E0 faire avouer =E0 ce pointeur la
valeur de 'this'. Zut, peste et crotte, me voila bien emb=EAt=E9 !
Donc, est-ce que quelqu'un =E0 une id=E9e de si, et comment, je peux
exploiter cette adresse pour retrouver les arguments d'une fonction
quelconque dans la pile, et en particulier 'this' ? Ou est-ce que
quelqu'un =E0 une id=E9e de comment faire ce que je demande (si c'est
possible...) ?
Et là on met le doigt dans l'usine à gaz (qui s'appelle dwarf). Il y a bien une libdwarf pour aider, àhttp://reality.sgiweb.org/davea/d warf.html, mais manifestement c'est pas fait pour les premiers communiants... Il faut vraiment en avoir besoin pour s'y plonger (ça n'a jamais été mon cas, donc je ne peux pas t' en dire plus).
D'accord, je vois. Et c'est ce que je ne voulais absolument pas faire (au sens où pour satisfaire ma curiosité, je n'ai pas envie d'aller jusque là !).
Merci pour tes explications, je crois que je comprends mieux. -- Rémi
On Nov 9, 4:23 pm, Alain Ketterlin <al...@dpt-info.u-strasbg.fr>
wrote:
[snip]
Et là on met le doigt dans l'usine à gaz (qui s'appelle dwarf).
Il y a bien une libdwarf pour aider, àhttp://reality.sgiweb.org/davea/d warf.html, mais manifestement c'est pas
fait pour les premiers communiants... Il faut vraiment en avoir besoin
pour s'y plonger (ça n'a jamais été mon cas, donc je ne peux pas t' en
dire plus).
D'accord, je vois. Et c'est ce que je ne voulais absolument pas faire
(au sens où pour satisfaire ma curiosité, je n'ai pas envie d'aller
jusque là !).
Merci pour tes explications, je crois que je comprends mieux.
--
Rémi
Et là on met le doigt dans l'usine à gaz (qui s'appelle dwarf). Il y a bien une libdwarf pour aider, àhttp://reality.sgiweb.org/davea/d warf.html, mais manifestement c'est pas fait pour les premiers communiants... Il faut vraiment en avoir besoin pour s'y plonger (ça n'a jamais été mon cas, donc je ne peux pas t' en dire plus).
D'accord, je vois. Et c'est ce que je ne voulais absolument pas faire (au sens où pour satisfaire ma curiosité, je n'ai pas envie d'aller jusque là !).
Merci pour tes explications, je crois que je comprends mieux. -- Rémi