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; } @@ -347,6 +347,7 @@ inline uint64_t Registers_x86_64::getRegister(int regNum) const { switch (regNum) { case UNW_REG_IP: + case UNW_X86_64_RIP: return _registers.__rip; case UNW_REG_SP: return _registers.__rsp; @@ -389,6 +390,7 @@ inline void Registers_x86_64::setRegister(int regNum, uint64_t value) { switch (regNum) { case UNW_REG_IP: + case UNW_X86_64_RIP: _registers.__rip = value; return; case UNW_REG_SP: @@ -449,6 +451,7 @@ inline const char *Registers_x86_64::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: + case UNW_X86_64_RIP: return "rip"; case UNW_REG_SP: return "rsp"; 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,6 @@ #include #include +#include void backtrace(int lower_bound) { unw_context_t context; @@ -55,10 +56,83 @@ 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; }