2015-01-07 39 views
8

Eseguo una traccia di stack ad un certo punto nel mio programma. Una volta con la funzione libcbacktrace_symbols() e una volta con unw_get_proc_name() da libunwind.Offset diverso in backtrace_symbols() di libc e unw_get_proc_name() di libunwind()

backtrace_symbols() Uscita:

/home/jj/test/mylib.so(+0x97004)[0x7f6b47ce9004] 

unw_get_proc_name() Uscita:

ip: 0x7f6b47ce9004, offset: 0x458e4 

Qui si vede che il puntatore indirizzo istruzioni (0x7f6b47ce9004) è lo stesso e corretto . La funzione Offset 0x97004 da backtrace_symbols() è anche corretto, ma non quello che ricevo da unw_get_proc_name() (0x458e4).

Qualcuno ha idea di cosa sta succedendo qui e cosa potrebbe causare questa differenza negli offset?

Entrambi i metodi utilizzano un codice simile come i seguenti esempi:

backtrace():

void *array[10]; 
size_t size; 

size = backtrace(array, 10); 
backtrace_symbols_fd(array, size, STDERR_FILENO); 

libunwind:

unw_cursor_t cursor; 
unw_context_t context; 

unw_getcontext(&context); 
unw_init_local(&cursor, &context); 

while (unw_step(&cursor) > 0) { 
    unw_word_t offset, pc; 
    char  fname[64]; 

    unw_get_reg(&cursor, UNW_REG_IP, &pc); 

    fname[0] = '\0'; 
    (void) unw_get_proc_name(&cursor, fname, sizeof(fname), &offset); 

    printf ("%p : (%s+0x%x) [%p]\n", pc, fname, offset, pc); 
} 
+0

Non stai controllando il valore restituito da unw_get_proc_name. Forse non ha successo e restituisce un codice di errore?Non sembra, ma IMO dovresti ancora. Oltre a non mostrare la stampa per backtrace(). Quello per libunwind potrebbe suggerire di avere le vostre impronte errate. – Krzak

risposta

1

ritengo unw_get_proc_name calcolo compensata da un cornice interna senza nome.

Ad esempio:

void f() { 
    int i; 
    while (...) { 
    int j; 
    } 
} 

Avviso c'è una dichiarazione di variabili all'interno blocco del ciclo. In questo caso (e in base al livello di ottimizzazione), il compilatore può creare un frame (e le relative informazioni di unwind) per il ciclo. Di conseguenza, l'offset di calcolo unw_get_proc_name da questo ciclo anziché l'inizio della funzione.

Questo è spiegato nella pagina unw_get_proc_name man:

Si noti che su alcune piattaforme non v'è alcun modo affidabile per distinguere tra i nomi delle procedure e le etichette ordinari. Inoltre, se le informazioni sul simbolo sono state rimosse da un programma, i nomi delle procedure potrebbero essere completamente non disponibili o potrebbero essere limitati a quelli esportati tramite una tabella dei simboli dinamici . In questi casi, unw_get_proc_name() può restituire il nome di un'etichetta o una procedura precedente (vicina).

Puoi provare a testare di nuovo, ma senza togliere il tuo binario (Poiché unw_get_proc_name non è in grado di trovare il nome della funzione, credo che il tuo binario è spogliato).

+0

Hai visto quella frase nella documentazione e ha senso. Ma perché backtrace() è quindi in grado di calcolare l'offset reale? Mi sembra che il mio problema sia legato a un'altra causa. – tur1ng

+0

Beh ... Alla fine mi pongo la stessa domanda ... :-(L'unica cosa che sono sicuro è su i386/x86_64, o backtrace (usando 'libgcc_s.so') e' libunwind' si basa su .eh_frame informazioni. Di conseguenza, queste differenze derivano dall'implementazione di 'libunwind' e' libgcc_s'. Mentre 'libunwind' espone esplicitamente un problema, non trovo alcun riferimento a riguardo in' libgcc_s.so'. – Jezz