libunwind: update to LLVM 17

release/17.x branch, commit 8f4dd44097c9ae25dd203d5ac87f3b48f854bba8
This commit is contained in:
Andrew Kelley 2023-08-11 17:19:17 -07:00
parent 6a07b7024a
commit 571a4c86c3
15 changed files with 313 additions and 133 deletions

View File

@ -196,9 +196,9 @@
# define _LIBUNWIND_TARGET_RISCV 1
# define _LIBUNWIND_TARGET_VE 1
# define _LIBUNWIND_TARGET_S390X 1
#define _LIBUNWIND_TARGET_LOONGARCH 1
#define _LIBUNWIND_TARGET_LOONGARCH 1
# define _LIBUNWIND_CONTEXT_SIZE 167
# define _LIBUNWIND_CURSOR_SIZE 179
# define _LIBUNWIND_CURSOR_SIZE 204
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287
#endif // _LIBUNWIND_IS_NATIVE_ONLY

View File

@ -56,9 +56,9 @@ typedef enum {
typedef struct _Unwind_Context _Unwind_Context; // opaque
#if defined(_LIBUNWIND_ARM_EHABI)
#include "unwind_arm_ehabi.h"
#include <unwind_arm_ehabi.h>
#else
#include "unwind_itanium.h"
#include <unwind_itanium.h>
#endif
typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)

View File

@ -66,6 +66,10 @@ char *getFuncNameFromTBTable(uintptr_t pc, uint16_t &NameLen,
// In 10.7.0 or later, libSystem.dylib implements this function.
extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *);
namespace libunwind {
bool findDynamicUnwindSections(void *, unw_dynamic_unwind_sections *);
}
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
// When statically linked on bare-metal, the symbols for the EH table are looked
@ -497,6 +501,22 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
info.compact_unwind_section_length = (size_t)dyldInfo.compact_unwind_section_length;
return true;
}
unw_dynamic_unwind_sections dynamicUnwindSectionInfo;
if (findDynamicUnwindSections((void *)targetAddr,
&dynamicUnwindSectionInfo)) {
info.dso_base = dynamicUnwindSectionInfo.dso_base;
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
info.dwarf_section = (uintptr_t)dynamicUnwindSectionInfo.dwarf_section;
info.dwarf_section_length = dynamicUnwindSectionInfo.dwarf_section_length;
#endif
info.compact_unwind_section =
(uintptr_t)dynamicUnwindSectionInfo.compact_unwind_section;
info.compact_unwind_section_length =
dynamicUnwindSectionInfo.compact_unwind_section_length;
return true;
}
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
info.dso_base = 0;
// Bare metal is statically linked, so no need to ask the dynamic loader

View File

@ -224,7 +224,8 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
p &= ~0xfULL;
// CFA is the bottom of the current stack frame.
for (; p < cfa; p += 16) {
__asm__ __volatile__(".arch_extension memtag\n"
__asm__ __volatile__(".arch armv8.5-a\n"
".arch_extension memtag\n"
"stg %[Ptr], [%[Ptr]]\n"
:
: [Ptr] "r"(p)

View File

@ -709,7 +709,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
// Update info about this frame.
unw_proc_info_t frameInfo;
if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_step "
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_get_proc_info "
"failed => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
@ -885,8 +885,11 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
return result;
}
static uint64_t ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation,
void* valuep) {
// Only used in _LIBUNWIND_TRACE_API, which is a no-op when assertions are
// disabled.
[[gnu::unused]] static uint64_t
ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation,
const void *valuep) {
uint64_t value = 0;
switch (representation) {
case _UVRSD_UINT32:

View File

@ -212,11 +212,20 @@ __libunwind_seh_personality(int version, _Unwind_Action state,
ms_exc.ExceptionInformation[2] = state;
DISPATCHER_CONTEXT *disp_ctx =
__unw_seh_get_disp_ctx((unw_cursor_t *)context);
_LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() calling "
"LanguageHandler %p(%p, %p, %p, %p)",
(void *)disp_ctx->LanguageHandler, (void *)&ms_exc,
(void *)disp_ctx->EstablisherFrame,
(void *)disp_ctx->ContextRecord, (void *)disp_ctx);
EXCEPTION_DISPOSITION ms_act = disp_ctx->LanguageHandler(&ms_exc,
(PVOID)disp_ctx->EstablisherFrame,
disp_ctx->ContextRecord,
disp_ctx);
_LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() LanguageHandler "
"returned %d",
(int)ms_act);
switch (ms_act) {
case ExceptionContinueExecution: return _URC_END_OF_STACK;
case ExceptionContinueSearch: return _URC_CONTINUE_UNWIND;
case 4 /*ExceptionExecuteHandler*/:
return phase2 ? _URC_INSTALL_CONTEXT : _URC_HANDLER_FOUND;
@ -238,7 +247,7 @@ unwind_phase2_forced(unw_context_t *uc,
// Update info about this frame.
unw_proc_info_t frameInfo;
if (__unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_step "
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_get_proc_info "
"failed => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
@ -304,6 +313,12 @@ unwind_phase2_forced(unw_context_t *uc,
// We may get control back if landing pad calls _Unwind_Resume().
__unw_resume(&cursor2);
break;
case _URC_END_OF_STACK:
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
"personality returned "
"_URC_END_OF_STACK",
(void *)exception_object);
break;
default:
// Personality routine returned an unknown result code.
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
@ -312,6 +327,8 @@ unwind_phase2_forced(unw_context_t *uc,
(void *)exception_object, personalityResult);
return _URC_FATAL_PHASE2_ERROR;
}
if (personalityResult == _URC_END_OF_STACK)
break;
}
}

View File

@ -31,7 +31,8 @@
#endif
#if defined(_LIBUNWIND_TARGET_LINUX) && \
(defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_S390X))
(defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_RISCV) || \
defined(_LIBUNWIND_TARGET_S390X))
#include <sys/syscall.h>
#include <sys/uio.h>
#include <unistd.h>
@ -506,7 +507,14 @@ public:
#endif
DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; }
void setDispatcherContext(DISPATCHER_CONTEXT *disp) { _dispContext = *disp; }
void setDispatcherContext(DISPATCHER_CONTEXT *disp) {
_dispContext = *disp;
_info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);
if (_dispContext.LanguageHandler) {
_info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
} else
_info.handler = 0;
}
// libunwind does not and should not depend on C++ library which means that we
// need our own definition of inline placement new.
@ -568,10 +576,12 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
"UnwindCursor<> requires more alignment than unw_cursor_t");
memset(&_info, 0, sizeof(_info));
memset(&_histTable, 0, sizeof(_histTable));
memset(&_dispContext, 0, sizeof(_dispContext));
_dispContext.ContextRecord = &_msContext;
_dispContext.HistoryTable = &_histTable;
// Initialize MS context from ours.
R r(context);
RtlCaptureContext(&_msContext);
_msContext.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_FLOATING_POINT;
#if defined(_LIBUNWIND_TARGET_X86_64)
_msContext.Rax = r.getRegister(UNW_X86_64_RAX);
@ -669,6 +679,7 @@ UnwindCursor<A, R>::UnwindCursor(CONTEXT *context, A &as)
"UnwindCursor<> does not fit in unw_cursor_t");
memset(&_info, 0, sizeof(_info));
memset(&_histTable, 0, sizeof(_histTable));
memset(&_dispContext, 0, sizeof(_dispContext));
_dispContext.ContextRecord = &_msContext;
_dispContext.HistoryTable = &_histTable;
_msContext = *context;
@ -679,7 +690,7 @@ template <typename A, typename R>
bool UnwindCursor<A, R>::validReg(int regNum) {
if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) return true;
#if defined(_LIBUNWIND_TARGET_X86_64)
if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_R15) return true;
if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_RIP) return true;
#elif defined(_LIBUNWIND_TARGET_ARM)
if ((regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) ||
regNum == UNW_ARM_RA_AUTH_CODE)
@ -694,6 +705,7 @@ template <typename A, typename R>
unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
switch (regNum) {
#if defined(_LIBUNWIND_TARGET_X86_64)
case UNW_X86_64_RIP:
case UNW_REG_IP: return _msContext.Rip;
case UNW_X86_64_RAX: return _msContext.Rax;
case UNW_X86_64_RDX: return _msContext.Rdx;
@ -744,6 +756,7 @@ template <typename A, typename R>
void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
switch (regNum) {
#if defined(_LIBUNWIND_TARGET_X86_64)
case UNW_X86_64_RIP:
case UNW_REG_IP: _msContext.Rip = value; break;
case UNW_X86_64_RAX: _msContext.Rax = value; break;
case UNW_X86_64_RDX: _msContext.Rdx = value; break;
@ -981,6 +994,10 @@ private:
bool setInfoForSigReturn(Registers_arm64 &);
int stepThroughSigReturn(Registers_arm64 &);
#endif
#if defined(_LIBUNWIND_TARGET_RISCV)
bool setInfoForSigReturn(Registers_riscv &);
int stepThroughSigReturn(Registers_riscv &);
#endif
#if defined(_LIBUNWIND_TARGET_S390X)
bool setInfoForSigReturn(Registers_s390x &);
int stepThroughSigReturn(Registers_s390x &);
@ -1978,6 +1995,9 @@ bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {
uint32_t lastcode = (xdata->CountOfCodes + 1) & ~1;
const uint32_t *handler = reinterpret_cast<uint32_t *>(&xdata->UnwindCodes[lastcode]);
_info.lsda = reinterpret_cast<unw_word_t>(handler+1);
_dispContext.HandlerData = reinterpret_cast<void *>(_info.lsda);
_dispContext.LanguageHandler =
reinterpret_cast<EXCEPTION_ROUTINE *>(base + *handler);
if (*handler) {
_info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
} else
@ -2705,6 +2725,60 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {
#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
// defined(_LIBUNWIND_TARGET_AARCH64)
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
defined(_LIBUNWIND_TARGET_RISCV)
template <typename A, typename R>
bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_riscv &) {
const pint_t pc = static_cast<pint_t>(getReg(UNW_REG_IP));
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 the two instructions used in the sigreturn trampoline
// __vdso_rt_sigreturn:
//
// 0x08b00893 li a7,0x8b
// 0x00000073 ecall
if (bytesRead != sizeof instructions || instructions[0] != 0x08b00893 ||
instructions[1] != 0x00000073)
return false;
_info = {};
_info.start_ip = pc;
_info.end_ip = pc + 4;
_isSigReturn = true;
return true;
}
template <typename A, typename R>
int UnwindCursor<A, R>::stepThroughSigReturn(Registers_riscv &) {
// In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
// - 128-byte siginfo struct
// - ucontext_t struct:
// - 8-byte long (__uc_flags)
// - 8-byte pointer (*uc_link)
// - 24-byte uc_stack
// - 8-byte uc_sigmask
// - 120-byte of padding to allow sigset_t to be expanded in the future
// - 8 bytes of padding because sigcontext has 16-byte alignment
// - struct sigcontext uc_mcontext
// [1]
// https://github.com/torvalds/linux/blob/master/arch/riscv/kernel/signal.c
const pint_t kOffsetSpToSigcontext = 128 + 8 + 8 + 24 + 8 + 128;
const pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext;
_registers.setIP(_addressSpace.get64(sigctx));
for (int i = UNW_RISCV_X1; i <= UNW_RISCV_X31; ++i) {
uint64_t value = _addressSpace.get64(sigctx + static_cast<pint_t>(i * 8));
_registers.setRegister(i, value);
}
_isSignalFrame = true;
return UNW_STEP_SUCCESS;
}
#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
// defined(_LIBUNWIND_TARGET_RISCV)
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
defined(_LIBUNWIND_TARGET_S390X)
template <typename A, typename R>

View File

@ -167,7 +167,7 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
}
// Update the pr_cache in the mock exception object.
const uint32_t* unwindInfo = (uint32_t *) frameInfo.unwind_info;
uint32_t *unwindInfo = (uint32_t *)frameInfo.unwind_info;
ex.pr_cache.fnstart = frameInfo.start_ip;
ex.pr_cache.ehtp = (_Unwind_EHT_Header *) unwindInfo;
ex.pr_cache.additional= frameInfo.flags;

View File

@ -321,7 +321,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
unw_proc_info_t frameInfo;
if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING(
"unwind_phase2_forced(ex_obj=%p): __unw_step_stage2 "
"unwind_phase2_forced(ex_obj=%p): __unw_get_proc_info "
"failed => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;

View File

@ -194,9 +194,20 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv)
addi 4, 3, PPC64_OFFS_FP
// load VS register
#ifdef __LITTLE_ENDIAN__
// For little-endian targets, we need a swap since lxvd2x will load the register
// in the incorrect doubleword order.
// FIXME: when supporting targets older than Power9 on LE is no longer required,
// this can be changed to simply `lxv n, (16 * n)(4)`.
#define PPC64_LVS(n) \
lxvd2x n, 0, 4 ;\
xxswapd n, n ;\
addi 4, 4, 16
#else
#define PPC64_LVS(n) \
lxvd2x n, 0, 4 ;\
addi 4, 4, 16
#endif
// restore the first 32 VS regs (and also all floating point regs)
PPC64_LVS(0)
@ -232,9 +243,16 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv)
PPC64_LVS(30)
PPC64_LVS(31)
#ifdef __LITTLE_ENDIAN__
#define PPC64_CLVS_RESTORE(n) \
addi 4, 3, PPC64_OFFS_FP + n * 16 ;\
lxvd2x n, 0, 4 ;\
xxswapd n, n
#else
#define PPC64_CLVS_RESTORE(n) \
addi 4, 3, PPC64_OFFS_FP + n * 16 ;\
lxvd2x n, 0, 4
#endif
#if !defined(_AIX)
// use VRSAVE to conditionally restore the remaining VS regs, that are
@ -1203,8 +1221,8 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind19Registers_loongarch6jumptoEv)
ld.d $r\i, $a0, (8 * \i)
.endr
ld.d $r4, $a0, (8 * 4) // restore $a0 last
ld.d $r1, $a0, (8 * 32) // load new pc into $ra
ld.d $ra, $a0, (8 * 32) // load new pc into $ra
ld.d $a0, $a0, (8 * 4) // restore $a0 last
jr $ra

View File

@ -351,9 +351,20 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
addi 4, 3, PPC64_OFFS_FP
// store VS register
#ifdef __LITTLE_ENDIAN__
// For little-endian targets, we need a swap since stxvd2x will store the
// register in the incorrect doubleword order.
// FIXME: when supporting targets older than Power9 on LE is no longer required
// this can be changed to simply `stxv n, 16 * n(4)`.
#define PPC64_STVS(n) \
xxswapd n, n ;\
stxvd2x n, 0, 4 ;\
addi 4, 4, 16
#else
#define PPC64_STVS(n) \
stxvd2x n, 0, 4 ;\
addi 4, 4, 16
#endif
PPC64_STVS(0)
PPC64_STVS(1)

View File

@ -1,113 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//
//===----------------------------------------------------------------------===//
#include "config.h"
// static linker symbols to prevent wrong two level namespace for _Unwind symbols
#if defined(__arm__)
#define NOT_HERE_BEFORE_5_0(sym) \
extern const char sym##_tmp30 __asm("$ld$hide$os3.0$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp30 = 0; \
extern const char sym##_tmp31 __asm("$ld$hide$os3.1$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp31 = 0; \
extern const char sym##_tmp32 __asm("$ld$hide$os3.2$_" #sym );\
__attribute__((visibility("default"))) const char sym##_tmp32 = 0; \
extern const char sym##_tmp40 __asm("$ld$hide$os4.0$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp40 = 0; \
extern const char sym##_tmp41 __asm("$ld$hide$os4.1$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp41 = 0; \
extern const char sym##_tmp42 __asm("$ld$hide$os4.2$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp42 = 0; \
extern const char sym##_tmp43 __asm("$ld$hide$os4.3$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp43 = 0;
#elif defined(__aarch64__)
#define NOT_HERE_BEFORE_10_6(sym)
#define NEVER_HERE(sym)
#else
#define NOT_HERE_BEFORE_10_6(sym) \
extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp5 = 0;
#define NEVER_HERE(sym) \
extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp5 = 0; \
extern const char sym##_tmp6 __asm("$ld$hide$os10.6$_" #sym ); \
__attribute__((visibility("default"))) const char sym##_tmp6 = 0;
#endif
#if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
//
// symbols in libSystem.dylib in 10.6 and later, but are in libgcc_s.dylib in
// earlier versions
//
NOT_HERE_BEFORE_10_6(_Unwind_DeleteException)
NOT_HERE_BEFORE_10_6(_Unwind_Find_FDE)
NOT_HERE_BEFORE_10_6(_Unwind_ForcedUnwind)
NOT_HERE_BEFORE_10_6(_Unwind_GetGR)
NOT_HERE_BEFORE_10_6(_Unwind_GetIP)
NOT_HERE_BEFORE_10_6(_Unwind_GetLanguageSpecificData)
NOT_HERE_BEFORE_10_6(_Unwind_GetRegionStart)
NOT_HERE_BEFORE_10_6(_Unwind_RaiseException)
NOT_HERE_BEFORE_10_6(_Unwind_Resume)
NOT_HERE_BEFORE_10_6(_Unwind_SetGR)
NOT_HERE_BEFORE_10_6(_Unwind_SetIP)
NOT_HERE_BEFORE_10_6(_Unwind_Backtrace)
NOT_HERE_BEFORE_10_6(_Unwind_FindEnclosingFunction)
NOT_HERE_BEFORE_10_6(_Unwind_GetCFA)
NOT_HERE_BEFORE_10_6(_Unwind_GetDataRelBase)
NOT_HERE_BEFORE_10_6(_Unwind_GetTextRelBase)
NOT_HERE_BEFORE_10_6(_Unwind_Resume_or_Rethrow)
NOT_HERE_BEFORE_10_6(_Unwind_GetIPInfo)
NOT_HERE_BEFORE_10_6(__register_frame)
NOT_HERE_BEFORE_10_6(__deregister_frame)
//
// symbols in libSystem.dylib for compatibility, but we don't want any new code
// using them
//
NEVER_HERE(__register_frame_info_bases)
NEVER_HERE(__register_frame_info)
NEVER_HERE(__register_frame_info_table_bases)
NEVER_HERE(__register_frame_info_table)
NEVER_HERE(__register_frame_table)
NEVER_HERE(__deregister_frame_info)
NEVER_HERE(__deregister_frame_info_bases)
#endif // defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
#if defined(_LIBUNWIND_BUILD_SJLJ_APIS)
//
// symbols in libSystem.dylib in iOS 5.0 and later, but are in libgcc_s.dylib in
// earlier versions
//
NOT_HERE_BEFORE_5_0(_Unwind_GetLanguageSpecificData)
NOT_HERE_BEFORE_5_0(_Unwind_GetRegionStart)
NOT_HERE_BEFORE_5_0(_Unwind_GetIP)
NOT_HERE_BEFORE_5_0(_Unwind_SetGR)
NOT_HERE_BEFORE_5_0(_Unwind_SetIP)
NOT_HERE_BEFORE_5_0(_Unwind_DeleteException)
NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Register)
NOT_HERE_BEFORE_5_0(_Unwind_GetGR)
NOT_HERE_BEFORE_5_0(_Unwind_GetIPInfo)
NOT_HERE_BEFORE_5_0(_Unwind_GetCFA)
NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume)
NOT_HERE_BEFORE_5_0(_Unwind_SjLj_RaiseException)
NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume_or_Rethrow)
NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Unregister)
#endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS)

View File

@ -162,10 +162,14 @@
#define _LIBUNWIND_LOG0(msg)
#define _LIBUNWIND_LOG(msg, ...)
#else
#define _LIBUNWIND_LOG0(msg) \
fprintf(stderr, "libunwind: " msg "\n")
#define _LIBUNWIND_LOG(msg, ...) \
fprintf(stderr, "libunwind: " msg "\n", __VA_ARGS__)
#define _LIBUNWIND_LOG0(msg) do { \
fprintf(stderr, "libunwind: " msg "\n"); \
fflush(stderr); \
} while (0)
#define _LIBUNWIND_LOG(msg, ...) do { \
fprintf(stderr, "libunwind: " msg "\n", __VA_ARGS__); \
fflush(stderr); \
} while (0)
#endif
#if defined(NDEBUG)

View File

@ -349,7 +349,87 @@ void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
#endif // !defined(__USING_SJLJ_EXCEPTIONS__)
#ifdef __APPLE__
namespace libunwind {
static constexpr size_t MAX_DYNAMIC_UNWIND_SECTIONS_FINDERS = 8;
static RWMutex findDynamicUnwindSectionsLock;
static size_t numDynamicUnwindSectionsFinders = 0;
static unw_find_dynamic_unwind_sections
dynamicUnwindSectionsFinders[MAX_DYNAMIC_UNWIND_SECTIONS_FINDERS] = {0};
bool findDynamicUnwindSections(void *addr, unw_dynamic_unwind_sections *info) {
bool found = false;
findDynamicUnwindSectionsLock.lock_shared();
for (size_t i = 0; i != numDynamicUnwindSectionsFinders; ++i) {
if (dynamicUnwindSectionsFinders[i]((unw_word_t)addr, info)) {
found = true;
break;
}
}
findDynamicUnwindSectionsLock.unlock_shared();
return found;
}
} // namespace libunwind
int __unw_add_find_dynamic_unwind_sections(
unw_find_dynamic_unwind_sections find_dynamic_unwind_sections) {
findDynamicUnwindSectionsLock.lock();
// Check that we have enough space...
if (numDynamicUnwindSectionsFinders == MAX_DYNAMIC_UNWIND_SECTIONS_FINDERS) {
findDynamicUnwindSectionsLock.unlock();
return UNW_ENOMEM;
}
// Check for value already present...
for (size_t i = 0; i != numDynamicUnwindSectionsFinders; ++i) {
if (dynamicUnwindSectionsFinders[i] == find_dynamic_unwind_sections) {
findDynamicUnwindSectionsLock.unlock();
return UNW_EINVAL;
}
}
// Success -- add callback entry.
dynamicUnwindSectionsFinders[numDynamicUnwindSectionsFinders++] =
find_dynamic_unwind_sections;
findDynamicUnwindSectionsLock.unlock();
return UNW_ESUCCESS;
}
int __unw_remove_find_dynamic_unwind_sections(
unw_find_dynamic_unwind_sections find_dynamic_unwind_sections) {
findDynamicUnwindSectionsLock.lock();
// Find index to remove.
size_t finderIdx = numDynamicUnwindSectionsFinders;
for (size_t i = 0; i != numDynamicUnwindSectionsFinders; ++i) {
if (dynamicUnwindSectionsFinders[i] == find_dynamic_unwind_sections) {
finderIdx = i;
break;
}
}
// If no such registration is present then error out.
if (finderIdx == numDynamicUnwindSectionsFinders) {
findDynamicUnwindSectionsLock.unlock();
return UNW_EINVAL;
}
// Remove entry.
for (size_t i = finderIdx; i != numDynamicUnwindSectionsFinders - 1; ++i)
dynamicUnwindSectionsFinders[i] = dynamicUnwindSectionsFinders[i + 1];
dynamicUnwindSectionsFinders[--numDynamicUnwindSectionsFinders] = nullptr;
findDynamicUnwindSectionsLock.unlock();
return UNW_ESUCCESS;
}
#endif // __APPLE__
// Add logging hooks in Debug builds only
#ifndef NDEBUG

View File

@ -58,6 +58,71 @@ extern void __unw_remove_dynamic_fde(unw_word_t fde);
extern void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start);
extern void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start);
#ifdef __APPLE__
// Holds a description of the object-format-header (if any) and unwind info
// sections for a given address:
//
// * dso_base should point to a header for the JIT'd object containing the
// given address. The header's type should match the format type that
// libunwind was compiled for (so a mach_header or mach_header_64 on Darwin).
// A value of zero indicates that no such header exists.
//
// * dwarf_section and dwarf_section_length hold the address range of a DWARF
// eh-frame section associated with the given address, if any. If the
// dwarf_section_length field is zero it indicates that no such section
// exists (and in this case dwarf_section should also be set to zero).
//
// * compact_unwind_section and compact_unwind_section_length hold the address
// range of a compact-unwind info section associated with the given address,
// if any. If the compact_unwind_section_length field is zero it indicates
// that no such section exists (and in this case compact_unwind_section
// should also be set to zero).
//
// See the unw_find_dynamic_unwind_sections type below for more details.
struct unw_dynamic_unwind_sections {
unw_word_t dso_base;
unw_word_t dwarf_section;
size_t dwarf_section_length;
unw_word_t compact_unwind_section;
size_t compact_unwind_section_length;
};
// Typedef for unwind-info lookup callbacks. Functions of this type can be
// registered and deregistered using __unw_add_find_dynamic_unwind_sections
// and __unw_remove_find_dynamic_unwind_sections respectively.
//
// An unwind-info lookup callback should return 1 to indicate that it found
// unwind-info for the given address, or 0 to indicate that it did not find
// unwind-info for the given address. If found, the callback should populate
// some or all of the fields of the info argument (which is guaranteed to be
// non-null with all fields zero-initialized):
typedef int (*unw_find_dynamic_unwind_sections)(
unw_word_t addr, struct unw_dynamic_unwind_sections *info);
// Register a dynamic unwind-info lookup callback. If libunwind does not find
// unwind info for a given frame in the executable program or normal dynamic
// shared objects then it will call all registered dynamic lookup functions
// in registration order until either one of them returns true, or the end
// of the list is reached. This lookup will happen before libunwind searches
// any eh-frames registered via __register_frame or
// __unw_add_dynamic_eh_frame_section.
//
// Returns UNW_ESUCCESS for successful registrations. If the given callback
// has already been registered then UNW_EINVAL will be returned. If all
// available callback entries are in use then UNW_ENOMEM will be returned.
extern int __unw_add_find_dynamic_unwind_sections(
unw_find_dynamic_unwind_sections find_dynamic_unwind_sections);
// Deregister a dynacim unwind-info lookup callback.
//
// Returns UNW_ESUCCESS for successful deregistrations. If the given callback
// has already been registered then UNW_EINVAL will be returned.
extern int __unw_remove_find_dynamic_unwind_sections(
unw_find_dynamic_unwind_sections find_dynamic_unwind_sections);
#endif
#if defined(_LIBUNWIND_ARM_EHABI)
extern const uint32_t* decode_eht_entry(const uint32_t*, size_t*, size_t*);
extern _Unwind_Reason_Code _Unwind_VRS_Interpret(_Unwind_Context *context,