summaryrefslogtreecommitdiff
path: root/testcase/backtrace.c
blob: dc07ec216d6192162fb09e6de6330529d92a55d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <execinfo.h>
#include <elfutils/libdwfl.h>

#define MAX_STACK_FRAMES 64
static void *stack_traces[MAX_STACK_FRAMES];

void print_trace() {
  int stack_depth = backtrace(stack_traces, MAX_STACK_FRAMES);
  Dwfl_Callbacks callbacks = {
    .find_elf = dwfl_linux_proc_find_elf,
    .find_debuginfo = dwfl_standard_find_debuginfo,
    .debuginfo_path = NULL
  };

  Dwfl *dwfl = dwfl_begin(&callbacks);
  dwfl_linux_proc_report(dwfl, getpid());
  dwfl_report_end(dwfl, NULL, NULL);

  for (int i = 0; i < stack_depth; ++i) {
    const char *modname;
    const char *symname;
    GElf_Off offset;
    Dwfl_Module *mod = dwfl_addrmodule(dwfl, (uintptr_t)stack_traces[i]);
    Dwfl_Line *line = dwfl_module_getsrc(mod, (uintptr_t)stack_traces[i]);
    const char *src;
    int lineno, colno;

    if (line) {
      src = dwfl_lineinfo(mod, line, &lineno, &colno, &modname, &symname);
      printf("%s (%d) %s\n", src, lineno, symname);
    }
  }

  dwfl_end(dwfl);
}

void foo() {
  print_trace();
}

void bar() {
  foo();
}

int main(int argc, char **argv) {
  bar();
  return 0;
}