Skip to content

Update libunwind to LLVM 17.0.4 #20705

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions system/lib/libunwind/include/__libunwind_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, looks like an attempt to fix a typo upstream that failed..? Or is there meaning to indentation like this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it looks someone tried fix an already inconsistent indentation in llvm/llvm-project@d080b5f but didn't get it right... I uploaded llvm/llvm-project#72314 to fix that upstream but given that this doesn't affect our behavior I guess we can just wait until the upstream fix trickles down in the next release.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good.

Btw, I don't see a PR for that indentation commit - do people land things in LLVM without review these days?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, folks have always been able to directly push LLVM.. for better or worse.

# 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

Expand Down
6 changes: 3 additions & 3 deletions system/lib/libunwind/readme.txt
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
llvm's libunwind
----------------

These files are from the llvm-project based on release 16.0.6.
These files are from the llvm-project based on release 17.0.4.

We maintain a local fork of llvm-project that contains any emscripten
specific patches:

https://github.com/emscripten-core/llvm-project

The current patch is based on the emscripten-libs-16 branch.
The current patch is based on the emscripten-libs-17 branch.

Update Instructions
-------------------
Expand All @@ -20,4 +20,4 @@ Modifications

For a list of changes from upstream see the libunwind files that are part of:

https://github.com/llvm/llvm-project/compare/llvmorg-16.0.6...emscripten-core:emscripten-libs-16
https://github.com/llvm/llvm-project/compare/llvmorg-17.0.4...emscripten-core:emscripten-libs-17
20 changes: 20 additions & 0 deletions system/lib/libunwind/src/AddressSpace.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
9 changes: 6 additions & 3 deletions system/lib/libunwind/src/Unwind-EHABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down
19 changes: 18 additions & 1 deletion system/lib/libunwind/src/Unwind-seh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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): "
Expand All @@ -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;
}
}

Expand Down
80 changes: 77 additions & 3 deletions system/lib/libunwind/src/UnwindCursor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -506,7 +507,14 @@ class UnwindCursor : public AbstractUnwindCursor {
#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.
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -981,6 +994,10 @@ class UnwindCursor : public AbstractUnwindCursor{
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 &);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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>
Expand Down
2 changes: 1 addition & 1 deletion system/lib/libunwind/src/UnwindLevel1-gcc-ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion system/lib/libunwind/src/UnwindLevel1.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading