libunwind: update to LLVM 18

release/18.x branch, commit 78b99c73ee4b96fe9ce0e294d4632326afb2db42
This commit is contained in:
Andrew Kelley 2024-04-26 14:40:08 -07:00
parent a6856ef6d2
commit 6295415da7
17 changed files with 393 additions and 132 deletions

View File

@ -36,6 +36,9 @@
# if defined(__linux__) # if defined(__linux__)
# define _LIBUNWIND_TARGET_LINUX 1 # define _LIBUNWIND_TARGET_LINUX 1
# endif # endif
# if defined(__HAIKU__)
# define _LIBUNWIND_TARGET_HAIKU 1
# endif
# if defined(__i386__) # if defined(__i386__)
# define _LIBUNWIND_TARGET_I386 # define _LIBUNWIND_TARGET_I386
# define _LIBUNWIND_CONTEXT_SIZE 8 # define _LIBUNWIND_CONTEXT_SIZE 8

View File

@ -876,6 +876,9 @@ enum {
UNW_MIPS_F29 = 61, UNW_MIPS_F29 = 61,
UNW_MIPS_F30 = 62, UNW_MIPS_F30 = 62,
UNW_MIPS_F31 = 63, UNW_MIPS_F31 = 63,
// HI,LO have been dropped since r6, we keep them here.
// So, when we add DSP/MSA etc, we can use the same register indexes
// for r6 and pre-r6.
UNW_MIPS_HI = 64, UNW_MIPS_HI = 64,
UNW_MIPS_LO = 65, UNW_MIPS_LO = 65,
}; };

View File

@ -372,7 +372,7 @@ enum {
// .quad except_tab1 // .quad except_tab1
// //
// //
// Notes: There is no need for any labels in the the __compact_unwind section. // Notes: There is no need for any labels in the __compact_unwind section.
// The use of the .set directive is to force the evaluation of the // The use of the .set directive is to force the evaluation of the
// range-length at assembly time, instead of generating relocations. // range-length at assembly time, instead of generating relocations.
// //

View File

@ -414,8 +414,8 @@ static bool checkForUnwindInfoSegment(const Elf_Phdr *phdr, size_t image_base,
cbdata->sects->dwarf_index_section = eh_frame_hdr_start; cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
cbdata->sects->dwarf_index_section_length = phdr->p_memsz; cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
if (EHHeaderParser<LocalAddressSpace>::decodeEHHdr( if (EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
*cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, *cbdata->addressSpace, eh_frame_hdr_start,
hdrInfo)) { eh_frame_hdr_start + phdr->p_memsz, hdrInfo)) {
// .eh_frame_hdr records the start of .eh_frame, but not its size. // .eh_frame_hdr records the start of .eh_frame, but not its size.
// Rely on a zero terminator to find the end of the section. // Rely on a zero terminator to find the end of the section.
cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
@ -638,7 +638,8 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
info.dwarf_index_section_length = SIZE_MAX; info.dwarf_index_section_length = SIZE_MAX;
EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo; EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
if (!EHHeaderParser<LocalAddressSpace>::decodeEHHdr( if (!EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
*this, info.dwarf_index_section, info.dwarf_index_section_length, *this, info.dwarf_index_section,
info.dwarf_index_section + info.dwarf_index_section_length,
hdrInfo)) { hdrInfo)) {
return false; return false;
} }

View File

@ -55,6 +55,19 @@ template <typename A>
bool EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart, bool EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) { pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) {
pint_t p = ehHdrStart; pint_t p = ehHdrStart;
// Ensure that we don't read data beyond the end of .eh_frame_hdr
if (ehHdrEnd - ehHdrStart < 4) {
// Don't print a message for an empty .eh_frame_hdr (this can happen if
// the linker script defines symbols for it even in the empty case).
if (ehHdrEnd == ehHdrStart)
return false;
_LIBUNWIND_LOG("unsupported .eh_frame_hdr at %" PRIx64
": need at least 4 bytes of data but only got %zd",
static_cast<uint64_t>(ehHdrStart),
static_cast<size_t>(ehHdrEnd - ehHdrStart));
return false;
}
uint8_t version = addressSpace.get8(p++); uint8_t version = addressSpace.get8(p++);
if (version != 1) { if (version != 1) {
_LIBUNWIND_LOG("unsupported .eh_frame_hdr version: %" PRIu8 " at %" PRIx64, _LIBUNWIND_LOG("unsupported .eh_frame_hdr version: %" PRIu8 " at %" PRIx64,

View File

@ -31,8 +31,8 @@
class _LIBUNWIND_HIDDEN FrameHeaderCache { class _LIBUNWIND_HIDDEN FrameHeaderCache {
struct CacheEntry { struct CacheEntry {
uintptr_t LowPC() { return Info.dso_base; }; uintptr_t LowPC() { return Info.dso_base; }
uintptr_t HighPC() { return Info.dso_base + Info.text_segment_length; }; uintptr_t HighPC() { return Info.dso_base + Info.text_segment_length; }
UnwindInfoSections Info; UnwindInfoSections Info;
CacheEntry *Next; CacheEntry *Next;
}; };
@ -41,7 +41,7 @@ class _LIBUNWIND_HIDDEN FrameHeaderCache {
// Can't depend on the C++ standard library in libunwind, so use an array to // Can't depend on the C++ standard library in libunwind, so use an array to
// allocate the entries, and two linked lists for ordering unused and recently // allocate the entries, and two linked lists for ordering unused and recently
// used entries. FIXME: Would the the extra memory for a doubly-linked list // used entries. FIXME: Would the extra memory for a doubly-linked list
// be better than the runtime cost of traversing a very short singly-linked // be better than the runtime cost of traversing a very short singly-linked
// list on a cache miss? The entries themselves are all small and consecutive, // list on a cache miss? The entries themselves are all small and consecutive,
// so unlikely to cause page faults when following the pointers. The memory // so unlikely to cause page faults when following the pointers. The memory

View File

@ -619,6 +619,8 @@ public:
void setIP(uint32_t value) { _registers.__srr0 = value; } void setIP(uint32_t value) { _registers.__srr0 = value; }
uint64_t getCR() const { return _registers.__cr; } uint64_t getCR() const { return _registers.__cr; }
void setCR(uint32_t value) { _registers.__cr = value; } void setCR(uint32_t value) { _registers.__cr = value; }
uint64_t getLR() const { return _registers.__lr; }
void setLR(uint32_t value) { _registers.__lr = value; }
private: private:
struct ppc_thread_state_t { struct ppc_thread_state_t {
@ -1189,6 +1191,8 @@ public:
void setIP(uint64_t value) { _registers.__srr0 = value; } void setIP(uint64_t value) { _registers.__srr0 = value; }
uint64_t getCR() const { return _registers.__cr; } uint64_t getCR() const { return _registers.__cr; }
void setCR(uint64_t value) { _registers.__cr = value; } void setCR(uint64_t value) { _registers.__cr = value; }
uint64_t getLR() const { return _registers.__lr; }
void setLR(uint64_t value) { _registers.__lr = value; }
private: private:
struct ppc64_thread_state_t { struct ppc64_thread_state_t {
@ -2869,7 +2873,7 @@ inline bool Registers_mips_o32::validRegister(int regNum) const {
return false; return false;
if (regNum <= UNW_MIPS_R31) if (regNum <= UNW_MIPS_R31)
return true; return true;
#if __mips_isa_rev != 6 #if __mips_isa_rev < 6
if (regNum == UNW_MIPS_HI) if (regNum == UNW_MIPS_HI)
return true; return true;
if (regNum == UNW_MIPS_LO) if (regNum == UNW_MIPS_LO)
@ -2903,10 +2907,12 @@ inline uint32_t Registers_mips_o32::getRegister(int regNum) const {
return _registers.__pc; return _registers.__pc;
case UNW_REG_SP: case UNW_REG_SP:
return _registers.__r[29]; return _registers.__r[29];
#if __mips_isa_rev < 6
case UNW_MIPS_HI: case UNW_MIPS_HI:
return _registers.__hi; return _registers.__hi;
case UNW_MIPS_LO: case UNW_MIPS_LO:
return _registers.__lo; return _registers.__lo;
#endif
} }
_LIBUNWIND_ABORT("unsupported mips_o32 register"); _LIBUNWIND_ABORT("unsupported mips_o32 register");
} }
@ -2936,11 +2942,13 @@ inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
case UNW_REG_SP: case UNW_REG_SP:
_registers.__r[29] = value; _registers.__r[29] = value;
return; return;
#if __mips_isa_rev < 6
case UNW_MIPS_HI: case UNW_MIPS_HI:
_registers.__hi = value; _registers.__hi = value;
return; return;
case UNW_MIPS_LO: case UNW_MIPS_LO:
_registers.__lo = value; _registers.__lo = value;
#endif
return; return;
} }
_LIBUNWIND_ABORT("unsupported mips_o32 register"); _LIBUNWIND_ABORT("unsupported mips_o32 register");
@ -3120,10 +3128,12 @@ inline const char *Registers_mips_o32::getRegisterName(int regNum) {
return "$f30"; return "$f30";
case UNW_MIPS_F31: case UNW_MIPS_F31:
return "$f31"; return "$f31";
#if __mips_isa_rev < 6
case UNW_MIPS_HI: case UNW_MIPS_HI:
return "$hi"; return "$hi";
case UNW_MIPS_LO: case UNW_MIPS_LO:
return "$lo"; return "$lo";
#endif
default: default:
return "unknown register"; return "unknown register";
} }
@ -3193,7 +3203,7 @@ inline bool Registers_mips_newabi::validRegister(int regNum) const {
return false; return false;
if (regNum <= UNW_MIPS_R31) if (regNum <= UNW_MIPS_R31)
return true; return true;
#if __mips_isa_rev != 6 #if __mips_isa_rev < 6
if (regNum == UNW_MIPS_HI) if (regNum == UNW_MIPS_HI)
return true; return true;
if (regNum == UNW_MIPS_LO) if (regNum == UNW_MIPS_LO)
@ -3212,10 +3222,12 @@ inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {
return _registers.__pc; return _registers.__pc;
case UNW_REG_SP: case UNW_REG_SP:
return _registers.__r[29]; return _registers.__r[29];
#if __mips_isa_rev < 6
case UNW_MIPS_HI: case UNW_MIPS_HI:
return _registers.__hi; return _registers.__hi;
case UNW_MIPS_LO: case UNW_MIPS_LO:
return _registers.__lo; return _registers.__lo;
#endif
} }
_LIBUNWIND_ABORT("unsupported mips_newabi register"); _LIBUNWIND_ABORT("unsupported mips_newabi register");
} }
@ -3233,12 +3245,14 @@ inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {
case UNW_REG_SP: case UNW_REG_SP:
_registers.__r[29] = value; _registers.__r[29] = value;
return; return;
#if __mips_isa_rev < 6
case UNW_MIPS_HI: case UNW_MIPS_HI:
_registers.__hi = value; _registers.__hi = value;
return; return;
case UNW_MIPS_LO: case UNW_MIPS_LO:
_registers.__lo = value; _registers.__lo = value;
return; return;
#endif
} }
_LIBUNWIND_ABORT("unsupported mips_newabi register"); _LIBUNWIND_ABORT("unsupported mips_newabi register");
} }
@ -3417,10 +3431,12 @@ inline const char *Registers_mips_newabi::getRegisterName(int regNum) {
return "$f30"; return "$f30";
case UNW_MIPS_F31: case UNW_MIPS_F31:
return "$f31"; return "$f31";
#if __mips_isa_rev < 6
case UNW_MIPS_HI: case UNW_MIPS_HI:
return "$hi"; return "$hi";
case UNW_MIPS_LO: case UNW_MIPS_LO:
return "$lo"; return "$lo";
#endif
default: default:
return "unknown register"; return "unknown register";
} }

View File

@ -82,7 +82,8 @@ struct _Unwind_FunctionContext {
static _LIBUNWIND_THREAD_LOCAL struct _Unwind_FunctionContext *stack = NULL; static _LIBUNWIND_THREAD_LOCAL struct _Unwind_FunctionContext *stack = NULL;
#endif #endif
static struct _Unwind_FunctionContext *__Unwind_SjLj_GetTopOfFunctionStack() { static struct _Unwind_FunctionContext *
__Unwind_SjLj_GetTopOfFunctionStack(void) {
#if defined(__APPLE__) #if defined(__APPLE__)
return _pthread_getspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key); return _pthread_getspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key);
#else #else
@ -426,7 +427,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context,
/// Called by personality handler during phase 2 to alter register values. /// Called by personality handler during phase 2 to alter register values.
_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index, _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
uintptr_t new_value) { uintptr_t new_value) {
_LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%" PRIuPTR _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%" PRIxPTR
")", ")",
(void *)context, index, new_value); (void *)context, index, new_value);
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
@ -437,7 +438,7 @@ _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
/// Called by personality handler during phase 2 to get instruction pointer. /// Called by personality handler during phase 2 to get instruction pointer.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
_LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIu32, _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR,
(void *)context, ufc->resumeLocation + 1); (void *)context, ufc->resumeLocation + 1);
return ufc->resumeLocation + 1; return ufc->resumeLocation + 1;
} }
@ -450,7 +451,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
int *ipBefore) { int *ipBefore) {
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
*ipBefore = 0; *ipBefore = 0;
_LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%" PRIu32, _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%" PRIxPTR,
(void *)context, (void *)ipBefore, (void *)context, (void *)ipBefore,
ufc->resumeLocation + 1); ufc->resumeLocation + 1);
return ufc->resumeLocation + 1; return ufc->resumeLocation + 1;
@ -460,7 +461,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
/// Called by personality handler during phase 2 to alter instruction pointer. /// Called by personality handler during phase 2 to alter instruction pointer.
_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context, _LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
uintptr_t new_value) { uintptr_t new_value) {
_LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%" PRIuPTR ")", _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%" PRIxPTR ")",
(void *)context, new_value); (void *)context, new_value);
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context; _Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
ufc->resumeLocation = new_value - 1; ufc->resumeLocation = new_value - 1;

123
lib/libunwind/src/Unwind-wasm.c vendored Normal file
View File

@ -0,0 +1,123 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// Implements Wasm exception handling proposal
// (https://github.com/WebAssembly/exception-handling) based C++ exceptions
//
//===----------------------------------------------------------------------===//
#include <stdbool.h>
#include "config.h"
#ifdef __USING_WASM_EXCEPTIONS__
#include "unwind.h"
#include <threads.h>
_Unwind_Reason_Code __gxx_personality_wasm0(int version, _Unwind_Action actions,
uint64_t exceptionClass,
_Unwind_Exception *unwind_exception,
_Unwind_Context *context);
struct _Unwind_LandingPadContext {
// Input information to personality function
uintptr_t lpad_index; // landing pad index
uintptr_t lsda; // LSDA address
// Output information computed by personality function
uintptr_t selector; // selector value
};
// Communication channel between compiler-generated user code and personality
// function
thread_local struct _Unwind_LandingPadContext __wasm_lpad_context;
/// Calls to this function is in landing pads in compiler-generated user code.
/// In other EH schemes, stack unwinding is done by libunwind library, which
/// calls the personality function for each each frame it lands. On the other
/// hand, WebAssembly stack unwinding process is performed by a VM, and the
/// personality function cannot be called from there. So the compiler inserts
/// a call to this function in landing pads in the user code, which in turn
/// calls the personality function.
_Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) {
struct _Unwind_Exception *exception_object =
(struct _Unwind_Exception *)exception_ptr;
_LIBUNWIND_TRACE_API("_Unwind_CallPersonality(exception_object=%p)",
(void *)exception_object);
// Reset the selector.
__wasm_lpad_context.selector = 0;
// Call personality function. Wasm does not have two-phase unwinding, so we
// only do the cleanup phase.
return __gxx_personality_wasm0(
1, _UA_SEARCH_PHASE, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)&__wasm_lpad_context);
}
/// Called by __cxa_throw.
_LIBUNWIND_EXPORT _Unwind_Reason_Code
_Unwind_RaiseException(_Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("_Unwind_RaiseException(exception_object=%p)",
(void *)exception_object);
// Use Wasm EH's 'throw' instruction.
__builtin_wasm_throw(0, exception_object);
}
/// Called by __cxa_end_catch.
_LIBUNWIND_EXPORT void
_Unwind_DeleteException(_Unwind_Exception *exception_object) {
_LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
(void *)(exception_object));
if (exception_object->exception_cleanup != NULL)
(*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
exception_object);
}
/// Called by personality handler to alter register values.
_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
uintptr_t value) {
_LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, index=%d, value=%lu)",
(void *)context, index, value);
// We only use this function to set __wasm_lpad_context.selector field, which
// is index 1 in the personality function.
if (index == 1)
((struct _Unwind_LandingPadContext *)context)->selector = value;
}
/// Called by personality handler to get instruction pointer.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
// The result will be used as an 1-based index after decrementing 1, so we
// increment 2 here
uintptr_t result =
((struct _Unwind_LandingPadContext *)context)->lpad_index + 2;
_LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => %lu", (void *)context,
result);
return result;
}
/// Not used in Wasm.
_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
_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
uintptr_t result = ((struct _Unwind_LandingPadContext *)context)->lsda;
_LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) => 0x%lx",
(void *)context, result);
return result;
}
/// Not used in Wasm.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetRegionStart(struct _Unwind_Context *context) {
return 0;
}
#endif // defined(__USING_WASM_EXCEPTIONS__)

View File

@ -33,6 +33,8 @@
#if defined(_LIBUNWIND_TARGET_LINUX) && \ #if defined(_LIBUNWIND_TARGET_LINUX) && \
(defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_RISCV) || \ (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_RISCV) || \
defined(_LIBUNWIND_TARGET_S390X)) defined(_LIBUNWIND_TARGET_S390X))
#include <errno.h>
#include <signal.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <unistd.h> #include <unistd.h>
@ -990,6 +992,7 @@ private:
R dummy; R dummy;
return stepThroughSigReturn(dummy); return stepThroughSigReturn(dummy);
} }
bool isReadableAddr(const pint_t addr) const;
#if defined(_LIBUNWIND_TARGET_AARCH64) #if defined(_LIBUNWIND_TARGET_AARCH64)
bool setInfoForSigReturn(Registers_arm64 &); bool setInfoForSigReturn(Registers_arm64 &);
int stepThroughSigReturn(Registers_arm64 &); int stepThroughSigReturn(Registers_arm64 &);
@ -2301,27 +2304,39 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
if (!getFunctionName(functionBuf, sizeof(functionBuf), &offset)) { if (!getFunctionName(functionBuf, sizeof(functionBuf), &offset)) {
functionName = ".anonymous."; functionName = ".anonymous.";
} }
_LIBUNWIND_TRACE_UNWINDING("%s: Look up traceback table of func=%s at %p", _LIBUNWIND_TRACE_UNWINDING(
__func__, functionName, "%s: Look up traceback table of func=%s at %p, pc=%p, "
reinterpret_cast<void *>(TBTable)); "SP=%p, saves_lr=%d, stores_bc=%d",
__func__, functionName, reinterpret_cast<void *>(TBTable),
reinterpret_cast<void *>(pc),
reinterpret_cast<void *>(registers.getSP()), TBTable->tb.saves_lr,
TBTable->tb.stores_bc);
} }
#if defined(__powerpc64__) #if defined(__powerpc64__)
// Instruction to reload TOC register "l r2,40(r1)" // Instruction to reload TOC register "ld r2,40(r1)"
const uint32_t loadTOCRegInst = 0xe8410028; const uint32_t loadTOCRegInst = 0xe8410028;
const int32_t unwPPCF0Index = UNW_PPC64_F0; const int32_t unwPPCF0Index = UNW_PPC64_F0;
const int32_t unwPPCV0Index = UNW_PPC64_V0; const int32_t unwPPCV0Index = UNW_PPC64_V0;
#else #else
// Instruction to reload TOC register "l r2,20(r1)" // Instruction to reload TOC register "lwz r2,20(r1)"
const uint32_t loadTOCRegInst = 0x80410014; const uint32_t loadTOCRegInst = 0x80410014;
const int32_t unwPPCF0Index = UNW_PPC_F0; const int32_t unwPPCF0Index = UNW_PPC_F0;
const int32_t unwPPCV0Index = UNW_PPC_V0; const int32_t unwPPCV0Index = UNW_PPC_V0;
#endif #endif
// lastStack points to the stack frame of the next routine up.
pint_t curStack = static_cast<pint_t>(registers.getSP());
pint_t lastStack = *reinterpret_cast<pint_t *>(curStack);
if (lastStack == 0)
return UNW_STEP_END;
R newRegisters = registers; R newRegisters = registers;
// lastStack points to the stack frame of the next routine up. // If backchain is not stored, use the current stack frame.
pint_t lastStack = *(reinterpret_cast<pint_t *>(registers.getSP())); if (!TBTable->tb.stores_bc)
lastStack = curStack;
// Return address is the address after call site instruction. // Return address is the address after call site instruction.
pint_t returnAddress; pint_t returnAddress;
@ -2331,33 +2346,41 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
reinterpret_cast<void *>(lastStack)); reinterpret_cast<void *>(lastStack));
sigcontext *sigContext = reinterpret_cast<sigcontext *>( sigcontext *sigContext = reinterpret_cast<sigcontext *>(
reinterpret_cast<char *>(lastStack) + STKMIN);
returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;
_LIBUNWIND_TRACE_UNWINDING("From sigContext=%p, returnAddress=%p\n",
reinterpret_cast<void *>(sigContext),
reinterpret_cast<void *>(returnAddress));
if (returnAddress < 0x10000000) {
// Try again using STKMINALIGN
sigContext = reinterpret_cast<sigcontext *>(
reinterpret_cast<char *>(lastStack) + STKMINALIGN); reinterpret_cast<char *>(lastStack) + STKMINALIGN);
returnAddress = sigContext->sc_jmpbuf.jmp_context.iar; returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;
bool useSTKMIN = false;
if (returnAddress < 0x10000000) { if (returnAddress < 0x10000000) {
_LIBUNWIND_TRACE_UNWINDING("Bad returnAddress=%p\n", // Try again using STKMIN.
reinterpret_cast<void *>(returnAddress)); sigContext = reinterpret_cast<sigcontext *>(
reinterpret_cast<char *>(lastStack) + STKMIN);
returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;
if (returnAddress < 0x10000000) {
_LIBUNWIND_TRACE_UNWINDING("Bad returnAddress=%p from sigcontext=%p",
reinterpret_cast<void *>(returnAddress),
reinterpret_cast<void *>(sigContext));
return UNW_EBADFRAME; return UNW_EBADFRAME;
} else { }
_LIBUNWIND_TRACE_UNWINDING("Tried again using STKMINALIGN: " useSTKMIN = true;
}
_LIBUNWIND_TRACE_UNWINDING("Returning from a signal handler %s: "
"sigContext=%p, returnAddress=%p. " "sigContext=%p, returnAddress=%p. "
"Seems to be a valid address\n", "Seems to be a valid address",
useSTKMIN ? "STKMIN" : "STKMINALIGN",
reinterpret_cast<void *>(sigContext), reinterpret_cast<void *>(sigContext),
reinterpret_cast<void *>(returnAddress)); reinterpret_cast<void *>(returnAddress));
}
}
// Restore the condition register from sigcontext. // Restore the condition register from sigcontext.
newRegisters.setCR(sigContext->sc_jmpbuf.jmp_context.cr); newRegisters.setCR(sigContext->sc_jmpbuf.jmp_context.cr);
// Save the LR in sigcontext for stepping up when the function that
// raised the signal is a leaf function. This LR has the return address
// to the caller of the leaf function.
newRegisters.setLR(sigContext->sc_jmpbuf.jmp_context.lr);
_LIBUNWIND_TRACE_UNWINDING(
"Save LR=%p from sigcontext",
reinterpret_cast<void *>(sigContext->sc_jmpbuf.jmp_context.lr));
// Restore GPRs from sigcontext. // Restore GPRs from sigcontext.
for (int i = 0; i < 32; ++i) for (int i = 0; i < 32; ++i)
newRegisters.setRegister(i, sigContext->sc_jmpbuf.jmp_context.gpr[i]); newRegisters.setRegister(i, sigContext->sc_jmpbuf.jmp_context.gpr[i]);
@ -2380,13 +2403,26 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
} }
} else { } else {
// Step up a normal frame. // Step up a normal frame.
returnAddress = reinterpret_cast<pint_t *>(lastStack)[2];
_LIBUNWIND_TRACE_UNWINDING("Extract info from lastStack=%p, " if (!TBTable->tb.saves_lr && registers.getLR()) {
"returnAddress=%p\n", // This case should only occur if we were called from a signal handler
// and the signal occurred in a function that doesn't save the LR.
returnAddress = static_cast<pint_t>(registers.getLR());
_LIBUNWIND_TRACE_UNWINDING("Use saved LR=%p",
reinterpret_cast<void *>(returnAddress));
} else {
// Otherwise, use the LR value in the stack link area.
returnAddress = reinterpret_cast<pint_t *>(lastStack)[2];
}
// Reset LR in the current context.
newRegisters.setLR(NULL);
_LIBUNWIND_TRACE_UNWINDING(
"Extract info from lastStack=%p, returnAddress=%p",
reinterpret_cast<void *>(lastStack), reinterpret_cast<void *>(lastStack),
reinterpret_cast<void *>(returnAddress)); reinterpret_cast<void *>(returnAddress));
_LIBUNWIND_TRACE_UNWINDING("fpr_regs=%d, gpr_regs=%d, saves_cr=%d\n", _LIBUNWIND_TRACE_UNWINDING("fpr_regs=%d, gpr_regs=%d, saves_cr=%d",
TBTable->tb.fpr_saved, TBTable->tb.gpr_saved, TBTable->tb.fpr_saved, TBTable->tb.gpr_saved,
TBTable->tb.saves_cr); TBTable->tb.saves_cr);
@ -2450,7 +2486,7 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
struct vec_ext *vec_ext = reinterpret_cast<struct vec_ext *>(charPtr); struct vec_ext *vec_ext = reinterpret_cast<struct vec_ext *>(charPtr);
_LIBUNWIND_TRACE_UNWINDING("vr_saved=%d\n", vec_ext->vr_saved); _LIBUNWIND_TRACE_UNWINDING("vr_saved=%d", vec_ext->vr_saved);
// Restore vector register(s) if saved on the stack. // Restore vector register(s) if saved on the stack.
if (vec_ext->vr_saved) { if (vec_ext->vr_saved) {
@ -2480,11 +2516,11 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
// Do we need to set the TOC register? // Do we need to set the TOC register?
_LIBUNWIND_TRACE_UNWINDING( _LIBUNWIND_TRACE_UNWINDING(
"Current gpr2=%p\n", "Current gpr2=%p",
reinterpret_cast<void *>(newRegisters.getRegister(2))); reinterpret_cast<void *>(newRegisters.getRegister(2)));
if (firstInstruction == loadTOCRegInst) { if (firstInstruction == loadTOCRegInst) {
_LIBUNWIND_TRACE_UNWINDING( _LIBUNWIND_TRACE_UNWINDING(
"Set gpr2=%p from frame\n", "Set gpr2=%p from frame",
reinterpret_cast<void *>(reinterpret_cast<pint_t *>(lastStack)[5])); reinterpret_cast<void *>(reinterpret_cast<pint_t *>(lastStack)[5]));
newRegisters.setRegister(2, reinterpret_cast<pint_t *>(lastStack)[5]); newRegisters.setRegister(2, reinterpret_cast<pint_t *>(lastStack)[5]);
} }
@ -2516,7 +2552,6 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
} else { } else {
isSignalFrame = false; isSignalFrame = false;
} }
return UNW_STEP_SUCCESS; return UNW_STEP_SUCCESS;
} }
#endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND) #endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
@ -2668,20 +2703,12 @@ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {
// [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/vdso/sigreturn.S // [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/vdso/sigreturn.S
const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP)); const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
// The PC might contain an invalid address if the unwind info is bad, so // The PC might contain an invalid address if the unwind info is bad, so
// directly accessing it could cause a segfault. Use process_vm_readv to read // directly accessing it could cause a SIGSEGV.
// the memory safely instead. process_vm_readv was added in Linux 3.2, and if (!isReadableAddr(pc))
// AArch64 supported was added in Linux 3.7, so the syscall is guaranteed to return false;
// be present. Unfortunately, there are Linux AArch64 environments where the auto *instructions = reinterpret_cast<const uint32_t *>(pc);
// libc wrapper for the syscall might not be present (e.g. Android 5), so call
// the syscall directly instead.
uint32_t instructions[2];
struct iovec local_iov = {&instructions, sizeof instructions};
struct iovec remote_iov = {reinterpret_cast<void *>(pc), sizeof instructions};
long bytesRead =
syscall(SYS_process_vm_readv, getpid(), &local_iov, 1, &remote_iov, 1, 0);
// Look for instructions: mov x8, #0x8b; svc #0x0 // Look for instructions: mov x8, #0x8b; svc #0x0
if (bytesRead != sizeof instructions || instructions[0] != 0xd2801168 || if (instructions[0] != 0xd2801168 || instructions[1] != 0xd4000001)
instructions[1] != 0xd4000001)
return false; return false;
_info = {}; _info = {};
@ -2730,18 +2757,17 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {
template <typename A, typename R> template <typename A, typename R>
bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_riscv &) { bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_riscv &) {
const pint_t pc = static_cast<pint_t>(getReg(UNW_REG_IP)); const pint_t pc = static_cast<pint_t>(getReg(UNW_REG_IP));
uint32_t instructions[2]; // The PC might contain an invalid address if the unwind info is bad, so
struct iovec local_iov = {&instructions, sizeof instructions}; // directly accessing it could cause a SIGSEGV.
struct iovec remote_iov = {reinterpret_cast<void *>(pc), sizeof instructions}; if (!isReadableAddr(pc))
long bytesRead = return false;
syscall(SYS_process_vm_readv, getpid(), &local_iov, 1, &remote_iov, 1, 0); const auto *instructions = reinterpret_cast<const uint32_t *>(pc);
// Look for the two instructions used in the sigreturn trampoline // Look for the two instructions used in the sigreturn trampoline
// __vdso_rt_sigreturn: // __vdso_rt_sigreturn:
// //
// 0x08b00893 li a7,0x8b // 0x08b00893 li a7,0x8b
// 0x00000073 ecall // 0x00000073 ecall
if (bytesRead != sizeof instructions || instructions[0] != 0x08b00893 || if (instructions[0] != 0x08b00893 || instructions[1] != 0x00000073)
instructions[1] != 0x00000073)
return false; return false;
_info = {}; _info = {};
@ -2790,13 +2816,11 @@ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_s390x &) {
// onto the stack. // onto the stack.
const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP)); const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
// The PC might contain an invalid address if the unwind info is bad, so // The PC might contain an invalid address if the unwind info is bad, so
// directly accessing it could cause a segfault. Use process_vm_readv to // directly accessing it could cause a SIGSEGV.
// read the memory safely instead. if (!isReadableAddr(pc))
uint16_t inst; return false;
struct iovec local_iov = {&inst, sizeof inst}; const auto inst = *reinterpret_cast<const uint16_t *>(pc);
struct iovec remote_iov = {reinterpret_cast<void *>(pc), sizeof inst}; if (inst == 0x0a77 || inst == 0x0aad) {
long bytesRead = process_vm_readv(getpid(), &local_iov, 1, &remote_iov, 1, 0);
if (bytesRead == sizeof inst && (inst == 0x0a77 || inst == 0x0aad)) {
_info = {}; _info = {};
_info.start_ip = pc; _info.start_ip = pc;
_info.end_ip = pc + 2; _info.end_ip = pc + 2;
@ -2942,6 +2966,37 @@ bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen,
buf, bufLen, offset); buf, bufLen, offset);
} }
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
template <typename A, typename R>
bool UnwindCursor<A, R>::isReadableAddr(const pint_t addr) const {
// We use SYS_rt_sigprocmask, inspired by Abseil's AddressIsReadable.
const auto sigsetAddr = reinterpret_cast<sigset_t *>(addr);
// We have to check that addr is nullptr because sigprocmask allows that
// as an argument without failure.
if (!sigsetAddr)
return false;
const auto saveErrno = errno;
// We MUST use a raw syscall here, as wrappers may try to access
// sigsetAddr which may cause a SIGSEGV. A raw syscall however is
// safe. Additionally, we need to pass the kernel_sigset_size, which is
// different from libc sizeof(sigset_t). For the majority of architectures,
// it's 64 bits (_NSIG), and libc NSIG is _NSIG + 1.
const auto kernelSigsetSize = NSIG / 8;
[[maybe_unused]] const int Result = syscall(
SYS_rt_sigprocmask, /*how=*/~0, sigsetAddr, nullptr, kernelSigsetSize);
// Because our "how" is invalid, this syscall should always fail, and our
// errno should always be EINVAL or an EFAULT. This relies on the Linux
// kernel to check copy_from_user before checking if the "how" argument is
// invalid.
assert(Result == -1);
assert(errno == EFAULT || errno == EINVAL);
const auto readable = errno != EFAULT;
errno = saveErrno;
return readable;
}
#endif
#if defined(_LIBUNWIND_USE_CET) #if defined(_LIBUNWIND_USE_CET)
extern "C" void *__libunwind_cet_get_registers(unw_cursor_t *cursor) { extern "C" void *__libunwind_cet_get_registers(unw_cursor_t *cursor) {
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;

View File

@ -143,7 +143,7 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
// Create a mock exception object for force unwinding. // Create a mock exception object for force unwinding.
_Unwind_Exception ex; _Unwind_Exception ex;
memset(&ex, '\0', sizeof(ex)); memset(&ex, '\0', sizeof(ex));
strcpy((char *)&ex.exception_class, "CLNGUNW"); memcpy(&ex.exception_class, "CLNGUNW", sizeof(ex.exception_class));
#endif #endif
// walk each frame // walk each frame

View File

@ -673,7 +673,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
ldr d30, [x0, #0x200] ldr d30, [x0, #0x200]
ldr d31, [x0, #0x208] ldr d31, [x0, #0x208]
// Finally, restore sp. This must be done after the the last read from the // Finally, restore sp. This must be done after the last read from the
// context struct, because it is allocated on the stack, and an exception // context struct, because it is allocated on the stack, and an exception
// could clobber the de-allocated portion of the stack after sp has been // could clobber the de-allocated portion of the stack after sp has been
// restored. // restored.
@ -993,11 +993,13 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv)
ldc1 $f31, (4 * 36 + 8 * 31)($4) ldc1 $f31, (4 * 36 + 8 * 31)($4)
#endif #endif
#endif #endif
#if __mips_isa_rev < 6
// restore hi and lo // restore hi and lo
lw $8, (4 * 33)($4) lw $8, (4 * 33)($4)
mthi $8 mthi $8
lw $8, (4 * 34)($4) lw $8, (4 * 34)($4)
mtlo $8 mtlo $8
#endif
// r0 is zero // r0 is zero
lw $1, (4 * 1)($4) lw $1, (4 * 1)($4)
lw $2, (4 * 2)($4) lw $2, (4 * 2)($4)
@ -1054,11 +1056,13 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv)
ldc1 $f\i, (280+8*\i)($4) ldc1 $f\i, (280+8*\i)($4)
.endr .endr
#endif #endif
#if __mips_isa_rev < 6
// restore hi and lo // restore hi and lo
ld $8, (8 * 33)($4) ld $8, (8 * 33)($4)
mthi $8 mthi $8
ld $8, (8 * 34)($4) ld $8, (8 * 34)($4)
mtlo $8 mtlo $8
#endif
// r0 is zero // r0 is zero
ld $1, (8 * 1)($4) ld $1, (8 * 1)($4)
ld $2, (8 * 2)($4) ld $2, (8 * 2)($4)

View File

@ -174,11 +174,13 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
sw $31, (4 * 31)($4) sw $31, (4 * 31)($4)
# Store return address to pc # Store return address to pc
sw $31, (4 * 32)($4) sw $31, (4 * 32)($4)
#if __mips_isa_rev < 6
# hi and lo # hi and lo
mfhi $8 mfhi $8
sw $8, (4 * 33)($4) sw $8, (4 * 33)($4)
mflo $8 mflo $8
sw $8, (4 * 34)($4) sw $8, (4 * 34)($4)
#endif
#ifdef __mips_hard_float #ifdef __mips_hard_float
#if __mips_fpr != 64 #if __mips_fpr != 64
sdc1 $f0, (4 * 36 + 8 * 0)($4) sdc1 $f0, (4 * 36 + 8 * 0)($4)
@ -255,11 +257,13 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
.endr .endr
# Store return address to pc # Store return address to pc
sd $31, (8 * 32)($4) sd $31, (8 * 32)($4)
#if __mips_isa_rev < 6
# hi and lo # hi and lo
mfhi $8 mfhi $8
sd $8, (8 * 33)($4) sd $8, (8 * 33)($4)
mflo $8 mflo $8
sd $8, (8 * 34)($4) sd $8, (8 * 34)($4)
#endif
#ifdef __mips_hard_float #ifdef __mips_hard_float
.irp i,FROM_0_TO_31 .irp i,FROM_0_TO_31
sdc1 $f\i, (280+8*\i)($4) sdc1 $f\i, (280+8*\i)($4)
@ -301,9 +305,21 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
mflr 0 mflr 0
std 0, PPC64_OFFS_SRR0(3) // store lr as ssr0 std 0, PPC64_OFFS_SRR0(3) // store lr as ssr0
PPC64_STR(1) PPC64_STR(1)
PPC64_STR(4) // Save r4 first since it will be used for fixing r2.
#if defined(_AIX)
// The TOC register (r2) was changed by the glue code if unw_getcontext
// is called from a different module. Save the original TOC register
// in the context if this is the case.
mflr 4
lwz 4, 0(4) // Get the first instruction at the return address.
xoris 0, 4, 0xe841 // Is it reloading the TOC register "ld 2,40(1)"?
cmplwi 0, 0x28
bne 0, LnoR2Fix // No need to fix up r2 if it is not.
ld 2, 40(1) // Use the saved TOC register in the stack.
LnoR2Fix:
#endif
PPC64_STR(2) PPC64_STR(2)
PPC64_STR(3) PPC64_STR(3)
PPC64_STR(4)
PPC64_STR(5) PPC64_STR(5)
PPC64_STR(6) PPC64_STR(6)
PPC64_STR(7) PPC64_STR(7)
@ -336,7 +352,12 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
std 0, PPC64_OFFS_CR(3) std 0, PPC64_OFFS_CR(3)
mfxer 0 mfxer 0
std 0, PPC64_OFFS_XER(3) std 0, PPC64_OFFS_XER(3)
#if defined(_AIX)
// LR value saved from the register is not used, initialize it to 0.
li 0, 0
#else
mflr 0 mflr 0
#endif
std 0, PPC64_OFFS_LR(3) std 0, PPC64_OFFS_LR(3)
mfctr 0 mfctr 0
std 0, PPC64_OFFS_CTR(3) std 0, PPC64_OFFS_CTR(3)
@ -543,9 +564,21 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
mflr 0 mflr 0
stw 0, 0(3) // store lr as ssr0 stw 0, 0(3) // store lr as ssr0
stw 1, 12(3) stw 1, 12(3)
stw 4, 24(3) // Save r4 first since it will be used for fixing r2.
#if defined(_AIX)
// The TOC register (r2) was changed by the glue code if unw_getcontext
// is called from a different module. Save the original TOC register
// in the context if this is the case.
mflr 4
lwz 4, 0(4) // Get the instruction at the return address.
xoris 0, 4, 0x8041 // Is it reloading the TOC register "lwz 2,20(1)"?
cmplwi 0, 0x14
bne 0, LnoR2Fix // No need to fix up r2 if it is not.
lwz 2, 20(1) // Use the saved TOC register in the stack.
LnoR2Fix:
#endif
stw 2, 16(3) stw 2, 16(3)
stw 3, 20(3) stw 3, 20(3)
stw 4, 24(3)
stw 5, 28(3) stw 5, 28(3)
stw 6, 32(3) stw 6, 32(3)
stw 7, 36(3) stw 7, 36(3)
@ -582,6 +615,11 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
// save CR registers // save CR registers
mfcr 0 mfcr 0
stw 0, 136(3) stw 0, 136(3)
#if defined(_AIX)
// LR value from the register is not used, initialize it to 0.
li 0, 0
stw 0, 144(3)
#endif
// save CTR register // save CTR register
mfctr 0 mfctr 0
stw 0, 148(3) stw 0, 148(3)

View File

@ -46,6 +46,12 @@
#elif defined(_AIX) #elif defined(_AIX)
// The traceback table at the end of each function is used for unwinding. // The traceback table at the end of each function is used for unwinding.
#define _LIBUNWIND_SUPPORT_TBTAB_UNWIND 1 #define _LIBUNWIND_SUPPORT_TBTAB_UNWIND 1
#elif defined(__HAIKU__)
#if defined(_LIBUNWIND_USE_HAIKU_BSD_LIB)
#define _LIBUNWIND_USE_DL_ITERATE_PHDR 1
#endif
#define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
#define _LIBUNWIND_SUPPORT_DWARF_INDEX 1
#else #else
// Assume an ELF system with a dl_iterate_phdr function. // Assume an ELF system with a dl_iterate_phdr function.
#define _LIBUNWIND_USE_DL_ITERATE_PHDR 1 #define _LIBUNWIND_USE_DL_ITERATE_PHDR 1
@ -83,7 +89,7 @@
__asm__(".globl " SYMBOL_NAME(aliasname)); \ __asm__(".globl " SYMBOL_NAME(aliasname)); \
__asm__(SYMBOL_NAME(aliasname) " = " SYMBOL_NAME(name)); \ __asm__(SYMBOL_NAME(aliasname) " = " SYMBOL_NAME(name)); \
_LIBUNWIND_ALIAS_VISIBILITY(SYMBOL_NAME(aliasname)) _LIBUNWIND_ALIAS_VISIBILITY(SYMBOL_NAME(aliasname))
#elif defined(__ELF__) || defined(_AIX) #elif defined(__ELF__) || defined(_AIX) || defined(__wasm__)
#define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \ #define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \
extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \ extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \
__attribute__((weak, alias(#name))); __attribute__((weak, alias(#name)));
@ -108,10 +114,6 @@
#define _LIBUNWIND_BUILD_SJLJ_APIS #define _LIBUNWIND_BUILD_SJLJ_APIS
#endif #endif
#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__)
#define _LIBUNWIND_SUPPORT_FRAME_APIS
#endif
#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || \ #if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || \
(!defined(__APPLE__) && defined(__arm__)) || defined(__aarch64__) || \ (!defined(__APPLE__) && defined(__arm__)) || defined(__aarch64__) || \
defined(__mips__) || defined(__riscv) || defined(__hexagon__) || \ defined(__mips__) || defined(__riscv) || defined(__hexagon__) || \
@ -125,7 +127,7 @@
#if defined(_LIBUNWIND_REMEMBER_STACK_ALLOC) || defined(__APPLE__) || \ #if defined(_LIBUNWIND_REMEMBER_STACK_ALLOC) || defined(__APPLE__) || \
defined(__linux__) || defined(__ANDROID__) || defined(__MINGW32__) || \ defined(__linux__) || defined(__ANDROID__) || defined(__MINGW32__) || \
defined(_LIBUNWIND_IS_BAREMETAL) defined(_LIBUNWIND_IS_BAREMETAL)
#define _LIBUNWIND_REMEMBER_ALLOC(_size) alloca(_size) #define _LIBUNWIND_REMEMBER_ALLOC(_size) __builtin_alloca(_size)
#define _LIBUNWIND_REMEMBER_FREE(_ptr) \ #define _LIBUNWIND_REMEMBER_FREE(_ptr) \
do { \ do { \
} while (0) } while (0)

View File

@ -26,7 +26,7 @@
#include <sanitizer/asan_interface.h> #include <sanitizer/asan_interface.h>
#endif #endif
#if !defined(__USING_SJLJ_EXCEPTIONS__) #if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
#include "AddressSpace.hpp" #include "AddressSpace.hpp"
#include "UnwindCursor.hpp" #include "UnwindCursor.hpp"
@ -324,7 +324,7 @@ void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo; CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo; CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
auto p = (LocalAddressSpace::pint_t)eh_frame_start; auto p = (LocalAddressSpace::pint_t)eh_frame_start;
while (true) { while (LocalAddressSpace::sThisAddressSpace.get32(p)) {
if (CFI_Parser<LocalAddressSpace>::decodeFDE( if (CFI_Parser<LocalAddressSpace>::decodeFDE(
LocalAddressSpace::sThisAddressSpace, p, &fdeInfo, &cieInfo, LocalAddressSpace::sThisAddressSpace, p, &fdeInfo, &cieInfo,
true) == NULL) { true) == NULL) {
@ -347,7 +347,8 @@ void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
} }
#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
#endif // !defined(__USING_SJLJ_EXCEPTIONS__) #endif // !defined(__USING_SJLJ_EXCEPTIONS__) &&
// !defined(__USING_WASM_EXCEPTIONS__)
#ifdef __APPLE__ #ifdef __APPLE__

View File

@ -164,6 +164,7 @@ const unwind_src_list = [_][]const u8{
"libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindLevel1.c", "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindLevel1.c",
"libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindLevel1-gcc-ext.c", "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindLevel1-gcc-ext.c",
"libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-sjlj.c", "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-sjlj.c",
"libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-wasm.c",
"libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersRestore.S", "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersRestore.S",
"libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersSave.S", "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersSave.S",
"libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind_AIXExtras.cpp", "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind_AIXExtras.cpp",