2015-01-07 13 views
8

Ich mache einen Stack-Trace an einem bestimmten Punkt in meinem Programm. Einmal mit libc 's backtrace_symbols() Funktion und einmal mit unw_get_proc_name() von libunwind.Verschiedene Offset in libc's backtrace_symbols() und libunwind's unw_get_proc_name()

backtrace_symbols() Ausgabe:

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

unw_get_proc_name() -Ausgabe:

ip: 0x7f6b47ce9004, offset: 0x458e4 

Hier sehen Sie, dass die Befehlszeiger Adresse (0x7f6b47ce9004) gleich und richtig ist . Die Funktion Offset 0x97004 von backtrace_symbols() auch korrekt ist, aber nicht, den ich von unw_get_proc_name get() (0x458e4).

Hat jemand eine Ahnung, was hier vor sich geht und was diesen Unterschied in Offsets verursachen könnte?

Beiden Verfahren verwenden einen ähnlichen Code wie die folgenden Beispiele:

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

Sie überprüfen nicht den Rückgabewert von unw_get_proc_name. Vielleicht ist es nicht erfolgreich und gibt einen Fehlercode zurück?Es scheint nicht, aber IMO sollten Sie noch. Außerdem zeigen Sie nicht den Printf für Backtrace(). Die für libunwind könnte vorschlagen, dass Sie Ihre printfs falsch beschriftet haben. – Krzak

Antwort

1

glaube ich unw_get_proc_name compute von einem Offset unbenannter interner Rahmen

Zum Beispiel:

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

Hinweis gibt es eine variable Deklaration innerhalb Schleifenblock. In diesem Fall (und abhängig von der Optimierungsebene) kann der Compiler einen Rahmen (und zugehörige Abwicklungsinformationen) für die Schleife erstellen. Folglich unw_get_proc_name berechnen Offset von dieser Schleife anstelle von Beginn der Funktion.

Dies ist in unw_get_proc_name Manpage erklärt:

Beachten Sie, dass es auf einigen Plattformen keine zuverlässige Möglichkeit ist zwischen Prozedurnamen und gewöhnlichen Etiketten zu unterscheiden. Wenn das Symbol Informationen aus einem Programm entfernt wurde, sind die Prozedurnamen möglicherweise vollständig nicht verfügbar oder sind möglicherweise auf die über eine dynamische Symboltabelle exportierten Prozesse beschränkt. In solchen Fällen gibt unw_get_proc_name() möglicherweise den Namen eines Etiketts oder einer vorhergehenden (in der Nähe befindlichen) Prozedur zurück.

Sie können versuchen, erneut zu testen, aber ohne Strippen Binärdatei (Da unw_get_proc_name nicht in der Lage ist Name Funktion zu finden, ich glaube, Ihre binäre gestrippt).

+0

Sehe diesen Satz in der Dokumentation und es macht Sinn. Aber warum ist backtrace() dann in der Lage, den realen Offset zu berechnen? Es scheint mir, dass mein Problem mit einer anderen Ursache zusammenhängt. – tur1ng

+0

Nun ... Ich stelle mir schließlich die gleiche Frage ... :-(Das einzige, was ich sicher bin, ist auf i386/x86_64, entweder Backtrace (mit 'libgcc_s.so') und' libunwind' basiert auf .heh_frame Informationen. Folglich ergeben sich diese Unterschiede aus der Implementierung von 'libunwind' und' libgcc_s'. Während 'libunwind' das Problem explizit aufdeckt, finde ich keinen Hinweis darauf in' libgcc_s.so'. – Jezz