// TODO: Investigate these failures // XFAIL: asan, tsan, ubsan // TODO: Investigate these failures on x86_64 macOS // XFAIL: target=x86_64-apple-darwin{{.+}} // TODO: Investigate this failure // XFAIL: 32bits-on-64bits #include #include #include void backtrace(int lower_bound) { unw_context_t context; unw_getcontext(&context); unw_cursor_t cursor; unw_init_local(&cursor, &context); int n = 0; do { ++n; if (n > 100) { abort(); } } while (unw_step(&cursor) > 0); if (n < lower_bound) { abort(); } } void test1(int i) { backtrace(i); } void test2(int i, int j) { backtrace(i); test1(j); } void test3(int i, int j, int k) { backtrace(i); test2(j, k); } void test_no_info() { unw_context_t context; unw_getcontext(&context); unw_cursor_t cursor; unw_init_local(&cursor, &context); unw_proc_info_t info; int ret = unw_get_proc_info(&cursor, &info); if (ret != UNW_ESUCCESS) abort(); // Set the IP to an address clearly outside any function. unw_set_reg(&cursor, UNW_REG_IP, (unw_word_t)0); ret = unw_get_proc_info(&cursor, &info); if (ret != UNW_ENOINFO) abort(); } void test_reg_names() { unw_context_t context; unw_getcontext(&context); unw_cursor_t cursor; unw_init_local(&cursor, &context); int max_reg_num = -100; #if defined(__i386__) max_reg_num = 7; #elif defined(__x86_64__) max_reg_num = 32; #endif const char prefix[] = "unknown"; for (int i = -2; i < max_reg_num; ++i) { if (strncmp(prefix, unw_regname(&cursor, i), sizeof(prefix) - 1) == 0) abort(); } if (strncmp(prefix, unw_regname(&cursor, max_reg_num + 1), sizeof(prefix) - 1) != 0) abort(); } #if defined(__x86_64__) void test_reg_get_set() { unw_context_t context; unw_getcontext(&context); unw_cursor_t cursor; unw_init_local(&cursor, &context); for (int i = 0; i < 17; ++i) { const unw_word_t set_value = 7; if (unw_set_reg(&cursor, i, set_value) != UNW_ESUCCESS) abort(); unw_word_t get_value = 0; if (unw_get_reg(&cursor, i, &get_value) != UNW_ESUCCESS) abort(); if (set_value != get_value) abort(); } } void test_fpreg_get_set() { unw_context_t context; unw_getcontext(&context); unw_cursor_t cursor; unw_init_local(&cursor, &context); // get/set is not implemented for x86_64 fpregs. for (int i = 17; i < 33; ++i) { const unw_fpreg_t set_value = 7; if (unw_set_fpreg(&cursor, i, set_value) != UNW_EBADREG) abort(); unw_fpreg_t get_value = 0; if (unw_get_fpreg(&cursor, i, &get_value) != UNW_EBADREG) abort(); } } #else void test_reg_get_set() {} void test_fpreg_get_set() {} #endif int main(int, char**) { test1(1); test2(1, 2); test3(1, 2, 3); test_no_info(); test_reg_names(); test_reg_get_set(); test_fpreg_get_set(); return 0; }