trailer - c++ backtrace




Wie macht man backtrace()/backtrace_symbols() druckt die Funktionsnamen? (3)

Das Linux-spezifische backtrace() und backtrace_symbols() ermöglicht es Ihnen, eine Aufruf-Ablaufverfolgung des Programms zu erstellen. Es druckt jedoch nur Funktionsadressen, nicht ihre Namen für mein Programm. Wie kann ich sie dazu bringen, die Funktionsnamen ebenfalls auszudrucken? Ich habe versucht, das Programm mit -g sowie -ggdb . Der folgende Testfall druckt das nur aus:

    BACKTRACE ------------
    ./a.out() [0x8048616]
    ./a.out() [0x8048623]
    /lib/libc.so.6(__libc_start_main+0xf3) [0x4a937413]
    ./a.out() [0x8048421]
    ----------------------
    

Ich möchte, dass die ersten beiden Elemente auch die Funktionsnamen foo und main foo

Code:

#include <execinfo.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>

static void full_write(int fd, const char *buf, size_t len)
{
        while (len > 0) {
                ssize_t ret = write(fd, buf, len);

                if ((ret == -1) && (errno != EINTR))
                        break;

                buf += (size_t) ret;
                len -= (size_t) ret;
        }
}

void print_backtrace(void)
{
        static const char start[] = "BACKTRACE ------------\n";
        static const char end[] = "----------------------\n";

        void *bt[1024];
        int bt_size;
        char **bt_syms;
        int i;

        bt_size = backtrace(bt, 1024);
        bt_syms = backtrace_symbols(bt, bt_size);
        full_write(STDERR_FILENO, start, strlen(start));
        for (i = 1; i < bt_size; i++) {
                size_t len = strlen(bt_syms[i]);
                full_write(STDERR_FILENO, bt_syms[i], len);
                full_write(STDERR_FILENO, "\n", 1);
        }
        full_write(STDERR_FILENO, end, strlen(end));
    free(bt_syms);
}
void foo()
{
    print_backtrace();
}

int main()
{
    foo();
    return 0;
}

Der exzellente Libbacktrace von Ian Lance Taylor löst dieses Problem. Es behandelt Stackabwickeln und unterstützt sowohl normale ELF-Symbole als auch DWARF-Debugging-Symbole.

Libbacktrace erfordert nicht das Exportieren aller Symbole, was hässlich wäre, und ASLR bricht es nicht.

Libbacktrace war ursprünglich Teil der GCC-Distribution. Jetzt kann eine eigenständige Version auf Github gefunden werden:

https://github.com/ianlancetaylor/libbacktrace


Die Symbole stammen aus der dynamischen Symboltabelle; Sie benötigen die Option -rdynamic für gcc , die eine -rdynamic an den Linker -rdynamic , die sicherstellt, dass alle Symbole in der Tabelle platziert werden.

(Siehe die Link-Optionen- Seite des GCC-Handbuchs und / oder die Backtraces Seite des glibc-Handbuchs .)


die Antwort auf der Oberseite hat einen Fehler, wenn ret == -1 und errno ist EINTER sollten Sie es erneut versuchen, aber nicht ret wie kopiert (nicht um ein Konto nur für dieses zu machen, wenn Sie es nicht hart mögen)

static void full_write(int fd, const char *buf, size_t len)
{
        while (len > 0) {
                ssize_t ret = write(fd, buf, len);

                if ((ret == -1) {
                        if (errno != EINTR))
                                break;
                        //else
                        continue;
                }
                buf += (size_t) ret;
                len -= (size_t) ret;
        }
}




backtrace