1 #include <libunwind.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4
backtrace(int lower_bound)5 void backtrace(int lower_bound) {
6 unw_context_t context;
7 unw_getcontext(&context);
8
9 unw_cursor_t cursor;
10 unw_init_local(&cursor, &context);
11
12 char buffer[1024];
13 size_t offset = 0;
14
15 int n = 0;
16 while (1) {
17 n++;
18 if (unw_get_proc_name(&cursor, buffer, sizeof(buffer), &offset) == 0) {
19 fprintf(stderr, "Frame %d: %s+%p\n", n, buffer, (void*)(intptr_t)offset);
20 } else {
21 fprintf(stderr, "Frame %d: Could not get name for cursor\n", n);
22 }
23 if (n > 100) {
24 fprintf(stderr, "ERROR: Got %d frames, but expected at most 100\n", n);
25 abort();
26 }
27 int error = unw_step(&cursor);
28 if (error == 0) {
29 fprintf(stderr, "Note: Reached final frame after %d steps\n", n);
30 break;
31 } else if (error < 0) {
32 fprintf(stderr, "ERROR: Got error in unw_step: %d\n", error);
33 abort();
34 }
35 };
36
37 if (n < lower_bound) {
38 fprintf(stderr, "ERROR: Got %d frames, but expected at least %d\n", n, lower_bound);
39 abort();
40 }
41 }
42
test1(int i)43 __attribute__((noinline)) void test1(int i) {
44 fprintf(stderr, "starting %s\n", __func__);
45 backtrace(i);
46 fprintf(stderr, "finished %s\n", __func__); // ensure return address is saved
47 }
48
test2(int i,int j)49 __attribute__((noinline)) void test2(int i, int j) {
50 fprintf(stderr, "starting %s\n", __func__);
51 backtrace(i);
52 test1(j);
53 fprintf(stderr, "finished %s\n", __func__); // ensure return address is saved
54 }
55
test3(int i,int j,int k)56 __attribute__((noinline)) void test3(int i, int j, int k) {
57 fprintf(stderr, "starting %s\n", __func__);
58 backtrace(i);
59 test2(j, k);
60 fprintf(stderr, "finished %s\n", __func__); // ensure return address is saved
61 }
62
test_no_info()63 void test_no_info() {
64 unw_context_t context;
65 unw_getcontext(&context);
66
67 unw_cursor_t cursor;
68 unw_init_local(&cursor, &context);
69
70 unw_proc_info_t info;
71 int ret = unw_get_proc_info(&cursor, &info);
72 if (ret != UNW_ESUCCESS)
73 abort();
74
75 // Set the IP to an address clearly outside any function.
76 unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)0);
77
78 ret = unw_get_proc_info(&cursor, &info);
79 if (ret != UNW_ENOINFO)
80 abort();
81 }
82
main()83 int main() {
84 test1(3);
85 test2(3, 4);
86 test3(3, 4, 5);
87 test_no_info();
88 fprintf(stderr, "Success!\n");
89 return 0;
90 }
91