2015-07-21 23 views
5

Ich verwende 'backtrce()' und 'backtrace_symbols_fd()' Funktionen in einem Signal-Handler, um eine Rückverfolgung zum Debuggen zu generieren (GDB nicht verfügbar).Kein Backtrace von SIGABRT Signal auf ARM-Plattform?

Sie auf x86-Desktop funktionieren (Ubuntu), aber auf dem Zielgerät (ARM-basiert) der Backtrace auf Abort-Signal (durch Doppelfreies Fehler) zeigt nur drei Frames: die Signal-Handler und zwei von innen libc, das ist nicht nützlich für das Debuggen unseres Codes! Rückverfolgung auf SEGV (z. B. unter Verwendung eines schlechten Zeigers) erzeugt eine gute Rückverfolgung.

Warum kann ich kein nützliches Backtrace auf ABRT-Signal auf ARM bekommen?

[Frage für Klarheit bearbeitet]

Hier ist ein einfaches Testprogramm, das das Problem veranschaulicht:

#include <execinfo.h> 
#include <signal.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 

// Signal hangler to catch seg fault: 
void handler_segv(int sig) { 
    // get void*'s for all entries on the stack 
    void *array[10]; 
    size_t size; 
    size = backtrace(array, 10); 
    fprintf(stderr, "Error: Signal %d; %d frames found:\n", sig, size); 
    // print out all the frames to stderr 
    backtrace_symbols_fd(array, size, STDERR_FILENO); 
    exit(1); 
} 


void crashme() 
{ 
    // Deliberate Error: Abort (double free): 
    char *test_ptr = malloc(1); 
    free(test_ptr); 
    free(test_ptr); 
    // Deliberate Error #2: Seg fault: 
    //char * p = NULL; 
    //*p = 0; 
} 

void foo() 
{ 
    fprintf(stdout, "---->About to crash...\n"); 
    crashme(); 
    fprintf(stdout, "---->Crashed (shouldn't get to here)...\n"); 
} 



// Main entry point: 
int main(int argc, char *argv[]) 
{ 
    fprintf(stdout, "Application start...\n"); 

    // Install signal handlers: 
    fprintf(stdout, "-->Adding handler for SIGSEGV and SIGABRT\n"); 
    signal(SIGSEGV, handler_segv); 
    signal(SIGABRT, handler_segv); 

    fprintf(stdout, "-->OK. Causing Error...\n"); 
    foo(); 
    fprintf(stdout, "-->Test finished (shouldn't get to here!)\n"); 
    return 0; 
} 

Dies wurde für x86 kompiliert wie folgt:

gcc -o test test-backtrace-simple.c -g -rdynamic 

Und für ARM:

arm-none-linux-gnueabi-gcc -o test-arm test-backtrace-simple.c -g -rdynamic -O0 -mapcs-frame -funwind-tables -fasynchronous-unwind-tables 

Ich habe verschiedene Compiler-Optionen für ARM verwendet, wie in anderen Posts beschrieben, die sich auf die Generierung von Backtraces auf ARM beziehen.

Wenn auf dem x86-Desktop ausgeführt werden, erzeugt er die erwartete Ausgabe mit vielen debug, endete in:

Error: Signal 6; 10 frames found: 
./test(handler_segv+0x19)[0x80487dd] 
[0xb7745404] 
[0xb7745428] 
/lib/i386-linux-gnu/libc.so.6(gsignal+0x4f)[0xb75b0e0f] 
/lib/i386-linux-gnu/libc.so.6(abort+0x175)[0xb75b4455] 
/lib/i386-linux-gnu/libc.so.6(+0x6a43a)[0xb75ed43a] 
/lib/i386-linux-gnu/libc.so.6(+0x74f82)[0xb75f7f82] 
./test(crashme+0x2b)[0x8048855] 
./test(foo+0x33)[0x804888a] 
./test(main+0xae)[0x8048962] 

(das heißt die Rückverfolgung von meinem Handler erzeugt, mit meiner Funktion am unteren Rande bezeichnet).

Wenn jedoch auf der ARM-Plattform laufen, die ich erhalten:

Application start... 
-->Adding handler for SIGSEGV and SIGABRT 
-->OK. Causing Error... 
---->About to crash... 
*** Error in `/opt/bin/test-arm': double free or corruption (fasttop): 0x015b6008 *** 
Error: Signal 6; 3 frames found: 
/opt/bin/test-arm(handler_segv+0x24)[0x8868] 
/lib/libc.so.6(__default_sa_restorer_v2+0x0)[0xb6e6c150] 
/lib/libc.so.6(gsignal+0x34)[0xb6e6af48] 

Der Backtrace() nur 3 Frames findet, und sie sind nur die Signal-Handler und etwas in libc (nicht sinnvoll)!

fand ich eine Mailingliste senden, die sagte:

If you link with the debugging C library, -lc_g, you'll get debugging info back past abort().

Diese relevant sein könnten, aber -lc_g auf meinem Compiler nicht funktioniert (ld: nicht finden können -lg_c).

Der Backtrace arbeitet auf ARM in Ordnung, wenn ich einen seg Fehler statt (zB Änderung crashme() Funktion zu verwenden, erzeugen "char * p = NULL; * p = 0;". Anstelle des Doppel frei

Beliebig Ideen oder Vorschläge für andere Möglichkeiten, um eine Rückverfolgung zu erhalten?

[--EDIT--]

ich einige MALLOC_CHECK_ Optionen ausprobiert, wie in den Kommentaren vorgeschlagen, aber der einzige Effekt war, ob der Abbruch zu ändern erzeugt wurde Hier ist die Ausgabe von drei Läufen auf dem ARM:

# MALLOC_CHECK_=0 /opt/bin/test-arm 
Application start... 
-->Adding handler for SIGSEGV and SIGABRT 
-->OK. Causing Error... 
---->About to crash... 
---->Crashed (shouldn't get to here)... 
-->Test finished (shouldn't get to here!) 


# MALLOC_CHECK_=1 /opt/bin/test-arm 
Application start... 
-->Adding handler for SIGSEGV and SIGABRT 
-->OK. Causing Error... 
---->About to crash... 
*** Error in `/opt/bin/test-arm': free(): invalid pointer: 0x015b2008 *** 
---->Crashed (shouldn't get to here)... 
-->Test finished (shouldn't get to here!) 


# MALLOC_CHECK_=2 /opt/bin/test-arm 
Application start... 
-->Adding handler for SIGSEGV and SIGABRT 
-->OK. Causing Error... 
---->About to crash... 
Error: Signal 6; 3 frames found: 
/opt/bin/test-arm(handler_segv+0x24)[0x8868] 
/lib/libc.so.6(__default_sa_restorer_v2+0x0)[0xb6e24150] 
/lib/libc.so.6(gsignal+0x34)[0xb6e22f48] 
# 

MALLOC_CHECK_ = 0: Keine Fehlermeldung (Doppel frei ignoriert!

)

MALLOC_CHECK_ = 1: Fehlermeldung, aber Programm läuft weiter

MALLOC_CHECK_ = 2: Fehlermeldung und ABRT Signal; nutzlos Backtrace erzeugt (dies ist das Standardverhalten!)

Mein Cross-Compiler Berichte: gcc Version 4.6.1 (Sourcery Codebench Lite 2.011,09-70) Zielgerät hat Version Linux-Kernel 3.8.8

+0

Haben Sie einen Blick auf: http://www.gnu.org/software/libc/manual/html_node/Backtraces.html Es gibt ein Beispiel, wie Backtracing ohne die Notwendigkeit für Gdb verwendet werden kann. Lass es mich wissen, wenn das hilft, danke. – KillaBytes

+0

@Kozmik ja, bereits mit ziemlich viel, dass (siehe Frage und beigefügten Beispielcode). Es funktioniert jedoch nicht korrekt für eine ABRT, die durch double free verursacht wird. – Jeremy

+1

Können Sie so kurz wie möglich angeben, wonach Sie fragen? Ich bin ein wenig verwirrt, wenn es darum geht, worum es wirklich geht. – KillaBytes

Antwort

0

Ich war das gleiche Problem haben. Ich habe die eingebaute Methode backtrace_symbols() ausprobiert und festgestellt, dass es gelegentlich funktioniert hat, aber meistens am Signalhandler gestoppt wurde. Dann habe ich rückwärts.hpp und deathhandler mit ähnlichen Ergebnissen versucht.

libubwind v1.2rc arbeitet für mich für SIGSEGV, SIGABRT eine Verwendung meiner eigenen Signal-Handler (kein spezieller Code in diesem, nur die Rückverfolgung von libunwind anfordern). Versuche es.

1

Es scheint, dass Sie genügend Forschung durchgeführt haben, um zu wissen, dass Sie die Schalter -funwind-tables und -fasynchronous-unwind-tables in Ihrer Compiler-Befehlszeile benötigen. In der Praxis scheint einer von ihnen ausreichend zu sein, aber ohne sie funktioniert Backtracing überhaupt nicht. Nun, das Problem mit Dingen wie SIGABRT ist, dass das Backtrace Stack-Frames durchlaufen muss, die von libc-Funktionen wie abort und gsignal generiert wurden und fehlschlägt, weil diese Bibliothek nicht mit einem dieser Switches erstellt wurde (in jeder mir bekannten Distribution). .

Während es nett wäre, die Betreuer von Sourcery CodeBench anzurufen, um ihre Distribution mit dieser Option zu erstellen, ist die einzige unmittelbare Lösung, libc selbst zu erstellen, mit einer oder beiden dieser Flags (meiner Erfahrung nach reicht es nur -funwind-tables)). Wenn Sie auch eine Stack-Trace benötigen, wenn Sie eine unbehandelte Exception abfangen (über std::set_terminate), müssen Sie auch libstdC++ neu erstellen.

An meinem Arbeitsplatz benötigten wir Backtraces für beide Fälle (SIGABRT und unbehandelte Ausnahmen), und da libstdC++ Teil der Toolchain ist, haben wir die Toolchain selbst neu aufgebaut. Das Tool crosstool-NG macht dies relativ einfach. Im Konfigurationshilfsprogramm ./ct-ng menuconfig haben wir den Abschnitt Target Options eingegeben und Target CFLAGS (setzt die Build-Variable TARGET_CFLAGS) auf -funwind-tables. Die resultierende Toolchain (genauer gesagt die Verwendung von libc und libstdC++ aus dem resultierenden Toolchain-Build) liefert uns in allen Fällen eine vollständige Rückverfolgung.

+0

Danke, das ist ein interessanter Winkel, den ich nicht berücksichtigt hatte. Leider bin ich nicht eine Position, um Ihre Lösung im Moment zu testen. – Jeremy

Verwandte Themen