Comment mapper une adresse de fonction pour fonctionner dans des fichiers * .so

backtrace function donne un ensemble de backtrace comment le mapper avec un nom de fonction / un nom de fichier / un numéro de ligne?

for ex:- backtrace() returned 8 addresses ./libtst.so(myfunc5+0x2b) [0xb7767767] ./libtst.so(fun4+0x4a) [0xb7767831] ./libtst.so(fun3+0x48) [0xb776787f] ./libtst.so(fun2+0x35) [0xb77678ba] ./libtst.so(fun1+0x35) [0xb77678f5] ./a.out() [0x80485b9] /lib/libc.so.6(__libc_start_main+0xe5) [0xb75e9be5] ./a.out() [0x80484f1] 

À partir de la stack ci-dessus, comment puis-je obtenir le nom du fichier et le numéro de ligne? J’ai suivi des choses, mais pas de chance. Corrigez-moi si je me trompe 🙂

 for ex:- ./libtst.so(fun2+0x35) [0xb77dc887] 0xb77dc887(fun2 addr+offset)-0xb77b6000 (lib starting addr) = 0x26887 (result) result is no way related to function in nm output. I used addr2line command:- addr2line -f -e libtst.so 0xb77dc887 ?? ??:0 

Alors, comment puis-je résoudre soit au moment de l’exécution, soit après l’exécution? Merci d’avance…

 nm:- 00000574 T _init 00000680 t __do_global_dtors_aux 00000700 t frame_dummy 00000737 t __i686.get_pc_thunk.bx 0000073c T myfunc5 000007e7 T fun4 00000837 T fun3 00000885 T fun2 000008c0 T fun1 00000900 t __do_global_ctors_aux 00000938 T _fini 000009b4 r __FRAME_END__ 00001efc d __CTOR_LIST__ 00001f00 d __CTOR_END__ 00001f04 d __DTOR_LIST__ 00001f08 d __DTOR_END__ 00001f0c d __JCR_END__ 00001f0c d __JCR_LIST__ 00001f10 a _DYNAMIC 00001ff4 a _GLOBAL_OFFSET_TABLE_ 00002030 d __dso_handle 00002034 A __bss_start 00002034 A _edata 00002034 b completed.5773 00002038 b dtor_idx.5775 0000203c B funptr 00002040 A _end U backtrace@@GLIBC_2.1 U backtrace_symbols@@GLIBC_2.1 U free@@GLIBC_2.0 U __isoc99_scanf@@GLIBC_2.7 U perror@@GLIBC_2.0 U printf@@GLIBC_2.0 U puts@@GLIBC_2.0 w __cxa_finalize@@GLIBC_2.1.3 w __gmon_start__ w _Jv_RegisterClasses pmap:- START SIZE RSS PSS DIRTY SWAP PERM MAPPING 08048000 4K 4K 4K 0K 0K r-xp /home/test/libtofun/a.out 08049000 4K 4K 4K 4K 0K r--p /home/test/libtofun/a.out 0804a000 4K 4K 4K 4K 0K rw-p /home/test/libtofun/a.out ... b7767000 4K 4K 4K 0K 0K r-xp /home/test/libtofun/libtst.so b7768000 4K 4K 4K 4K 0K r--p /home/test/libtofun/libtst.so b7769000 4K 4K 4K 4K 0K rw-p /home/test/libtofun/libtst.so .... Total: 1688K 376K 82K 72K 0K 

128K accessible en écriture, privée, 1560K en lecture seule, privée à 0K et référencée à 376K

 libtst.c:- void myfunc5(void){ int j, nptrs; #define SIZE 100 void *buffer[100]; char **ssortingngs; nptrs = backtrace(buffer, SIZE); printf("backtrace() returned %d addresses\n", nptrs); ssortingngs = backtrace_symbols(buffer, nptrs); if (ssortingngs == NULL) { perror("backtrace_symbols"); } for (j = 0; j < nptrs; j++) printf("%s\n", strings[j]); free(strings); } void fun4(){ char ip; char *fun = "fun4\0"; printf("Fun name %s\n",fun); scanf("%c",&ip); myfunc5(); } void fun3(){ char *fun = "fun3\0"; printf("Fun name %s\n",fun); funptr = fun4; funptr(); } void fun2(){ char *fun = "fun2\0"; printf("Fun name %s\n",fun); fun3(); } void fun1(){ char *fun = "fun1\0"; printf("Fun name %s\n",fun); fun2(); } main.c:- int main(){ char ip; funptr = &fun1; scanf("%c",&ip); funptr(); return 0; } 

Faites-moi savoir si besoin de plus d’informations …

    Essayez de donner l’offset à addr2line, ainsi que le nom de la section. Comme ça:

    addr2line -j .text -e libtst.so 0x26887

    Edit: Au fait, si ce n’était pas clair, le 0x26887 provient de ce que vous avez fourni:

    0xb77dc887(fun2 addr+offset)-0xb77b6000 (lib starting addr) = 0x26887 (result)

    J’ai consulté les fichiers backtrace.c et backtracesyms.c dans le code source de glibc (git: //sourceware.org/git/glibc.git, commit 2482ae433a4249495859343ae1fba408300f2c2e).

    En supposant que je n’ai pas mal lu ou mal compris les choses: backtrace () semble ne donner que les adresses de symboles telles qu’elles sont au moment de l’exécution, ce qui signifie que vous avez besoin de l’adresse de chargement de la bibliothèque telle qu’elle était de pmap ou similaire. Cependant, backtrace_symbols () recalcule les choses pour que les adresses soient relatives à la bibliothèque partagée ELF, et non au processus au moment de l’exécution, ce qui est vraiment pratique. Cela signifie que vous n’avez pas besoin des informations de pmap.

    Donc, si vous avez compilé avec -g (ou avec -rdynamic), alors vous avez de la chance. Vous devriez pouvoir faire ce qui suit:

     $ # get the address in the ELF so using objdump or nm $ nm libtst.so | grep myfunc 0000073c T myfunc5 $ # get the (hex) address after adding the offset $ # from the start of the symbol (as provided by backtrace_syms()) $ python -c 'print hex(0x0000073c+0x2b)' 0x767 $ # use addr2line to get the line information, assuming any is available addr2line -e libtst.so 0x767 

    Ou, en utilisant gdb:

     $ gdb libtst.so (gdb) info address myfunc Symbol "myfunc" is at 0x073c in a file comstackd without debugging. # (Faked output) (gdb) info line *(0x073c+0x2b) Line 27 of "foo.cpp" starts at address 0x767  and ends at 0x769 . # (Faked output) 

    De même, si vous avez vidé la bibliothèque, mais que vous avez caché les symboles de débogage pour une utilisation ultérieure , vous n’aurez probablement que des décalages ELF imprimés par backtrace_syms () et aucun nom de symbole (donc pas tout à fait le cas dans la question d’origine): Dans ce cas, utiliser gdb est sans doute plus pratique que d’autres outils en ligne de commande. En supposant que vous ayez fait cela, vous devrez appeler gdb comme suit (par exemple):

     $ gdb -s debug/libtst.debug -e libtst.so 

    Suivez ensuite la même séquence que ci-dessus, en utilisant les options “ligne info” et “adresse info”, selon que vous disposez uniquement de décalages de symbole ELF, de noms de symbole et de décalages.

     objdump -x --disassemble -l  

    Cela devrait, entre autres, vider chaque instruction compilée de code machine avec la ligne du fichier C dont elle provient.

    Au moment de l’exécution avec eu-addr2line (recherche automatiquement les bibliothèques et calcule les décalages):

     //------------------------------------- #include  #include  int i; #define SIZE 100 void *buffer[100]; int nptrs = backtrace(buffer, SIZE); for (i = 1; i < nptrs; ++i) { char syscom[1024]; syscom[0] = '\0'; snprintf(syscom, 1024, "eu-addr2line '%p' --pid=%d > /dev/stderr\n", buffer[i], getpid()); if (system(syscom) != 0) fprintf(stderr, "eu-addr2line failed\n"); } 

    Collez une --debuginfo-path=... si vos fichiers de débogage sont quelque part (correspond à l’identifiant de construction, etc.).

    eu-addr2line est dans le paquetage elfutils de votre dissortingbution.