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