/*
Preload library to print a stack trace when crashing.

Evan Jones <evanj@mit.edu>
March, 2008.

Based on a version written by Mark Hahn, SHARCnet, 2007.

Obtained from the beowulf mailing list:
http://article.gmane.org/gmane.comp.clustering.beowulf.general/18463

Compile:
gcc -fPIC backtrace.c -shared -o backtrace.so

Use:
LD_PRELOAD=./backtrace.so ./tester

Then use addr2line to translate addresses into file/line numbers.

TODO:
Use some DWARF library to translate addresses into file and line numbers.
Mark Hahn's code linked above uses libbfd.
*/

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

#define MAX_FRAMES (20)

static void handler(int sig) {
    static const char MESSAGE[] = "\n\nSTACK TRACE:\n";
    write(0, MESSAGE, sizeof(MESSAGE));

    void* array[MAX_FRAMES];
    size_t size = backtrace(array, sizeof(array)/sizeof(*array));
    backtrace_symbols_fd(array, size, 0);

    // Kill ourselves to propagate the error
    raise(sig);
}

static void __attribute__((constructor)) init() {
    struct sigaction sa;
    sa.sa_handler = handler;
    sa.sa_flags = SA_RESETHAND;

    sigaction(SIGABRT, &sa, 0);
    sigaction(SIGFPE, &sa, 0);
    sigaction(SIGINT, &sa, 0);
    sigaction(SIGSEGV, &sa, 0);
}
