diff --git a/libunwind/src/Registers.hpp b/libunwind/src/Registers.hpp --- a/libunwind/src/Registers.hpp +++ b/libunwind/src/Registers.hpp @@ -339,7 +339,7 @@ return true; if (regNum < 0) return false; - if (regNum > 15) + if (regNum > 16) return false; return true; } @@ -382,6 +382,8 @@ return _registers.__r14; case UNW_X86_64_R15: return _registers.__r15; + case UNW_X86_64_RIP: + return _registers.__rip; } _LIBUNWIND_ABORT("unsupported x86_64 register"); } @@ -442,6 +444,9 @@ case UNW_X86_64_R15: _registers.__r15 = value; return; + case UNW_X86_64_RIP: + _registers.__rip = value; + return; } _LIBUNWIND_ABORT("unsupported x86_64 register"); } @@ -484,6 +489,8 @@ return "r14"; case UNW_X86_64_R15: return "r15"; + case UNW_X86_64_RIP: + return "rip"; case UNW_X86_64_XMM0: return "xmm0"; case UNW_X86_64_XMM1: diff --git a/libunwind/test/libunwind_01.pass.cpp b/libunwind/test/libunwind_01.pass.cpp --- a/libunwind/test/libunwind_01.pass.cpp +++ b/libunwind/test/libunwind_01.pass.cpp @@ -1,5 +1,7 @@ #include +#include #include +#include void backtrace(int lower_bound) { unw_context_t context; @@ -55,10 +57,80 @@ abort(); } +#if defined(__x86_64__) +void test_reg_names() { + unw_context_t context; + unw_getcontext(&context); + + unw_cursor_t cursor; + unw_init_local(&cursor, &context); + + for (int i = 0; i < 33; ++i) { + const char prefix[] = "unknown"; + if (strncmp(prefix, unw_regname(&cursor, i), sizeof(prefix) - 1) == 0) + abort(); + } +} + +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) { + printf("1\n"); + abort(); + } + + unw_word_t get_value = 0; + if (unw_get_reg(&cursor, i, &get_value) != UNW_ESUCCESS) { + printf("2\n"); + abort(); + } + + if (set_value != get_value) { + printf("3\n"); + 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_names() {} +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; }