diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2017-11-10 20:51:45 +0100 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2017-11-10 20:51:45 +0100 |
commit | 4516416d3d0263891896488d2831f2dc4bdf79ee (patch) | |
tree | a32552685e808c4357b8fb2812aaaacd6c6d828a /btrace.c | |
parent | 50c27368522af16b7473e40a890ca9c29d71d63f (diff) |
xmonad.hs update, basic c stacktrace handler module
Diffstat (limited to 'btrace.c')
-rw-r--r-- | btrace.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/btrace.c b/btrace.c new file mode 100644 index 0000000..e9ade89 --- /dev/null +++ b/btrace.c @@ -0,0 +1,100 @@ +#include <execinfo.h> +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/wait.h> + +#define STACKTRACES 10 + + +static char *exec_path = NULL; + + +void bt_set_arg0(const char *arg0) { + if (!exec_path && arg0) { + exec_path = strdup(arg0); + } +} + +static void addr_to_array(char **strings, size_t siz, char **result) { + char *start, *end; + + for (size_t i = 0; i < siz; ++i) { + start = strchr(strings[i], '+'); + if (start) { + end = strchr(start, ')'); + start++; + if (end) + result[i] = strndup(start, end-start); + else + result[i] = strdup(""); + } + } +} + +void bt_print_trace (void) { + void *array[STACKTRACES]; + size_t bt_size; + char **strings; + size_t i; + char **addrs; + + bt_size = backtrace(array, STACKTRACES); + strings = backtrace_symbols(array, bt_size); + + printf("\n\n[1] Obtained %zd stack frames.\n", bt_size); + for (i = 0; i < bt_size; ++i) + printf("%s\n", strings[i]); + + /* addr2line -p -e ./btrace -f -i [addresses] */ + if (exec_path) { + addrs = (char**) calloc(bt_size, sizeof(*addrs)); + + addr_to_array(strings, bt_size, addrs); + printf("\n\n[2] Run for more info: addr2line -p -e %s -f -i", exec_path); + for (i = 0; i < bt_size; ++i) { + printf(" %s", addrs[i]); + } + printf("%s\n", ""); + + for (i = 0; i < bt_size; ++i) + if (addrs[i]) + free(addrs[i]); + free(addrs); + } + + free(strings); +} + +void bt_sighandler(int signum) { + bt_print_trace(); + switch (signum) { + case SIGTERM: + case SIGABRT: + case SIGSEGV: + exit(1); + } +} + + + + +/* A dummy function to make the backtrace more interesting. */ +void dummy_function(void) { + bt_print_trace(); +} + +#include <assert.h> +int main(int argc, char **argv) { + bt_set_arg0(argv[0]); + dummy_function(); + signal(SIGTERM, bt_sighandler); + signal(SIGABRT, bt_sighandler); + signal(SIGSEGV, bt_sighandler); + + //assert(0); + *(int*)(NULL) = 0; + return 0; +} |