171363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes#include <corkscrew/backtrace.h>
204607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes#include <corkscrew/symbol_table.h>
371363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes#include <stdio.h>
471363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes#include <stdlib.h>
571363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes
671363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughesvoid do_backtrace() {
771363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes  const size_t MAX_DEPTH = 32;
871363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes  backtrace_frame_t* frames = (backtrace_frame_t*) malloc(sizeof(backtrace_frame_t) * MAX_DEPTH);
971363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes  ssize_t frame_count = unwind_backtrace(frames, 0, MAX_DEPTH);
1071363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes  fprintf(stderr, "frame_count=%d\n", (int) frame_count);
1171363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes
1271363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes  backtrace_symbol_t* backtrace_symbols = (backtrace_symbol_t*) malloc(sizeof(backtrace_symbol_t) * frame_count);
1371363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes  get_backtrace_symbols(frames, frame_count, backtrace_symbols);
1471363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes
1571363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes  for (size_t i = 0; i < (size_t) frame_count; ++i) {
1671363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes    char line[MAX_BACKTRACE_LINE_LENGTH];
1771363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes    format_backtrace_line(i, &frames[i], &backtrace_symbols[i],
1871363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes                          line, MAX_BACKTRACE_LINE_LENGTH);
1904607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes    if (backtrace_symbols[i].symbol_name != NULL) {
2004607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes      // get_backtrace_symbols found the symbol's name with dladdr(3).
2104607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes      fprintf(stderr, "  %s\n", line);
2204607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes    } else {
2304607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes      // We don't have a symbol. Maybe this is a static symbol, and
2404607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes      // we can look it up?
2504607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes      symbol_table_t* symbols = NULL;
2604607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes      if (backtrace_symbols[i].map_name != NULL) {
2704607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes        symbols = load_symbol_table(backtrace_symbols[i].map_name);
2804607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes      }
2904607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes      const symbol_t* symbol = NULL;
3004607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes      if (symbols != NULL) {
3104607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes        symbol = find_symbol(symbols, frames[i].absolute_pc);
3204607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes      }
3304607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes      if (symbol != NULL) {
3404607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes        uintptr_t offset = frames[i].absolute_pc - symbol->start;
3504607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes        fprintf(stderr, "  %s (%s%+d)\n", line, symbol->name, offset);
3604607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes      } else {
3704607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes        fprintf(stderr, "  %s (\?\?\?)\n", line);
3804607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes      }
396b659aec2ef83504b836de211f072d79ad2edc3dElliott Hughes      free_symbol_table(symbols);
4004607b8aa91051bb43cd652dca1cef1579ed5dadElliott Hughes    }
4171363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes  }
4271363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes
4371363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes  free_backtrace_symbols(backtrace_symbols, frame_count);
4471363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes  free(backtrace_symbols);
4571363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes  free(frames);
4671363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes}
4771363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes
4871363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes__attribute__ ((noinline)) void g() {
4971363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes  fprintf(stderr, "g()\n");
5071363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes  do_backtrace();
5171363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes}
5271363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes
5371363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes__attribute__ ((noinline)) int f(int i) {
5471363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes  fprintf(stderr, "f(%i)\n", i);
5571363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes  if (i == 0) {
5671363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes    g();
5771363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes    return 0;
5871363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes  }
5971363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes  return f(i - 1);
6071363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes}
6171363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes
6271363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughesint main() {
6371363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes  return f(5);
6471363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes}
65