2011-09-26 9 views
27

funzione backtrace dare set di backtrace come mapparlo con nome funzione/nome file/numero linea?Come mappare l'indirizzo della funzione per funzionare nei file * .so

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] 

Dalla pila precedente come posso ottenere il nome del file e il numero di riga? Ho seguito le cose, ma senza fortuna. Correggetemi se sbaglio :)

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 

Così, come posso risolvere sia in fase di esecuzione o inviati runtime? Grazie in anticipo ...

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 [email protected]@GLIBC_2.1 
    U [email protected]@GLIBC_2.1 
    U [email protected]@GLIBC_2.0 
    U [email protected]@GLIBC_2.7 
    U [email protected]@GLIBC_2.0 
    U [email protected]@GLIBC_2.0 
    U [email protected]@GLIBC_2.0 
    w [email protected]@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 scrivibile-privato, 1560K sola lettura-privato, 0K condiviso, e 376K riferimento

libtst.c:- 

void myfunc5(void){ 
int j, nptrs; 
#define SIZE 100 
void *buffer[100]; 
char **strings; 

nptrs = backtrace(buffer, SIZE); 
printf("backtrace() returned %d addresses\n", nptrs); 

strings = backtrace_symbols(buffer, nptrs); 
if (strings == 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; 
} 

Fatemi sapere se bisogno di più informazioni ...

+1

Hai compilato con informazioni di debug ('-g')? – qrdl

+0

@qrdl si è compilato con (-g) gcc -shared -ldl -fPIC libtst.c -o libtst.so -g – Thangaraj

+0

Quindi utilizzare 'backtrace_symbols()' per ottenere i nomi delle funzioni. Per ottenere i nomi delle funzioni e i numeri delle linee dagli indirizzi è possibile utilizzare le informazioni nane - controllare l'utilità 'dwarfdump' fornita con' libdwarf'. – qrdl

risposta

28

Provare a dare l'offset a addr2line, insieme al nome della sezione. Come questo:

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

Edit: A proposito, se non fosse chiaro, il 0x26887 viene da quello che hai fornito:

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

+0

addr2line -j .text -e libtst.so 0x26887 ??: 0 scusate senza fortuna. – Thangaraj

+0

Sei sicuro che il tuo indirizzo di base sia corretto? Assicurati di ottenere l'indirizzo di base della sezione eseguibile della libreria (controlla in/proc/pid/maps e trova la riga libtst.so con le autorizzazioni 'r-xp'). –

+0

Grazie, get it.addr2line -e libtst.so 0x767 /home/test/libtofun/libtst.c:16 – Thangaraj

6
objdump -x --disassemble -l <objfile> 

Questo dovrebbe scaricare, tra le altre cose, ogni istruzione compilata del codice macchina con la riga del file C da cui proviene.

+0

Non l'ho fatto, cosa significa. Quando provo con objdump e nm, l'indirizzo del simbolo è lo stesso. Ulteriori informazioni sarebbero utili. – Thangaraj

+0

Assicurati di compilare la libreria con i simboli di debug. – nmichaels

+0

Sì, ho compilato con l'opzione -g ... – Thangaraj

16

che ho avuto un'occhiata ai file backtrace.c e backtracesyms.c nel codice sorgente glibc (git: //sourceware.org/git/glibc.git, commit 2482ae433a4249495859343ae1fba408300f2c2e).

Supponendo di non aver frainteso/frainteso le cose: backtrace() sembra che fornisca solo gli indirizzi dei simboli così come sono in fase di esecuzione, il che credo significhi che è necessario l'indirizzo di caricamento della libreria come era da pmap o simile. Tuttavia, backtrace_symbols() ricalcola le cose in modo che gli indirizzi siano relativi all'ELF della libreria condivisa e non al processo in fase di esecuzione, il che è davvero conveniente. Significa che non hai bisogno di informazioni da pmap.

Quindi, se hai compilato con -g (o con -rdynamic), allora sei fortunato. Si dovrebbe essere in grado di effettuare le seguenti operazioni:

$ # 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 

Oppure, utilizzando gdb:

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

Inoltre, if you've stripped the library, but stashed off debug symbols for later use, allora è probabile che tu solo avere compensazioni ELF stampati da backtrace_syms() e nessun simbolo nomi (quindi non è proprio il caso della domanda originale): in questo caso, usare gdb è probabilmente più conveniente che usare altri strumenti da riga di comando. Supponendo che hai fatto questo, è necessario richiamare gdb in questo modo (per esempio):

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

e poi passare attraverso una sequenza simile come sopra, usando 'Info Line' e 'indirizzo info' seconda se hai solo offset di simboli ELF o nomi di simboli più offset.

+1

Poiché 'myfunc' è già un simbolo valido in GDB, puoi semplicemente fare 'info line * (myfunc + 0x2b)'. –

3

In fase di esecuzione con eu-addr2line (trova automaticamente le librerie e calcola gli offset):

//------------------------------------- 
#include <sys/types.h> 
#include <unistd.h> 

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"); 
} 

Stick un --debuginfo-path=... opzione se i file di debug sono da qualche altra parte (di pari passo con la build-id, ecc).

eu-addr2line è nel pacchetto elfutils della vostra distribuzione.

+1

Notate anche l'icona "regola orizzontale" nella scheda di modifica sopra. Puoi separare sezioni di una domanda con quella. Assicurati di vedere il? aiuto nella barra dei menu di modifica la prossima volta che modifichi una domanda o una risposta. Linee guida di editing molto utili che vanno dal semplice all'avanzato. – clearlight

Problemi correlati