1 // TODO: Investigate these failures 2 // XFAIL: asan, tsan, ubsan 3 4 // TODO: Investigate these failures on x86_64 macOS 5 // XFAIL: target=x86_64-apple-darwin{{.+}} 6 7 // TODO: Investigate this failure 8 // XFAIL: 32bits-on-64bits 9 10 #include <libunwind.h> 11 #include <stdlib.h> 12 #include <string.h> 13 14 void backtrace(int lower_bound) { 15 unw_context_t context; 16 unw_getcontext(&context); 17 18 unw_cursor_t cursor; 19 unw_init_local(&cursor, &context); 20 21 int n = 0; 22 do { 23 ++n; 24 if (n > 100) { 25 abort(); 26 } 27 } while (unw_step(&cursor) > 0); 28 29 if (n < lower_bound) { 30 abort(); 31 } 32 } 33 34 void test1(int i) { 35 backtrace(i); 36 } 37 38 void test2(int i, int j) { 39 backtrace(i); 40 test1(j); 41 } 42 43 void test3(int i, int j, int k) { 44 backtrace(i); 45 test2(j, k); 46 } 47 48 void test_no_info() { 49 unw_context_t context; 50 unw_getcontext(&context); 51 52 unw_cursor_t cursor; 53 unw_init_local(&cursor, &context); 54 55 unw_proc_info_t info; 56 int ret = unw_get_proc_info(&cursor, &info); 57 if (ret != UNW_ESUCCESS) 58 abort(); 59 60 // Set the IP to an address clearly outside any function. 61 unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)0); 62 63 ret = unw_get_proc_info(&cursor, &info); 64 if (ret != UNW_ENOINFO) 65 abort(); 66 } 67 68 void test_reg_names() { 69 unw_context_t context; 70 unw_getcontext(&context); 71 72 unw_cursor_t cursor; 73 unw_init_local(&cursor, &context); 74 75 int max_reg_num = -100; 76 #if defined(__i386__) 77 max_reg_num = 7; 78 #elif defined(__x86_64__) 79 max_reg_num = 32; 80 #endif 81 82 const char prefix[] = "unknown"; 83 for (int i = -2; i < max_reg_num; ++i) { 84 if (strncmp(prefix, unw_regname(&cursor, i), sizeof(prefix) - 1) == 0) 85 abort(); 86 } 87 88 if (strncmp(prefix, unw_regname(&cursor, max_reg_num + 1), 89 sizeof(prefix) - 1) != 0) 90 abort(); 91 } 92 93 #if defined(__x86_64__) 94 void test_reg_get_set() { 95 unw_context_t context; 96 unw_getcontext(&context); 97 98 unw_cursor_t cursor; 99 unw_init_local(&cursor, &context); 100 101 for (int i = 0; i < 17; ++i) { 102 const unw_word_t set_value = 7; 103 if (unw_set_reg(&cursor, i, set_value) != UNW_ESUCCESS) 104 abort(); 105 106 unw_word_t get_value = 0; 107 if (unw_get_reg(&cursor, i, &get_value) != UNW_ESUCCESS) 108 abort(); 109 110 if (set_value != get_value) 111 abort(); 112 } 113 } 114 115 void test_fpreg_get_set() { 116 unw_context_t context; 117 unw_getcontext(&context); 118 119 unw_cursor_t cursor; 120 unw_init_local(&cursor, &context); 121 122 // get/set is not implemented for x86_64 fpregs. 123 for (int i = 17; i < 33; ++i) { 124 const unw_fpreg_t set_value = 7; 125 if (unw_set_fpreg(&cursor, i, set_value) != UNW_EBADREG) 126 abort(); 127 128 unw_fpreg_t get_value = 0; 129 if (unw_get_fpreg(&cursor, i, &get_value) != UNW_EBADREG) 130 abort(); 131 } 132 } 133 #else 134 void test_reg_get_set() {} 135 void test_fpreg_get_set() {} 136 #endif 137 138 int main(int, char**) { 139 test1(1); 140 test2(1, 2); 141 test3(1, 2, 3); 142 test_no_info(); 143 test_reg_names(); 144 test_reg_get_set(); 145 test_fpreg_get_set(); 146 return 0; 147 } 148