libunwind: update to LLVM 23

This commit is contained in:
Alex Rønne Petersen committed 2026-10-07 00:30:51 +02:00
1 parent f689d3cf27
commit a04355206b
18 files changed
+248 -80

No files matched your search

+1 -1
View File
@@ -9,7 +9,7 @@
#ifndef ____LIBUNWIND_CONFIG_H__
#define ____LIBUNWIND_CONFIG_H__
#define _LIBUNWIND_VERSION 15000
#define _LIBUNWIND_VERSION 230000
#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \
!defined(__ARM_DWARF_EH__) && !defined(__SEH__)
+1 -1
View File
@@ -122,7 +122,7 @@
__unwind_ptrauth_restricted_intptr(ptrauth_key_function_pointer, 1, \
__ptrauth_unwind_cie_info_personality_disc)
// ptrauth_string_discriminator("personality") == 0x7EAD)
// ptrauth_string_discriminator("personality") == 0x7EAD
#define __ptrauth_unwind_pauthtest_personality_disc 0x7EAD
#else
+1 -1
View File
@@ -443,7 +443,7 @@ struct unwind_info_section_header_lsda_index_entry
struct unwind_info_regular_second_level_entry
{
uint32_t functionOffset;
uint32_t functionOffset;
compact_unwind_encoding_t encoding;
};
+1 -1
View File
@@ -32,7 +32,7 @@ struct _Unwind_Exception {
// The implementation of _Unwind_Exception uses an attribute mode on the
// above fields which has the side effect of causing this whole struct to
// round up to 32 bytes in size (48 with SEH). To be more explicit, we add
// pad fields added for binary compatibility.
// pad fields for binary compatibility.
uint32_t reserved[3];
#endif
// The Itanium ABI requires that _Unwind_Exception objects are "double-word
-1
View File
@@ -666,7 +666,6 @@ inline bool LocalAddressSpace::findUnwindSections(
return true;
}
#endif
// zig patch: https://github.com/llvm/llvm-project/issues/194228
dl_iterate_cb_data cb_data = {this, &info, static_cast<pint_t>(targetAddr)};
int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data);
return static_cast<bool>(found);
+5 -4
View File
@@ -12,6 +12,7 @@
#ifndef __COMPACT_UNWINDER_HPP__
#define __COMPACT_UNWINDER_HPP__
#include <inttypes.h>
#include <stdint.h>
#include <stdlib.h>
@@ -335,8 +336,8 @@ int CompactUnwinder_x86_64<A>::stepWithCompactEncodingRBPFrame(
default:
(void)functionStart;
_LIBUNWIND_DEBUG_LOG("bad register for RBP frame, encoding=%08X for "
"function starting at 0x%llX",
compactEncoding, functionStart);
"function starting at 0x%" PRIu64 "X",
compactEncoding, functionStart);
_LIBUNWIND_ABORT("invalid compact unwind encoding");
}
savedRegisters += 8;
@@ -454,8 +455,8 @@ int CompactUnwinder_x86_64<A>::stepWithCompactEncodingFrameless(
break;
default:
_LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for "
"function starting at 0x%llX",
encoding, functionStart);
"function starting at 0x%" PRIu64 "X",
encoding, functionStart);
_LIBUNWIND_ABORT("invalid compact unwind encoding");
}
savedRegisters += 8;
+17 -26
View File
@@ -76,10 +76,14 @@ private:
__builtin_unreachable();
}
#if defined(_LIBUNWIND_TARGET_AARCH64)
static bool isReturnAddressSigned(A &addressSpace, R registers, pint_t cfa,
PrologInfo &prolog);
static bool isReturnAddressSignedWithPC(A &addressSpace, R registers,
pint_t cfa, PrologInfo &prolog);
enum RASignStatus {
RANotSigned = 0,
RASigned = 1,
RASignedWithPC = 2,
};
static RASignStatus getReturnAddressSignStatus(A &addressSpace, R registers,
pint_t cfa,
PrologInfo &prolog);
#endif
};
@@ -177,7 +181,8 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister(
}
#if defined(_LIBUNWIND_TARGET_AARCH64)
template <typename A, typename R>
bool DwarfInstructions<A, R>::isReturnAddressSigned(A &addressSpace,
typename DwarfInstructions<A, R>::RASignStatus
DwarfInstructions<A, R>::getReturnAddressSignStatus(A &addressSpace,
R registers, pint_t cfa,
PrologInfo &prolog) {
pint_t raSignState;
@@ -187,24 +192,9 @@ bool DwarfInstructions<A, R>::isReturnAddressSigned(A &addressSpace,
else
raSignState = getSavedRegister(addressSpace, registers, cfa, regloc);
// Only bit[0] is meaningful.
return raSignState & 0x01;
}
template <typename A, typename R>
bool DwarfInstructions<A, R>::isReturnAddressSignedWithPC(A &addressSpace,
R registers,
pint_t cfa,
PrologInfo &prolog) {
pint_t raSignState;
auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE];
if (regloc.location == CFI_Parser<A>::kRegisterUnused)
raSignState = static_cast<pint_t>(regloc.value);
else
raSignState = getSavedRegister(addressSpace, registers, cfa, regloc);
// Only bit[1] is meaningful.
return raSignState & 0x02;
// bits[1:0] describe how RA is signed.
assert((raSignState & 0x3) != 3 && "unexpected RA sign state");
return static_cast<RASignStatus>(raSignState & 0x3);
}
#endif
@@ -317,8 +307,9 @@ int DwarfInstructions<A, R>::stepWithDwarf(
// return address needs to be authenticated before the return address is
// restored. autia1716 is used instead of autia as autia1716 assembles
// to a NOP on pre-v8.3a architectures.
if ((R::getArch() == REGISTERS_ARM64) &&
isReturnAddressSigned(addressSpace, registers, cfa, prolog) &&
RASignStatus RAState =
getReturnAddressSignStatus(addressSpace, registers, cfa, prolog);
if ((R::getArch() == REGISTERS_ARM64) && RAState != RANotSigned &&
returnAddress != 0) {
#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
return UNW_ECROSSRASIGNING;
@@ -329,7 +320,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(
// We use the hint versions of the authentication instructions below to
// ensure they're assembled by the compiler even for targets with no
// FEAT_PAuth/FEAT_PAuth_LR support.
if (isReturnAddressSignedWithPC(addressSpace, registers, cfa, prolog)) {
if (RAState == RASignedWithPC) {
register unsigned long long x15 __asm("x15") =
prolog.ptrAuthDiversifier;
if (cieInfo.addressesSignedWithBKey) {
-1
View File
@@ -473,7 +473,6 @@ bool CFI_Parser<A>::parseFDEInstructions(
pint_t pcoffset;
};
// zig patch: https://github.com/llvm/llvm-project/issues/194228
ParseInfo parseInfoArray[] = {
{cieInfo.cieInstructions, cieInfo.cieStart + cieInfo.cieLength,
(pint_t)(-1)},
+1 -1
View File
@@ -24,7 +24,7 @@
#define _LIBUNWIND_FRAMEHEADERCACHE_TRACE(msg, ...)
#endif
// This cache should only be be used from within a dl_iterate_phdr callback.
// This cache should only be used from within a dl_iterate_phdr callback.
// dl_iterate_phdr does the necessary synchronization to prevent problems
// with concurrent access via the libc load lock. Adding synchronization
// for other uses is possible, but not currently done.
+17 -6
View File
@@ -20,6 +20,9 @@
#include "libunwind_ext.h"
#include "shadow_stack_unwind.h"
#if defined(__APPLE__)
#include <sys/sysctl.h>
#endif
#if defined(_LIBUNWIND_HAVE_GETAUXVAL) || defined(_LIBUNWIND_HAVE_ELF_AUX_INFO)
#include <sys/auxv.h>
#endif
@@ -1892,7 +1895,7 @@ public:
uint64_t value = _registers.__pc;
#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
// Note the value of the PC was signed to its address in the register state
// but everyone else expects it to be sign by the SP, so convert on return.
// but everyone else expects it to be signed by the SP, so convert on return.
value = (uint64_t)ptrauth_auth_and_resign((void *)_registers.__pc,
ptrauth_key_return_address,
&_registers.__pc,
@@ -1940,7 +1943,15 @@ private:
_LIBUNWIND_ABORT("SME ZA disable failed");
}
#if defined(_LIBUNWIND_HAVE_GETAUXVAL)
#if defined(__APPLE__)
static bool checkHasSME() {
int has_sme = 0;
size_t size = sizeof(has_sme);
if (sysctlbyname("hw.optional.arm.FEAT_SME", &has_sme, &size, NULL, 0))
return false;
return has_sme != 0;
}
#elif defined(_LIBUNWIND_HAVE_GETAUXVAL)
static bool checkHasSME() {
constexpr int hwcap2_sme = (1 << 23);
unsigned long hwcap2 = getauxval(AT_HWCAP2);
@@ -3724,21 +3735,21 @@ inline void Registers_sparc::setRegister(int regNum, uint32_t value) {
inline bool Registers_sparc::validFloatRegister(int) const { return false; }
inline double Registers_sparc::getFloatRegister(int) const {
_LIBUNWIND_ABORT("no Sparc float registers");
_LIBUNWIND_ABORT("no sparc float registers");
}
inline void Registers_sparc::setFloatRegister(int, double) {
_LIBUNWIND_ABORT("no Sparc float registers");
_LIBUNWIND_ABORT("no sparc float registers");
}
inline bool Registers_sparc::validVectorRegister(int) const { return false; }
inline v128 Registers_sparc::getVectorRegister(int) const {
_LIBUNWIND_ABORT("no Sparc vector registers");
_LIBUNWIND_ABORT("no sparc vector registers");
}
inline void Registers_sparc::setVectorRegister(int, v128) {
_LIBUNWIND_ABORT("no Sparc vector registers");
_LIBUNWIND_ABORT("no sparc vector registers");
}
inline const char *Registers_sparc::getRegisterName(int regNum) {
+20 -3
View File
@@ -54,7 +54,7 @@ _Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) {
__wasm_lpad_context.selector = 0;
// Call personality function. Wasm does not have two-phase unwinding, so we
// only do the cleanup phase.
// only do the search phase.
return __gxx_personality_wasm0(
1, _UA_SEARCH_PHASE, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)&__wasm_lpad_context);
@@ -69,6 +69,21 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) {
__builtin_wasm_throw(0, exception_object);
}
// Define the `__cpp_exception` symbol which `__builtin_wasm_throw` above will
// reference. This is defined here in `libunwind` as the single canonical
// definition for this API and it's required for users to ensure that there's
// only one copy of `libunwind` within a wasm module to ensure this is only
// defined once and exactly once.
__asm__(".globl __cpp_exception\n"
#if defined(__wasm32__)
".tagtype __cpp_exception i32\n"
#elif defined(__wasm64__)
".tagtype __cpp_exception i64\n"
#else
#error "Unsupported Wasm architecture"
#endif
"__cpp_exception:\n");
/// Called by __cxa_end_catch.
_LIBUNWIND_EXPORT void
_Unwind_DeleteException(_Unwind_Exception *exception_object) {
@@ -102,7 +117,8 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
}
/// Not used in Wasm.
_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t) {}
_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
uintptr_t value) {}
/// Called by personality handler to get LSDA for current frame.
_LIBUNWIND_EXPORT uintptr_t
@@ -114,7 +130,8 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
}
/// Not used in Wasm.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *) {
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetRegionStart(struct _Unwind_Context *context) {
return 0;
}
+119 -7
View File
@@ -963,7 +963,7 @@ template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {
/// UnwindCursor contains all state (including all register values) during
/// an unwind. This is normally stack allocated inside a unw_cursor_t.
template <typename A, typename R>
class UnwindCursor : public AbstractUnwindCursor{
class UnwindCursor : public AbstractUnwindCursor {
typedef typename A::pint_t pint_t;
public:
UnwindCursor(unw_context_t *context, A &as);
@@ -1363,6 +1363,10 @@ private:
reinterpret_cast<tbtable *>(_info.unwind_info),
_registers, _isSignalFrame);
}
bool isKnownVapiNotActive() const { return _isKnownVapiNotActive; }
void setIsKnownVapiNotActive(bool val) { _isKnownVapiNotActive = val; }
static pint_t getVAPILR();
#endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
A &_addressSpace;
@@ -1377,13 +1381,23 @@ private:
#ifdef _LIBUNWIND_TRACE_RET_INJECT
uint32_t _walkedFrames;
#endif
#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
// TODO: this will need to be recorded in the unw_context_t by unw_getcontext
// to support cases where the cursor is retrieved prior to invocation of the
// Virtual API.
bool _isKnownVapiNotActive;
#endif
};
template <typename A, typename R>
UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
: _addressSpace(as), _registers(context), _unwindInfoMissing(false),
_isSignalFrame(false) {
_isSignalFrame(false)
#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
,
_isKnownVapiNotActive(false)
#endif
{
static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
"UnwindCursor<> does not fit in unw_cursor_t");
static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)),
@@ -1393,13 +1407,17 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
template <typename A, typename R>
UnwindCursor<A, R>::UnwindCursor(A &as, void *)
: _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) {
: _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false)
#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
,
_isKnownVapiNotActive(false)
#endif
{
memset(static_cast<void *>(&_info), 0, sizeof(_info));
// FIXME
// fill in _registers from thread arg
}
template <typename A, typename R>
bool UnwindCursor<A, R>::validReg(int regNum) {
return _registers.validRegister(regNum);
@@ -1469,6 +1487,30 @@ template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
static constexpr size_t _EXTRA_LIBUNWIND_FRAMES_WALKED = 5 - 1;
_registers.returnto(_walkedFrames + _EXTRA_LIBUNWIND_FRAMES_WALKED);
#else
#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
if (isKnownVapiNotActive()) {
// If the current frame is known VAPI not active, execute the VAPI return
// glue to clear the VAPI control block. The VAPI return glue is used by
// AIX longjmp based on the VAPI active status recorded by setjmp in the
// jmp_buf, which means that the VAPI return glue can be called solely on
// the basis of the VAPI active status of the target context.
// VAPI return glue address is the VAPI glue address - 4.
#ifdef __64BIT__
constexpr pint_t VAPIReturnGlue = 0x8e40 - 4;
#else
constexpr pint_t VAPIReturnGlue = 0x8c40 - 4;
#endif
_LIBUNWIND_TRACE_UNWINDING("VAPI: executing return glue %p\n",
reinterpret_cast<void *>(VAPIReturnGlue));
register auto *registers __asm__("r30") = &_registers;
__asm__ __volatile__("bla %[retglue]"
: "+r"(registers)
: [retglue] "i"(VAPIReturnGlue));
registers->jumpto();
}
#endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
_registers.jumpto();
#endif
}
@@ -2037,7 +2079,7 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(
if (personalityIndex != 0) {
--personalityIndex; // change 1-based to zero-based index
if (personalityIndex >= sectionHeader.personalityArrayCount()) {
_LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, "
_LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, "
"but personality table has only %d entries",
encoding, personalityIndex,
sectionHeader.personalityArrayCount());
@@ -2459,6 +2501,45 @@ bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R &registers) {
return true;
}
// VAPI glue addresses
constexpr uintptr_t vapi_glue_addr_ext_32 = 0x8b80;
constexpr uintptr_t vapi_addr_64 = 0x8e00;
constexpr size_t vapi_size_64 = 0x0200;
constexpr uintptr_t vapi_glue_addr_begin =
vapi_glue_addr_ext_32; // Start address in 32-bit
constexpr uintptr_t vapi_glue_addr_end =
vapi_addr_64 + vapi_size_64; // End address in 64-bit
#ifdef __64BIT__
constexpr size_t VAPI_CB_SIZE = 256;
constexpr ptrdiff_t TLS_POINTER_OFFSET = 30 * 1024;
constexpr size_t TLSCB_BASE_SIZE = 256;
static __inline__ __attribute__((__always_inline__)) char *tptr(void) {
char *result;
__asm__("mr %0, 13" : "=r"(result));
return result;
}
#else // 32-bit
constexpr size_t VAPI_CB_SIZE = 128;
constexpr ptrdiff_t TLS_POINTER_OFFSET = 31 * 1024;
constexpr size_t TLSCB_BASE_SIZE = 128;
static __inline__ __attribute__((__always_inline__)) char *tptr(void) {
char *result;
__asm__("mfspr %0, 259" : "=r"(result));
return result;
}
#endif
constexpr ptrdiff_t VAPI_CB_OFFSET =
TLS_POINTER_OFFSET + VAPI_CB_SIZE + TLSCB_BASE_SIZE;
template <typename A, typename R>
typename UnwindCursor<A, R>::pint_t UnwindCursor<A, R>::getVAPILR() {
return *reinterpret_cast<pint_t *>(tptr() - VAPI_CB_OFFSET + 8);
}
// Step back up the stack following the frame back link.
template <typename A, typename R>
int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
@@ -2511,6 +2592,16 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
_LIBUNWIND_TRACE_UNWINDING("Possible signal handler frame: lastStack=%p",
reinterpret_cast<void *>(lastStack));
pint_t returnAddressInStack = reinterpret_cast<pint_t *>(lastStack)[2];
if (vapi_glue_addr_begin <= returnAddressInStack &&
returnAddressInStack < vapi_glue_addr_end) {
_LIBUNWIND_TRACE_UNWINDING(
"The return address in stack %p is within the range of VAPI address;"
" set isKnownVapiNotActive to true\n",
reinterpret_cast<void *>(returnAddressInStack));
setIsKnownVapiNotActive(true);
}
sigcontext *sigContext = reinterpret_cast<sigcontext *>(
reinterpret_cast<char *>(lastStack) + STKMINALIGN);
returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;
@@ -2579,6 +2670,17 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
} else {
// Otherwise, use the LR value in the stack link area.
returnAddress = reinterpret_cast<pint_t *>(lastStack)[2];
if (vapi_glue_addr_begin <= returnAddress &&
returnAddress < vapi_glue_addr_end) {
_LIBUNWIND_TRACE_UNWINDING(
"The return address=%p is within the range of VAPI address;",
reinterpret_cast<void *>(returnAddress));
setIsKnownVapiNotActive(true);
returnAddress = getVAPILR();
_LIBUNWIND_TRACE_UNWINDING("return address=%p from VAPI\n",
reinterpret_cast<void *>(returnAddress));
}
}
// Reset LR in the current context.
@@ -2709,6 +2811,16 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
// Return address is the address after call site instruction.
pint_t nextReturnAddress = reinterpret_cast<pint_t *>(nextStack)[2];
if (vapi_glue_addr_begin <= nextReturnAddress &&
nextReturnAddress < vapi_glue_addr_end) {
_LIBUNWIND_TRACE_UNWINDING(
"The next return address=%p is within the range of VAPI address;",
reinterpret_cast<void *>(nextReturnAddress));
nextReturnAddress = getVAPILR();
_LIBUNWIND_TRACE_UNWINDING("the next return address=%p from VAPI\n",
reinterpret_cast<void *>(nextReturnAddress));
}
if (nextReturnAddress > 0x01 && nextReturnAddress < 0x10000) {
_LIBUNWIND_TRACE_UNWINDING("The next is a signal handler frame: "
"nextStack=%p, next return address=%p\n",
@@ -3256,7 +3368,7 @@ int UnwindCursor<A, R>::stepThroughSigReturn() {
template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
(void)stage2;
// Bottom of stack is defined is when unwind info cannot be found.
// Bottom of stack is defined when unwind info cannot be found.
if (_unwindInfoMissing)
return UNW_STEP_END;
+1 -1
View File
@@ -284,7 +284,7 @@ _LIBUNWIND_EXPORT void __deregister_frame(const void *fde) {
// before 10.6 used keymgr to track known FDEs, but these functions
// never got updated to use keymgr.
// For now, we implement these as do-nothing functions to keep any existing
// applications working. We also add the not in 10.6 symbol so that nwe
// applications working. We also add the not in 10.6 symbol so that new
// application won't be able to use them.
#if defined(_LIBUNWIND_SUPPORT_FRAME_APIS)
+1 -1
View File
@@ -14,7 +14,7 @@
// ARM EHABI does not specify _Unwind_{Get,Set}{GR,IP}(). Thus, we are
// defining inline functions to delegate the function calls to
// _Unwind_VRS_{Get,Set}(). However, some applications might declare the
// function protetype directly (instead of including <unwind.h>), thus we need
// function prototype directly (instead of including <unwind.h>), thus we need
// to export these functions from libunwind.so as well.
#define _LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE 1
+18 -1
View File
@@ -678,9 +678,15 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
ldp x18,x19, [x0, #0x090]
ldp x20,x21, [x0, #0x0A0]
ldp x22,x23, [x0, #0x0B0]
#if defined(__LFI__)
ldr x24, [x0, #0x0C0]
// Skip reloading x25-x28; reserved by LFI ABI.
ldr x29, [x0, #0x0E8]
#else
ldp x24,x25, [x0, #0x0C0]
ldp x26,x27, [x0, #0x0D0]
ldp x28,x29, [x0, #0x0E0]
#endif
#if defined(__ARM_FP) && __ARM_FP != 0
ldp d0, d1, [x0, #0x110]
@@ -941,11 +947,22 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv)
#elif defined(__hexagon__)
# On entry:
# thread_state pointer is in r2
# thread_state pointer is in r0
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind17Registers_hexagon6jumptoEv)
#
# void libunwind::Registers_hexagon::jumpto()
#
# The context layout is hexagon_thread_state_t: unsigned int __r[35]
# __r[0..31] = r0..r31, __r[32] = predicates, __r[33] = PC.
# Offsets: __r[n] is at byte offset n*4. r0 is the context pointer, so
# it is restored last; r31 is loaded with the saved PC as the jumpr target.
r2 = memw(r0+#8)
r3 = memw(r0+#12)
r4 = memw(r0+#16)
r5 = memw(r0+#20)
r6 = memw(r0+#24)
r7 = memw(r0+#28)
r8 = memw(r0+#32)
r9 = memw(r0+#36)
r10 = memw(r0+#40)
+28 -3
View File
@@ -794,13 +794,20 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
stp x18,x19, [x0, #0x090]
stp x20,x21, [x0, #0x0A0]
stp x22,x23, [x0, #0x0B0]
#if defined(__LFI__)
str x24, [x0, #0x0C0]
// Skip spilling x25-x28; reserved by LFI ABI.
str x29, [x0, #0x0E8]
#else
stp x24,x25, [x0, #0x0C0]
stp x26,x27, [x0, #0x0D0]
stp x28,x29, [x0, #0x0E0]
#endif
str x30, [x0, #0x0F0]
mov x1,sp
str x1, [x0, #0x0F8]
str x30, [x0, #0x100] // store return address as pc
str xzr, [x0, #0x108] // zero __ra_sign_state
// skip cpsr
#if defined(__ARM_FP) && __ARM_FP != 0
stp d0, d1, [x0, #0x110]
@@ -1096,8 +1103,21 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
# On entry:
# thread_state pointer is in r0
#
# The context layout is hexagon_thread_state_t: unsigned int __r[35]
# __r[0..31] = r0..r31, __r[32] = predicates, __r[33] = PC, __r[34] = unused
# Offsets: __r[n] is at byte offset n*4.
#
#define OFFSET(offset) (offset/4)
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
// Save r1-r7 first (r0 is the context pointer, saved last)
memw(r0+#4) = r1
memw(r0+#8) = r2
memw(r0+#12) = r3
memw(r0+#16) = r4
memw(r0+#20) = r5
memw(r0+#24) = r6
memw(r0+#28) = r7
memw(r0+#32) = r8
memw(r0+#36) = r9
memw(r0+#40) = r10
@@ -1127,12 +1147,17 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
memw(r0+#116) = r29
memw(r0+#120) = r30
memw(r0+#124) = r31
r1 = c4 // Predicate register
r1 = c4 // Predicate register
memw(r0+#128) = r1
r1 = memw(r30) // *FP == Saved FP
r1 = r31
r1 = r31 // Store return address as PC
memw(r0+#132) = r1
// Save r0 (the context pointer itself) last
memw(r0+#0) = r0
r0 = #0 // return UNW_ESUCCESS
jumpr r31
#elif defined(__sparc__) && defined(__arch64__)
+15 -19
View File
@@ -32,7 +32,7 @@
using namespace libunwind;
/// internal object to represent this processes address space
/// internal object to represent this process's address space
LocalAddressSpace LocalAddressSpace::sThisAddressSpace;
_LIBUNWIND_EXPORT unw_addr_space_t unw_local_addr_space =
@@ -131,23 +131,19 @@ _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
{
// It is only valid to set the IP within the current function. This is
// important for ptrauth, otherwise the IP cannot be correctly signed.
// The current signature of `value` is via the schema:
// __ptrauth(ptrauth_key_return_address, <<sp>>, 0)
// For this to be generally usable we manually re-sign it to the
// directly supported schema:
// __ptrauth(ptrauth_key_return_address, 1, 0)
unw_word_t
__unwind_ptrauth_restricted_intptr(ptrauth_key_return_address, 1,
0) authenticated_value;
unw_word_t opaque_value = (uint64_t)ptrauth_auth_and_resign(
(void *)value, ptrauth_key_return_address, sp,
ptrauth_key_return_address, &authenticated_value);
memmove(reinterpret_cast<void *>(&authenticated_value),
reinterpret_cast<void *>(&opaque_value),
sizeof(authenticated_value));
if (authenticated_value < info.start_ip ||
authenticated_value > info.end_ip)
_LIBUNWIND_ABORT("PC vs frame info mismatch");
//
// However many JITs do not configure CFI frames, so we cannot actually
// enforce this - at least not without an extremely expensive syscall.
//
// For the forseeable future this will need to be a debug only assertion
// so we just strip and assert to avoid the unnecessary auths in release
// builds.
unw_word_t stripped_value = (unw_word_t)ptrauth_strip(
(void *)value, ptrauth_key_return_address);
if (stripped_value < info.start_ip && stripped_value > info.end_ip)
_LIBUNWIND_LOG("Badly behaved use of unw_set_reg: moving IP(0x%zX) "
"outside of CFI bounds function (0x%zX, 0x%zX)",
stripped_value, info.start_ip, info.end_ip);
// PC should have been signed with the sp, so we verify that
// roundtripping does not fail. The `ptrauth_auth_and_resign` is
@@ -306,7 +302,7 @@ _LIBUNWIND_HIDDEN int __unw_is_fpreg(unw_cursor_t *cursor,
}
_LIBUNWIND_WEAK_ALIAS(__unw_is_fpreg, unw_is_fpreg)
/// Checks if a register is a floating-point register.
/// Get name of specified register at cursor position in stack frame.
_LIBUNWIND_HIDDEN const char *__unw_regname(unw_cursor_t *cursor,
unw_regnum_t regNum) {
_LIBUNWIND_TRACE_API("__unw_regname(cursor=%p, regNum=%d)",
+2 -2
View File
@@ -120,10 +120,10 @@ typedef int (*unw_find_dynamic_unwind_sections)(
extern int __unw_add_find_dynamic_unwind_sections(
unw_find_dynamic_unwind_sections find_dynamic_unwind_sections);
// Deregister a dynacim unwind-info lookup callback.
// Deregister a dynamic unwind-info lookup callback.
//
// Returns UNW_ESUCCESS for successful deregistrations. If the given callback
// has already been registered then UNW_EINVAL will be returned.
// is not present then UNW_EINVAL will be returned.
extern int __unw_remove_find_dynamic_unwind_sections(
unw_find_dynamic_unwind_sections find_dynamic_unwind_sections);