Files
clang-p2996/libunwind/test/libunwind_01.pass.cpp
Louis Dionne 60fe1f59d0 [runtimes][ci] Run the tests for libunwind in the CI
We should arguably have always been doing that. The state of libunwind
is quite sad, so this commit adds several XFAILs to make the CI pass.
We need to investigate why so many tests are not passing in some
configurations, but I'll defer that to folks who actually work on
libunwind for lack of bandwidth.

Differential Revision: https://reviews.llvm.org/D110872
2021-10-06 11:25:26 -04:00

148 lines
2.8 KiB
C++

// 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 <libunwind.h>
#include <stdlib.h>
#include <string.h>
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;
}