blob: d89f8d16ce70d7374d00e38bc6e48beb0ca3e8ec [file] [log] [blame]
Louis Dionne10f4e4a2021-10-12 12:46:21 -04001// TODO: Investigate these failures on x86_64 macOS back deployment
2// UNSUPPORTED: target=x86_64-apple-darwin{{.+}}
Louis Dionne9915ba52021-09-30 15:11:48 -04003
Louis Dionne31359e02022-03-02 17:49:13 -05004// TODO: Figure out why this fails with Memory Sanitizer.
5// XFAIL: msan
6
Logan Chiena54f0962015-05-29 15:33:38 +00007#include <libunwind.h>
8#include <stdlib.h>
Vitaly Buka83f8edb2021-08-11 10:35:23 -07009#include <string.h>
Logan Chiena54f0962015-05-29 15:33:38 +000010
11void backtrace(int lower_bound) {
12 unw_context_t context;
13 unw_getcontext(&context);
14
15 unw_cursor_t cursor;
16 unw_init_local(&cursor, &context);
17
18 int n = 0;
19 do {
20 ++n;
21 if (n > 100) {
22 abort();
23 }
24 } while (unw_step(&cursor) > 0);
25
26 if (n < lower_bound) {
27 abort();
28 }
29}
30
31void test1(int i) {
32 backtrace(i);
33}
34
35void test2(int i, int j) {
36 backtrace(i);
37 test1(j);
38}
39
40void test3(int i, int j, int k) {
41 backtrace(i);
42 test2(j, k);
43}
44
Saleem Abdulrasool78b42cc2019-09-20 15:53:42 +000045void test_no_info() {
46 unw_context_t context;
47 unw_getcontext(&context);
48
49 unw_cursor_t cursor;
50 unw_init_local(&cursor, &context);
51
52 unw_proc_info_t info;
53 int ret = unw_get_proc_info(&cursor, &info);
54 if (ret != UNW_ESUCCESS)
55 abort();
56
57 // Set the IP to an address clearly outside any function.
John Brawn57be2d22019-10-03 17:01:04 +000058 unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)0);
Saleem Abdulrasool78b42cc2019-09-20 15:53:42 +000059
60 ret = unw_get_proc_info(&cursor, &info);
61 if (ret != UNW_ENOINFO)
62 abort();
63}
64
Vitaly Buka83f8edb2021-08-11 10:35:23 -070065void test_reg_names() {
66 unw_context_t context;
67 unw_getcontext(&context);
68
69 unw_cursor_t cursor;
70 unw_init_local(&cursor, &context);
71
72 int max_reg_num = -100;
73#if defined(__i386__)
74 max_reg_num = 7;
75#elif defined(__x86_64__)
76 max_reg_num = 32;
77#endif
78
79 const char prefix[] = "unknown";
80 for (int i = -2; i < max_reg_num; ++i) {
81 if (strncmp(prefix, unw_regname(&cursor, i), sizeof(prefix) - 1) == 0)
82 abort();
83 }
84
85 if (strncmp(prefix, unw_regname(&cursor, max_reg_num + 1),
86 sizeof(prefix) - 1) != 0)
87 abort();
88}
89
90#if defined(__x86_64__)
91void test_reg_get_set() {
92 unw_context_t context;
93 unw_getcontext(&context);
94
95 unw_cursor_t cursor;
96 unw_init_local(&cursor, &context);
97
98 for (int i = 0; i < 17; ++i) {
99 const unw_word_t set_value = 7;
100 if (unw_set_reg(&cursor, i, set_value) != UNW_ESUCCESS)
101 abort();
102
103 unw_word_t get_value = 0;
104 if (unw_get_reg(&cursor, i, &get_value) != UNW_ESUCCESS)
105 abort();
106
107 if (set_value != get_value)
108 abort();
109 }
110}
111
112void test_fpreg_get_set() {
113 unw_context_t context;
114 unw_getcontext(&context);
115
116 unw_cursor_t cursor;
117 unw_init_local(&cursor, &context);
118
119 // get/set is not implemented for x86_64 fpregs.
120 for (int i = 17; i < 33; ++i) {
121 const unw_fpreg_t set_value = 7;
122 if (unw_set_fpreg(&cursor, i, set_value) != UNW_EBADREG)
123 abort();
124
125 unw_fpreg_t get_value = 0;
126 if (unw_get_fpreg(&cursor, i, &get_value) != UNW_EBADREG)
127 abort();
128 }
129}
130#else
131void test_reg_get_set() {}
132void test_fpreg_get_set() {}
133#endif
134
Louis Dionnecbfe0172020-10-08 13:36:33 -0400135int main(int, char**) {
Logan Chiena54f0962015-05-29 15:33:38 +0000136 test1(1);
137 test2(1, 2);
138 test3(1, 2, 3);
Saleem Abdulrasool78b42cc2019-09-20 15:53:42 +0000139 test_no_info();
Vitaly Buka83f8edb2021-08-11 10:35:23 -0700140 test_reg_names();
141 test_reg_get_set();
142 test_fpreg_get_set();
Louis Dionnecbfe0172020-10-08 13:36:33 -0400143 return 0;
Logan Chiena54f0962015-05-29 15:33:38 +0000144}