mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-10-28 10:45:48 +08:00
libunwind: update to LLVM 23
This commit is contained in:
18 files changed
+248
-80
No files matched your search
+1
-1
@@ -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__)
|
||||
|
||||
Vendored
+1
-1
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Vendored
-1
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
Vendored
-1
@@ -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
@@ -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.
|
||||
|
||||
Vendored
+17
-6
@@ -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) {
|
||||
|
||||
Vendored
+20
-3
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+119
-7
@@ -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 ®isters) {
|
||||
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
@@ -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)
|
||||
|
||||
Vendored
+1
-1
@@ -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
@@ -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
@@ -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__)
|
||||
|
||||
Vendored
+15
-19
@@ -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)",
|
||||
|
||||
Vendored
+2
-2
@@ -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);
|
||||
|
||||
|
||||
Reference in new issue
Block a user