blob: 277e3e6ded4f470eef9f7bae8d4d5d988cc13369 [file] [log] [blame]
Logan Chiena54f0962015-05-29 15:33:38 +00001#include <libunwind.h>
2#include <stdlib.h>
Vitaly Buka83f8edb2021-08-11 10:35:23 -07003#include <string.h>
Logan Chiena54f0962015-05-29 15:33:38 +00004
5void 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 int n = 0;
13 do {
14 ++n;
15 if (n > 100) {
16 abort();
17 }
18 } while (unw_step(&cursor) > 0);
19
20 if (n < lower_bound) {
21 abort();
22 }
23}
24
25void test1(int i) {
26 backtrace(i);
27}
28
29void test2(int i, int j) {
30 backtrace(i);
31 test1(j);
32}
33
34void test3(int i, int j, int k) {
35 backtrace(i);
36 test2(j, k);
37}
38
Saleem Abdulrasool78b42cc2019-09-20 15:53:42 +000039void test_no_info() {
40 unw_context_t context;
41 unw_getcontext(&context);
42
43 unw_cursor_t cursor;
44 unw_init_local(&cursor, &context);
45
46 unw_proc_info_t info;
47 int ret = unw_get_proc_info(&cursor, &info);
48 if (ret != UNW_ESUCCESS)
49 abort();
50
51 // Set the IP to an address clearly outside any function.
John Brawn57be2d22019-10-03 17:01:04 +000052 unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)0);
Saleem Abdulrasool78b42cc2019-09-20 15:53:42 +000053
54 ret = unw_get_proc_info(&cursor, &info);
55 if (ret != UNW_ENOINFO)
56 abort();
57}
58
Vitaly Buka83f8edb2021-08-11 10:35:23 -070059void test_reg_names() {
60 unw_context_t context;
61 unw_getcontext(&context);
62
63 unw_cursor_t cursor;
64 unw_init_local(&cursor, &context);
65
66 int max_reg_num = -100;
67#if defined(__i386__)
68 max_reg_num = 7;
69#elif defined(__x86_64__)
70 max_reg_num = 32;
71#endif
72
73 const char prefix[] = "unknown";
74 for (int i = -2; i < max_reg_num; ++i) {
75 if (strncmp(prefix, unw_regname(&cursor, i), sizeof(prefix) - 1) == 0)
76 abort();
77 }
78
79 if (strncmp(prefix, unw_regname(&cursor, max_reg_num + 1),
80 sizeof(prefix) - 1) != 0)
81 abort();
82}
83
84#if defined(__x86_64__)
85void test_reg_get_set() {
86 unw_context_t context;
87 unw_getcontext(&context);
88
89 unw_cursor_t cursor;
90 unw_init_local(&cursor, &context);
91
92 for (int i = 0; i < 17; ++i) {
93 const unw_word_t set_value = 7;
94 if (unw_set_reg(&cursor, i, set_value) != UNW_ESUCCESS)
95 abort();
96
97 unw_word_t get_value = 0;
98 if (unw_get_reg(&cursor, i, &get_value) != UNW_ESUCCESS)
99 abort();
100
101 if (set_value != get_value)
102 abort();
103 }
104}
105
106void test_fpreg_get_set() {
107 unw_context_t context;
108 unw_getcontext(&context);
109
110 unw_cursor_t cursor;
111 unw_init_local(&cursor, &context);
112
113 // get/set is not implemented for x86_64 fpregs.
114 for (int i = 17; i < 33; ++i) {
115 const unw_fpreg_t set_value = 7;
116 if (unw_set_fpreg(&cursor, i, set_value) != UNW_EBADREG)
117 abort();
118
119 unw_fpreg_t get_value = 0;
120 if (unw_get_fpreg(&cursor, i, &get_value) != UNW_EBADREG)
121 abort();
122 }
123}
124#else
125void test_reg_get_set() {}
126void test_fpreg_get_set() {}
127#endif
128
Louis Dionnecbfe0172020-10-08 13:36:33 -0400129int main(int, char**) {
Logan Chiena54f0962015-05-29 15:33:38 +0000130 test1(1);
131 test2(1, 2);
132 test3(1, 2, 3);
Saleem Abdulrasool78b42cc2019-09-20 15:53:42 +0000133 test_no_info();
Vitaly Buka83f8edb2021-08-11 10:35:23 -0700134 test_reg_names();
135 test_reg_get_set();
136 test_fpreg_get_set();
Louis Dionnecbfe0172020-10-08 13:36:33 -0400137 return 0;
Logan Chiena54f0962015-05-29 15:33:38 +0000138}