diff options
author | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2016-10-04 05:27:04 -0500 |
---|---|---|
committer | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2016-10-04 05:27:04 -0500 |
commit | 0912f6890925a9e9aa552fb841f9162ea6bd3d70 (patch) | |
tree | 43800f360d677b163f745badc11bde81ea810b3c /backtrace.c | |
parent | 6b43a6a6c1f238b5ddea05964e19de86fe2fcda1 (diff) | |
download | gcompat-0912f6890925a9e9aa552fb841f9162ea6bd3d70.tar.gz gcompat-0912f6890925a9e9aa552fb841f9162ea6bd3d70.tar.bz2 gcompat-0912f6890925a9e9aa552fb841f9162ea6bd3d70.tar.xz gcompat-0912f6890925a9e9aa552fb841f9162ea6bd3d70.zip |
Add some new interfaces
Diffstat (limited to 'backtrace.c')
-rw-r--r-- | backtrace.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/backtrace.c b/backtrace.c new file mode 100644 index 0000000..2ceb334 --- /dev/null +++ b/backtrace.c @@ -0,0 +1,44 @@ +#include <dlfcn.h> +#include <stddef.h> +#include <stdlib.h> + +#define _frame_level(addr_buf, curr, frame, size) \ + if(__builtin_frame_address(frame) != NULL && (curr = __builtin_return_address(frame)) > 0x1000 && frame <= size) addr_buf[frame] = curr; \ + else return size; + +int backtrace(void **addr_buf, int size) +{ + void *curr; + _frame_level(addr_buf, curr, 0, size) + _frame_level(addr_buf, curr, 1, size) + _frame_level(addr_buf, curr, 2, size) + _frame_level(addr_buf, curr, 3, size) + _frame_level(addr_buf, curr, 4, size) + _frame_level(addr_buf, curr, 5, size) + _frame_level(addr_buf, curr, 6, size) + _frame_level(addr_buf, curr, 7, size) + _frame_level(addr_buf, curr, 8, size) + _frame_level(addr_buf, curr, 9, size) + return 9; +} + +char **backtrace_symbols(void * const *addr_buf, int size) +{ + char **result = calloc(sizeof(char *), size); + if(result == NULL) return result; + + for(int next = 0; next < size; next++) + { + Dl_info info; + int err = dladdr(addr_buf[next], &info); + + if(err != 0) + { + result[next] = "??:0"; + } else { + result[next] = info.dli_sname; + } + } + + return result; +} |