Please use GitHub pull requests for new patches. Avoid migrating existing patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
libunwind/src/Unwind-EHABI.cpp
Show First 20 Lines • Show All 255 Lines • ▼ Show 20 Lines | decode_eht_entry(const uint32_t* data, size_t* off, size_t* len) { | ||||
return data; | return data; | ||||
} | } | ||||
_LIBUNWIND_EXPORT _Unwind_Reason_Code | _LIBUNWIND_EXPORT _Unwind_Reason_Code | ||||
_Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, | _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, | ||||
size_t offset, size_t len) { | size_t offset, size_t len) { | ||||
bool wrotePC = false; | bool wrotePC = false; | ||||
bool finish = false; | bool finish = false; | ||||
bool hasReturnAddrAuthCode = false; | |||||
while (offset < len && !finish) { | while (offset < len && !finish) { | ||||
uint8_t byte = getByte(data, offset++); | uint8_t byte = getByte(data, offset++); | ||||
if ((byte & 0x80) == 0) { | if ((byte & 0x80) == 0) { | ||||
uint32_t sp; | uint32_t sp; | ||||
_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); | _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); | ||||
if (byte & 0x40) | if (byte & 0x40) | ||||
sp -= (((uint32_t)byte & 0x3f) << 2) + 4; | sp -= (((uint32_t)byte & 0x3f) << 2) + 4; | ||||
else | else | ||||
Show All 36 Lines | if ((byte & 0x80) == 0) { | ||||
switch (byte) { | switch (byte) { | ||||
case 0xb0: | case 0xb0: | ||||
finish = true; | finish = true; | ||||
break; | break; | ||||
case 0xb1: { | case 0xb1: { | ||||
if (offset >= len) | if (offset >= len) | ||||
return _URC_FAILURE; | return _URC_FAILURE; | ||||
uint8_t registers = getByte(data, offset++); | uint8_t registers = getByte(data, offset++); | ||||
if (registers & 0xf0 || !registers) | if (registers & 0xf0 || !registers) | ||||
mstorsjo: This particular change looks unrelated to the rest, on a quick glance | |||||
Indeed, that change is a leftover from when the encoding of the instruction to pop return address authentication code was <0xb1,0x00> chill: Indeed, that change is a leftover from when the encoding of the instruction to pop return… | |||||
return _URC_FAILURE; | return _URC_FAILURE; | ||||
_Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32); | _Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32); | ||||
break; | break; | ||||
} | } | ||||
case 0xb2: { | case 0xb2: { | ||||
uint32_t addend = 0; | uint32_t addend = 0; | ||||
uint32_t shift = 0; | uint32_t shift = 0; | ||||
// This decodes a uleb128 value. | // This decodes a uleb128 value. | ||||
Show All 17 Lines | if ((byte & 0x80) == 0) { | ||||
case 0xb3: { | case 0xb3: { | ||||
uint8_t v = getByte(data, offset++); | uint8_t v = getByte(data, offset++); | ||||
_Unwind_VRS_Pop(context, _UVRSC_VFP, | _Unwind_VRS_Pop(context, _UVRSC_VFP, | ||||
RegisterRange(static_cast<uint8_t>(v >> 4), | RegisterRange(static_cast<uint8_t>(v >> 4), | ||||
v & 0x0f), _UVRSD_VFPX); | v & 0x0f), _UVRSD_VFPX); | ||||
break; | break; | ||||
} | } | ||||
case 0xb4: | case 0xb4: | ||||
hasReturnAddrAuthCode = true; | |||||
_Unwind_VRS_Pop(context, _UVRSC_PSEUDO, | |||||
0 /* Return Address Auth Code */, _UVRSD_UINT32); | |||||
break; | |||||
case 0xb5: | case 0xb5: | ||||
case 0xb6: | case 0xb6: | ||||
case 0xb7: | case 0xb7: | ||||
return _URC_FAILURE; | return _URC_FAILURE; | ||||
default: | default: | ||||
_Unwind_VRS_Pop(context, _UVRSC_VFP, | _Unwind_VRS_Pop(context, _UVRSC_VFP, | ||||
RegisterRange(8, byte & 0x07), _UVRSD_VFPX); | RegisterRange(8, byte & 0x07), _UVRSD_VFPX); | ||||
break; | break; | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | #endif | ||||
default: | default: | ||||
return _URC_FAILURE; | return _URC_FAILURE; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if (!wrotePC) { | if (!wrotePC) { | ||||
uint32_t lr; | uint32_t lr; | ||||
_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_LR, _UVRSD_UINT32, &lr); | _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_LR, _UVRSD_UINT32, &lr); | ||||
#ifdef __ARM_FEATURE_PAUTH | |||||
if (hasReturnAddrAuthCode) { | |||||
uint32_t sp; | |||||
uint32_t pac; | |||||
_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); | |||||
_Unwind_VRS_Get(context, _UVRSC_PSEUDO, UNW_ARM_RA_AUTH_CODE, | |||||
_UVRSD_UINT32, &pac); | |||||
__asm__ __volatile__("autg %0, %1, %2" : : "r"(pac), "r"(lr), "r"(sp) :); | |||||
} | |||||
#endif | |||||
_Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr); | _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr); | ||||
} | } | ||||
return _URC_CONTINUE_UNWIND; | return _URC_CONTINUE_UNWIND; | ||||
} | } | ||||
extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code | extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code | ||||
__aeabi_unwind_cpp_pr0(_Unwind_State state, _Unwind_Control_Block *ucbp, | __aeabi_unwind_cpp_pr0(_Unwind_State state, _Unwind_Control_Block *ucbp, | ||||
_Unwind_Context *context) { | _Unwind_Context *context) { | ||||
▲ Show 20 Lines • Show All 503 Lines • ▼ Show 20 Lines | case _UVRSC_WMMXD: | ||||
*(unw_fpreg_t *)valuep) == UNW_ESUCCESS | *(unw_fpreg_t *)valuep) == UNW_ESUCCESS | ||||
? _UVRSR_OK | ? _UVRSR_OK | ||||
: _UVRSR_FAILED; | : _UVRSR_FAILED; | ||||
#else | #else | ||||
case _UVRSC_WMMXC: | case _UVRSC_WMMXC: | ||||
case _UVRSC_WMMXD: | case _UVRSC_WMMXD: | ||||
break; | break; | ||||
#endif | #endif | ||||
case _UVRSC_PSEUDO: | |||||
// There's only one pseudo-register, PAC, with regno == 0. | |||||
if (representation != _UVRSD_UINT32 || regno != 0) | |||||
return _UVRSR_FAILED; | |||||
return __unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_RA_AUTH_CODE), | |||||
*(unw_word_t *)valuep) == UNW_ESUCCESS | |||||
? _UVRSR_OK | |||||
: _UVRSR_FAILED; | |||||
break; | |||||
} | } | ||||
_LIBUNWIND_ABORT("unsupported register class"); | _LIBUNWIND_ABORT("unsupported register class"); | ||||
} | } | ||||
static _Unwind_VRS_Result | static _Unwind_VRS_Result | ||||
_Unwind_VRS_Get_Internal(_Unwind_Context *context, | _Unwind_VRS_Get_Internal(_Unwind_Context *context, | ||||
_Unwind_VRS_RegClass regclass, uint32_t regno, | _Unwind_VRS_RegClass regclass, uint32_t regno, | ||||
_Unwind_VRS_DataRepresentation representation, | _Unwind_VRS_DataRepresentation representation, | ||||
Show All 38 Lines | case _UVRSC_WMMXD: | ||||
(unw_fpreg_t *)valuep) == UNW_ESUCCESS | (unw_fpreg_t *)valuep) == UNW_ESUCCESS | ||||
? _UVRSR_OK | ? _UVRSR_OK | ||||
: _UVRSR_FAILED; | : _UVRSR_FAILED; | ||||
#else | #else | ||||
case _UVRSC_WMMXC: | case _UVRSC_WMMXC: | ||||
case _UVRSC_WMMXD: | case _UVRSC_WMMXD: | ||||
break; | break; | ||||
#endif | #endif | ||||
case _UVRSC_PSEUDO: | |||||
// There's only one pseudo-register, PAC, with regno == 0. | |||||
if (representation != _UVRSD_UINT32 || regno != 0) | |||||
return _UVRSR_FAILED; | |||||
return __unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_RA_AUTH_CODE), | |||||
(unw_word_t *)valuep) == UNW_ESUCCESS | |||||
? _UVRSR_OK | |||||
: _UVRSR_FAILED; | |||||
break; | |||||
} | } | ||||
_LIBUNWIND_ABORT("unsupported register class"); | _LIBUNWIND_ABORT("unsupported register class"); | ||||
} | } | ||||
_LIBUNWIND_EXPORT _Unwind_VRS_Result | _LIBUNWIND_EXPORT _Unwind_VRS_Result | ||||
_Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, | _Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, | ||||
uint32_t regno, _Unwind_VRS_DataRepresentation representation, | uint32_t regno, _Unwind_VRS_DataRepresentation representation, | ||||
void *valuep) { | void *valuep) { | ||||
▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | #endif | ||||
_UVRSR_OK) | _UVRSR_OK) | ||||
return _UVRSR_FAILED; | return _UVRSR_FAILED; | ||||
} | } | ||||
if (representation == _UVRSD_VFPX) | if (representation == _UVRSD_VFPX) | ||||
++sp; | ++sp; | ||||
return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, | return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, | ||||
&sp); | &sp); | ||||
} | } | ||||
case _UVRSC_PSEUDO: { | |||||
if (representation != _UVRSD_UINT32 || discriminator != 0) | |||||
return _UVRSR_FAILED; | |||||
// Return Address Authentication code (PAC) - discriminator 0 | |||||
uint32_t *sp; | |||||
if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, | |||||
&sp) != _UVRSR_OK) { | |||||
return _UVRSR_FAILED; | |||||
} | |||||
uint32_t pac = *sp++; | |||||
_Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); | |||||
return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_RA_AUTH_CODE, | |||||
_UVRSD_UINT32, &pac); | |||||
} | |||||
} | } | ||||
_LIBUNWIND_ABORT("unsupported register class"); | _LIBUNWIND_ABORT("unsupported register class"); | ||||
} | } | ||||
/// Not used by C++. | /// Not used by C++. | ||||
/// Unwinds stack, calling "stop" function at each frame. | /// Unwinds stack, calling "stop" function at each frame. | ||||
/// Could be used to implement longjmp(). | /// Could be used to implement longjmp(). | ||||
_LIBUNWIND_EXPORT _Unwind_Reason_Code | _LIBUNWIND_EXPORT _Unwind_Reason_Code | ||||
▲ Show 20 Lines • Show All 58 Lines • Show Last 20 Lines |
This particular change looks unrelated to the rest, on a quick glance