1 // TODO: Investigate these failures 2 // XFAIL: asan, tsan, ubsan 3 4 // TODO: Investigate these failures on x86_64 macOS back deployment 5 // UNSUPPORTED: target=x86_64-apple-darwin{{.+}} 6 7 #include <libunwind.h> 8 #include <stdlib.h> 9 #include <string.h> 10 11 void 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 31 void test1(int i) { 32 backtrace(i); 33 } 34 35 void test2(int i, int j) { 36 backtrace(i); 37 test1(j); 38 } 39 40 void test3(int i, int j, int k) { 41 backtrace(i); 42 test2(j, k); 43 } 44 45 void 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. 58 unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)0); 59 60 ret = unw_get_proc_info(&cursor, &info); 61 if (ret != UNW_ENOINFO) 62 abort(); 63 } 64 65 void 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__) 91 void 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 112 void 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 131 void test_reg_get_set() {} 132 void test_fpreg_get_set() {} 133 #endif 134 135 int main(int, char**) { 136 test1(1); 137 test2(1, 2); 138 test3(1, 2, 3); 139 test_no_info(); 140 test_reg_names(); 141 test_reg_get_set(); 142 test_fpreg_get_set(); 143 return 0; 144 } 145