diff --git a/src/Native/Runtime/unix/UnixContext.cpp b/src/Native/Runtime/unix/UnixContext.cpp index 18fff0ccbd0..ea538213c05 100644 --- a/src/Native/Runtime/unix/UnixContext.cpp +++ b/src/Native/Runtime/unix/UnixContext.cpp @@ -232,11 +232,11 @@ int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*) static void RegDisplayToUnwindCursor(REGDISPLAY* regDisplay, unw_cursor_t *cursor) { #define ASSIGN_REG(regName1, regName2) \ - unw_set_reg(cursor, regName1, regDisplay->regName2); + unw_set_reg(cursor, regName1, regDisplay->regName2, 0); #define ASSIGN_REG_PTR(regName1, regName2) \ if (regDisplay->p##regName2 != NULL) \ - unw_set_reg(cursor, regName1, *(regDisplay->p##regName2)); + unw_set_reg(cursor, regName1, *(regDisplay->p##regName2), 0); #if defined(_AMD64_) ASSIGN_REG(UNW_REG_SP, SP) diff --git a/src/Native/Runtime/unix/UnwindHelpers.cpp b/src/Native/Runtime/unix/UnwindHelpers.cpp index c77de82009c..7322e1ab1ed 100644 --- a/src/Native/Runtime/unix/UnwindHelpers.cpp +++ b/src/Native/Runtime/unix/UnwindHelpers.cpp @@ -292,13 +292,152 @@ struct Registers_REGDISPLAY : REGDISPLAY }; #endif // _TARGET_AMD64_ +#if defined(_TARGET_ARM_) + +class Registers_arm_rt: public libunwind::Registers_arm { +public: + Registers_arm_rt() { abort(); }; + Registers_arm_rt(void *registers) { regs = (REGDISPLAY *)registers; }; + uint32_t getRegister(int num); + void setRegister(int num, uint32_t value, uint32_t location); + uint32_t getRegisterLocation(int regNum) const { abort();} + unw_fpreg_t getFloatRegister(int num) { abort();} + void setFloatRegister(int num, unw_fpreg_t value) {abort();} + bool validVectorRegister(int num) const { abort();} + uint32_t getVectorRegister(int num) const {abort();}; + void setVectorRegister(int num, uint32_t value) {abort();}; + void jumpto() { abort();}; + uint32_t getSP() const { return regs->SP;} + void setSP(uint32_t value, uint32_t location) { regs->SP = value;} + uint32_t getIP() const { return regs->IP;} + void setIP(uint32_t value, uint32_t location) + { regs->IP = value; regs->pIP = (PTR_UIntNative)location; } + void saveVFPAsX() {abort();}; +private: + REGDISPLAY *regs; +}; + +inline uint32_t Registers_arm_rt::getRegister(int regNum) { + if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) + return regs->SP; + + if (regNum == UNW_ARM_LR) + return *regs->pLR; + + if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) + return regs->IP; + + switch (regNum) + { + case (UNW_ARM_R0): + return *regs->pR0; + case (UNW_ARM_R1): + return *regs->pR1; + case (UNW_ARM_R2): + return *regs->pR2; + case (UNW_ARM_R3): + return *regs->pR3; + case (UNW_ARM_R4): + return *regs->pR4; + case (UNW_ARM_R5): + return *regs->pR5; + case (UNW_ARM_R6): + return *regs->pR6; + case (UNW_ARM_R7): + return *regs->pR7; + case (UNW_ARM_R8): + return *regs->pR8; + case (UNW_ARM_R9): + return *regs->pR9; + case (UNW_ARM_R10): + return *regs->pR10; + case (UNW_ARM_R11): + return *regs->pR11; + case (UNW_ARM_R12): + return *regs->pR12; + } + + PORTABILITY_ASSERT("unsupported arm register"); +} + +void Registers_arm_rt::setRegister(int num, uint32_t value, uint32_t location) +{ + + if (num == UNW_REG_SP || num == UNW_ARM_SP) { + regs->SP = (UIntNative )value; + return; + } + + if (num == UNW_ARM_LR) { + regs->pLR = (PTR_UIntNative)location; + return; + } + + if (num == UNW_REG_IP || num == UNW_ARM_IP) { + regs->IP = value; + /* the location could be NULL, we could try to recover + pointer to value in stack from pLR */ + if ((!location) && (regs->pLR) && (*regs->pLR == value)) + regs->pIP = regs->pLR; + else + regs->pIP = (PTR_UIntNative)location; + return; + } + + switch (num) + { + case (UNW_ARM_R0): + regs->pR0 = (PTR_UIntNative)location; + break; + case (UNW_ARM_R1): + regs->pR1 = (PTR_UIntNative)location; + break; + case (UNW_ARM_R2): + regs->pR2 = (PTR_UIntNative)location; + break; + case (UNW_ARM_R3): + regs->pR3 = (PTR_UIntNative)location; + break; + case (UNW_ARM_R4): + regs->pR4 = (PTR_UIntNative)location; + break; + case (UNW_ARM_R5): + regs->pR5 = (PTR_UIntNative)location; + break; + case (UNW_ARM_R6): + regs->pR6 = (PTR_UIntNative)location; + break; + case (UNW_ARM_R7): + regs->pR7 = (PTR_UIntNative)location; + break; + case (UNW_ARM_R8): + regs->pR8 = (PTR_UIntNative)location; + break; + case (UNW_ARM_R9): + regs->pR9 = (PTR_UIntNative)location; + break; + case (UNW_ARM_R10): + regs->pR10 = (PTR_UIntNative)location; + break; + case (UNW_ARM_R11): + regs->pR11 = (PTR_UIntNative)location; + break; + case (UNW_ARM_R12): + regs->pR12 = (PTR_UIntNative)location; + break; + default: + PORTABILITY_ASSERT("unsupported arm register"); + } +} + +#endif // _TARGET_ARM_ bool DoTheStep(uintptr_t pc, UnwindInfoSections uwInfoSections, REGDISPLAY *regs) { #if defined(_TARGET_AMD64_) libunwind::UnwindCursor uc(_addressSpace); #elif defined(_TARGET_ARM_) - libunwind::UnwindCursor uc(_addressSpace); + libunwind::UnwindCursor uc(_addressSpace, regs); #else #error "Unwinding is not implemented for this architecture yet." #endif @@ -322,8 +461,13 @@ bool DoTheStep(uintptr_t pc, UnwindInfoSections uwInfoSections, REGDISPLAY *regs } regs->pIP = PTR_PCODE(regs->SP - sizeof(TADDR)); -#else - PORTABILITY_ASSERT("DoTheStep"); +#elif defined(_LIBUNWIND_ARM_EHABI) + uc.setInfoBasedOnIPRegister(true); + int stepRet = uc.step(); + if ((stepRet != UNW_STEP_SUCCESS) && (stepRet != UNW_STEP_END)) + { + return false; + } #endif return true; @@ -365,18 +509,20 @@ UnwindInfoSections LocateUnwindSections(uintptr_t pc) bool UnwindHelpers::StepFrame(REGDISPLAY *regs) { +#if _LIBUNWIND_SUPPORT_DWARF_UNWIND uintptr_t pc = regs->GetIP(); - UnwindInfoSections uwInfoSections = LocateUnwindSections(pc); - -#if _LIBUNWIND_SUPPORT_DWARF_UNWIND if (uwInfoSections.dwarf_section == NULL) { return false; } + return DoTheStep(pc, uwInfoSections, regs); +#elif defined(_LIBUNWIND_ARM_EHABI) + // unwind section is located later for ARM + // pc will be taked from regs parameter + UnwindInfoSections uwInfoSections; + return DoTheStep(0, uwInfoSections, regs); #else PORTABILITY_ASSERT("StepFrame"); #endif - - return DoTheStep(pc, uwInfoSections, regs); } diff --git a/src/Native/libunwind/include/libunwind.h b/src/Native/libunwind/include/libunwind.h index 59187798d32..2e11f48d961 100644 --- a/src/Native/libunwind/include/libunwind.h +++ b/src/Native/libunwind/include/libunwind.h @@ -124,7 +124,7 @@ extern int unw_init_local(unw_cursor_t *, unw_context_t *) LIBUNWIND_AVAIL; extern int unw_step(unw_cursor_t *) LIBUNWIND_AVAIL; extern int unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *) LIBUNWIND_AVAIL; extern int unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *) LIBUNWIND_AVAIL; -extern int unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t) LIBUNWIND_AVAIL; +extern int unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t, unw_word_t *) LIBUNWIND_AVAIL; extern int unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t) LIBUNWIND_AVAIL; extern int unw_resume(unw_cursor_t *) LIBUNWIND_AVAIL; diff --git a/src/Native/libunwind/include/unwind.h b/src/Native/libunwind/include/unwind.h index 1d163ca9af6..a350f51adde 100644 --- a/src/Native/libunwind/include/unwind.h +++ b/src/Native/libunwind/include/unwind.h @@ -200,7 +200,7 @@ _Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, extern _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, uint32_t regno, _Unwind_VRS_DataRepresentation representation, - void *valuep); + void *valuep, uint32_t *pos); extern _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, @@ -212,7 +212,7 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, extern uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index); extern void _Unwind_SetGR(struct _Unwind_Context *context, int index, - uintptr_t new_value); + uintptr_t new_value, uintptr_t *pos); extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context); extern void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t new_value); @@ -240,8 +240,8 @@ uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) { _LIBUNWIND_EXPORT_UNWIND_LEVEL1 void _Unwind_SetGR(struct _Unwind_Context *context, int index, - uintptr_t value) { - _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value); + uintptr_t value,uintptr_t *pos) { + _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value, pos); } _LIBUNWIND_EXPORT_UNWIND_LEVEL1 @@ -253,7 +253,7 @@ uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { _LIBUNWIND_EXPORT_UNWIND_LEVEL1 void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t value) { uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1); - _Unwind_SetGR(context, 15, value | thumb_bit); + _Unwind_SetGR(context, 15, value | thumb_bit, NULL); } #endif // _LIBUNWIND_ARM_EHABI diff --git a/src/Native/libunwind/src/Unwind-EHABI.cpp b/src/Native/libunwind/src/Unwind-EHABI.cpp index 11465521510..31da198c4e7 100644 --- a/src/Native/libunwind/src/Unwind-EHABI.cpp +++ b/src/Native/libunwind/src/Unwind-EHABI.cpp @@ -259,7 +259,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, sp -= (((uint32_t)byte & 0x3f) << 2) + 4; else sp += ((uint32_t)byte << 2) + 4; - _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); + _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp, NULL); } else { switch (byte & 0xf0) { case 0x80: { @@ -283,7 +283,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_R0 + reg, _UVRSD_UINT32, &sp); _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, - &sp); + &sp, NULL); break; } case 0xa0: { @@ -325,7 +325,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, &sp); sp += 0x204 + (addend << 2); _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, - &sp); + &sp, NULL); break; } case 0xb3: { @@ -411,7 +411,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, if (!wrotePC) { uint32_t lr; _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_LR, _UVRSD_UINT32, &lr); - _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr); + _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr, NULL); } return _URC_CONTINUE_UNWIND; } @@ -559,7 +559,7 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor // // See #7.4.6 for details. unw_set_reg(cursor, UNW_REG_IP, - exception_object->unwinder_cache.reserved2); + exception_object->unwinder_cache.reserved2, NULL); resume = false; } @@ -753,7 +753,7 @@ static uint64_t ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation, _LIBUNWIND_EXPORT _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, uint32_t regno, _Unwind_VRS_DataRepresentation representation, - void *valuep) { + void *valuep, unw_word_t *pos) { _LIBUNWIND_TRACE_API("_Unwind_VRS_Set(context=%p, regclass=%d, reg=%d, " "rep=%d, value=0x%llX)", static_cast(context), regclass, regno, @@ -765,7 +765,7 @@ _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, if (representation != _UVRSD_UINT32 || regno > 15) return _UVRSR_FAILED; return unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno), - *(unw_word_t *)valuep) == UNW_ESUCCESS + *(unw_word_t *)valuep,(unw_word_t *)pos) == UNW_ESUCCESS ? _UVRSR_OK : _UVRSR_FAILED; case _UVRSC_VFP: @@ -897,6 +897,7 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, // computed new stack location. See EHABI #7.5.4 table 3. bool poppedSP = false; uint32_t* sp; + uint32_t* pos; if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp) != _UVRSR_OK) { return _UVRSR_FAILED; @@ -904,17 +905,18 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, for (uint32_t i = 0; i < 16; ++i) { if (!(discriminator & static_cast(1 << i))) continue; + pos = sp; uint32_t value = *sp++; if (regclass == _UVRSC_CORE && i == 13) poppedSP = true; if (_Unwind_VRS_Set(context, regclass, i, - _UVRSD_UINT32, &value) != _UVRSR_OK) { + _UVRSD_UINT32, &value, pos) != _UVRSR_OK) { return _UVRSR_FAILED; } } if (!poppedSP) { return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, - _UVRSD_UINT32, &sp); + _UVRSD_UINT32, &sp, NULL); } return _UVRSR_OK; } @@ -939,14 +941,14 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, // SP is only 32-bit aligned so don't copy 64-bit at a time. uint64_t value = *sp++; value |= ((uint64_t)(*sp++)) << 32; - if (_Unwind_VRS_Set(context, regclass, i, representation, &value) != + if (_Unwind_VRS_Set(context, regclass, i, representation, &value, NULL) != _UVRSR_OK) return _UVRSR_FAILED; } if (representation == _UVRSD_VFPX) ++sp; return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, - &sp); + &sp, NULL); } } _LIBUNWIND_ABORT("unsupported register class"); diff --git a/src/Native/libunwind/src/UnwindCursor.hpp b/src/Native/libunwind/src/UnwindCursor.hpp index f68eee18e96..17cd33c47a2 100644 --- a/src/Native/libunwind/src/UnwindCursor.hpp +++ b/src/Native/libunwind/src/UnwindCursor.hpp @@ -628,9 +628,11 @@ UnwindCursor::UnwindCursor(unw_context_t *context, A &as) } template -UnwindCursor::UnwindCursor(A &as, void *) - : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) { +UnwindCursor::UnwindCursor(A &as, void *arg) + : _addressSpace(as),_registers(arg), _unwindInfoMissing(false), + _isSignalFrame(false) { memset(&_info, 0, sizeof(_info)); + // FIXME // fill in _registers from thread arg } diff --git a/src/Native/libunwind/src/config.h b/src/Native/libunwind/src/config.h index bba0f9c9f1f..d8bcac88217 100644 --- a/src/Native/libunwind/src/config.h +++ b/src/Native/libunwind/src/config.h @@ -42,13 +42,8 @@ #endif #else #if defined(__ARM_DWARF_EH__) || !defined(__arm__) - #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 0 #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1 - #else - #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 0 - #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 0 - #define _LIBUNWIND_SUPPORT_DWARF_INDEX 0 #endif #endif diff --git a/src/Native/libunwind/src/libunwind.cpp b/src/Native/libunwind/src/libunwind.cpp index 3821149d684..00c0fc3776e 100644 --- a/src/Native/libunwind/src/libunwind.cpp +++ b/src/Native/libunwind/src/libunwind.cpp @@ -171,13 +171,13 @@ _LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum, /// Set value of specified register at cursor position in stack frame. _LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, - unw_word_t value) { + unw_word_t value, unw_word_t *pos) { _LIBUNWIND_TRACE_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%llX)", static_cast(cursor), regNum, (long long)value); typedef LocalAddressSpace::pint_t pint_t; AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->validReg(regNum)) { - co->setReg(regNum, (pint_t)value, 0); + co->setReg(regNum, (pint_t)value, (pint_t)pos); // special case altering IP to re-find info (being called by personality // function) if (regNum == UNW_REG_IP)