mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
libunwind: update to LLVM 21
This commit is contained in:
parent
c34fc8f198
commit
85438e75e0
9 changed files with 373 additions and 110 deletions
10
lib/libunwind/src/Registers.hpp
vendored
10
lib/libunwind/src/Registers.hpp
vendored
|
|
@ -15,9 +15,9 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "cet_unwind.h"
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "libunwind.h"
|
#include "libunwind.h"
|
||||||
|
#include "shadow_stack_unwind.h"
|
||||||
|
|
||||||
namespace libunwind {
|
namespace libunwind {
|
||||||
|
|
||||||
|
|
@ -48,7 +48,7 @@ class _LIBUNWIND_HIDDEN Registers_x86;
|
||||||
extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *);
|
extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *);
|
||||||
|
|
||||||
#if defined(_LIBUNWIND_USE_CET)
|
#if defined(_LIBUNWIND_USE_CET)
|
||||||
extern "C" void *__libunwind_cet_get_jump_target() {
|
extern "C" void *__libunwind_shstk_get_jump_target() {
|
||||||
return reinterpret_cast<void *>(&__libunwind_Registers_x86_jumpto);
|
return reinterpret_cast<void *>(&__libunwind_Registers_x86_jumpto);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -268,7 +268,7 @@ class _LIBUNWIND_HIDDEN Registers_x86_64;
|
||||||
extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *);
|
extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *);
|
||||||
|
|
||||||
#if defined(_LIBUNWIND_USE_CET)
|
#if defined(_LIBUNWIND_USE_CET)
|
||||||
extern "C" void *__libunwind_cet_get_jump_target() {
|
extern "C" void *__libunwind_shstk_get_jump_target() {
|
||||||
return reinterpret_cast<void *>(&__libunwind_Registers_x86_64_jumpto);
|
return reinterpret_cast<void *>(&__libunwind_Registers_x86_64_jumpto);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1817,7 +1817,7 @@ class _LIBUNWIND_HIDDEN Registers_arm64;
|
||||||
extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);
|
extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *);
|
||||||
|
|
||||||
#if defined(_LIBUNWIND_USE_GCS)
|
#if defined(_LIBUNWIND_USE_GCS)
|
||||||
extern "C" void *__libunwind_cet_get_jump_target() {
|
extern "C" void *__libunwind_shstk_get_jump_target() {
|
||||||
return reinterpret_cast<void *>(&__libunwind_Registers_arm64_jumpto);
|
return reinterpret_cast<void *>(&__libunwind_Registers_arm64_jumpto);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -4126,7 +4126,7 @@ inline reg_t Registers_riscv::getRegister(int regNum) const {
|
||||||
return _registers[regNum];
|
return _registers[regNum];
|
||||||
if (regNum == UNW_RISCV_VLENB) {
|
if (regNum == UNW_RISCV_VLENB) {
|
||||||
reg_t vlenb;
|
reg_t vlenb;
|
||||||
__asm__("csrr %0, 0xC22" : "=r"(vlenb));
|
__asm__ volatile("csrr %0, 0xC22" : "=r"(vlenb));
|
||||||
return vlenb;
|
return vlenb;
|
||||||
}
|
}
|
||||||
_LIBUNWIND_ABORT("unsupported riscv register");
|
_LIBUNWIND_ABORT("unsupported riscv register");
|
||||||
|
|
|
||||||
41
lib/libunwind/src/Unwind-seh.cpp
vendored
41
lib/libunwind/src/Unwind-seh.cpp
vendored
|
|
@ -51,6 +51,32 @@ static DISPATCHER_CONTEXT *__unw_seh_get_disp_ctx(unw_cursor_t *cursor);
|
||||||
static void __unw_seh_set_disp_ctx(unw_cursor_t *cursor,
|
static void __unw_seh_set_disp_ctx(unw_cursor_t *cursor,
|
||||||
DISPATCHER_CONTEXT *disp);
|
DISPATCHER_CONTEXT *disp);
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wgnu-anonymous-struct"
|
||||||
|
// Local redefinition of this type; mingw-w64 headers lack the
|
||||||
|
// DISPATCHER_CONTEXT_NONVOLREG_ARM64 type as of May 2025, so locally redefine
|
||||||
|
// it and use that definition, to avoid needing to test/guess whether the real
|
||||||
|
// type is available of not.
|
||||||
|
union LOCAL_DISPATCHER_CONTEXT_NONVOLREG_ARM64 {
|
||||||
|
BYTE Buffer[11 * sizeof(DWORD64) + 8 * sizeof(double)];
|
||||||
|
|
||||||
|
struct {
|
||||||
|
DWORD64 GpNvRegs[11];
|
||||||
|
double FpNvRegs[8];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Custom data type definition; this type is not defined in WinSDK.
|
||||||
|
union LOCAL_DISPATCHER_CONTEXT_NONVOLREG_ARM {
|
||||||
|
BYTE Buffer[8 * sizeof(DWORD) + 8 * sizeof(double)];
|
||||||
|
|
||||||
|
struct {
|
||||||
|
DWORD GpNvRegs[8];
|
||||||
|
double FpNvRegs[8];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
/// Common implementation of SEH-style handler functions used by Itanium-
|
/// Common implementation of SEH-style handler functions used by Itanium-
|
||||||
/// style frames. Depending on how and why it was called, it may do one of:
|
/// style frames. Depending on how and why it was called, it may do one of:
|
||||||
/// a) Delegate to the given Itanium-style personality function; or
|
/// a) Delegate to the given Itanium-style personality function; or
|
||||||
|
|
@ -212,6 +238,21 @@ __libunwind_seh_personality(int version, _Unwind_Action state,
|
||||||
ms_exc.ExceptionInformation[2] = state;
|
ms_exc.ExceptionInformation[2] = state;
|
||||||
DISPATCHER_CONTEXT *disp_ctx =
|
DISPATCHER_CONTEXT *disp_ctx =
|
||||||
__unw_seh_get_disp_ctx((unw_cursor_t *)context);
|
__unw_seh_get_disp_ctx((unw_cursor_t *)context);
|
||||||
|
#if defined(__aarch64__)
|
||||||
|
LOCAL_DISPATCHER_CONTEXT_NONVOLREG_ARM64 nonvol;
|
||||||
|
memcpy(&nonvol.GpNvRegs, &disp_ctx->ContextRecord->X19,
|
||||||
|
sizeof(nonvol.GpNvRegs));
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
nonvol.FpNvRegs[i] = disp_ctx->ContextRecord->V[i + 8].D[0];
|
||||||
|
disp_ctx->NonVolatileRegisters = nonvol.Buffer;
|
||||||
|
#elif defined(__arm__)
|
||||||
|
LOCAL_DISPATCHER_CONTEXT_NONVOLREG_ARM nonvol;
|
||||||
|
memcpy(&nonvol.GpNvRegs, &disp_ctx->ContextRecord->R4,
|
||||||
|
sizeof(nonvol.GpNvRegs));
|
||||||
|
memcpy(&nonvol.FpNvRegs, &disp_ctx->ContextRecord->D[8],
|
||||||
|
sizeof(nonvol.FpNvRegs));
|
||||||
|
disp_ctx->NonVolatileRegisters = nonvol.Buffer;
|
||||||
|
#endif
|
||||||
_LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() calling "
|
_LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() calling "
|
||||||
"LanguageHandler %p(%p, %p, %p, %p)",
|
"LanguageHandler %p(%p, %p, %p, %p)",
|
||||||
(void *)disp_ctx->LanguageHandler, (void *)&ms_exc,
|
(void *)disp_ctx->LanguageHandler, (void *)&ms_exc,
|
||||||
|
|
|
||||||
6
lib/libunwind/src/Unwind-wasm.c
vendored
6
lib/libunwind/src/Unwind-wasm.c
vendored
|
|
@ -102,8 +102,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Not used in Wasm.
|
/// Not used in Wasm.
|
||||||
_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
|
_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t) {}
|
||||||
uintptr_t value) {}
|
|
||||||
|
|
||||||
/// Called by personality handler to get LSDA for current frame.
|
/// Called by personality handler to get LSDA for current frame.
|
||||||
_LIBUNWIND_EXPORT uintptr_t
|
_LIBUNWIND_EXPORT uintptr_t
|
||||||
|
|
@ -115,8 +114,7 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Not used in Wasm.
|
/// Not used in Wasm.
|
||||||
_LIBUNWIND_EXPORT uintptr_t
|
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *) {
|
||||||
_Unwind_GetRegionStart(struct _Unwind_Context *context) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
286
lib/libunwind/src/UnwindCursor.hpp
vendored
286
lib/libunwind/src/UnwindCursor.hpp
vendored
|
|
@ -11,7 +11,7 @@
|
||||||
#ifndef __UNWINDCURSOR_HPP__
|
#ifndef __UNWINDCURSOR_HPP__
|
||||||
#define __UNWINDCURSOR_HPP__
|
#define __UNWINDCURSOR_HPP__
|
||||||
|
|
||||||
#include "cet_unwind.h"
|
#include "shadow_stack_unwind.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -31,8 +31,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#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_S390X))
|
defined(_LIBUNWIND_TARGET_LOONGARCH) || \
|
||||||
|
defined(_LIBUNWIND_TARGET_RISCV) || defined(_LIBUNWIND_TARGET_S390X))
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
|
@ -40,6 +41,12 @@
|
||||||
#define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1
|
#define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64)
|
||||||
|
#include <OS.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#define _LIBUNWIND_CHECK_HAIKU_SIGRETURN 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "AddressSpace.hpp"
|
#include "AddressSpace.hpp"
|
||||||
#include "CompactUnwinder.hpp"
|
#include "CompactUnwinder.hpp"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
@ -82,6 +89,22 @@ struct UNWIND_INFO {
|
||||||
uint16_t UnwindCodes[2];
|
uint16_t UnwindCodes[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wgnu-anonymous-struct"
|
||||||
|
union UNWIND_INFO_ARM {
|
||||||
|
DWORD HeaderData;
|
||||||
|
struct {
|
||||||
|
DWORD FunctionLength : 18;
|
||||||
|
DWORD Version : 2;
|
||||||
|
DWORD ExceptionDataPresent : 1;
|
||||||
|
DWORD EpilogInHeader : 1;
|
||||||
|
DWORD FunctionFragment : 1;
|
||||||
|
DWORD EpilogCount : 5;
|
||||||
|
DWORD CodeWords : 4;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
extern "C" _Unwind_Reason_Code __libunwind_seh_personality(
|
extern "C" _Unwind_Reason_Code __libunwind_seh_personality(
|
||||||
int, _Unwind_Action, uint64_t, _Unwind_Exception *,
|
int, _Unwind_Action, uint64_t, _Unwind_Exception *,
|
||||||
struct _Unwind_Context *);
|
struct _Unwind_Context *);
|
||||||
|
|
@ -150,7 +173,7 @@ bool DwarfFDECache<A>::_registeredForDyldUnloads = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename A>
|
template <typename A>
|
||||||
typename DwarfFDECache<A>::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) {
|
typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) {
|
||||||
pint_t result = 0;
|
pint_t result = 0;
|
||||||
_LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared());
|
_LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared());
|
||||||
for (entry *p = _buffer; p < _bufferUsed; ++p) {
|
for (entry *p = _buffer; p < _bufferUsed; ++p) {
|
||||||
|
|
@ -996,6 +1019,10 @@ private:
|
||||||
bool setInfoForSigReturn(Registers_arm64 &);
|
bool setInfoForSigReturn(Registers_arm64 &);
|
||||||
int stepThroughSigReturn(Registers_arm64 &);
|
int stepThroughSigReturn(Registers_arm64 &);
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(_LIBUNWIND_TARGET_LOONGARCH)
|
||||||
|
bool setInfoForSigReturn(Registers_loongarch &);
|
||||||
|
int stepThroughSigReturn(Registers_loongarch &);
|
||||||
|
#endif
|
||||||
#if defined(_LIBUNWIND_TARGET_RISCV)
|
#if defined(_LIBUNWIND_TARGET_RISCV)
|
||||||
bool setInfoForSigReturn(Registers_riscv &);
|
bool setInfoForSigReturn(Registers_riscv &);
|
||||||
int stepThroughSigReturn(Registers_riscv &);
|
int stepThroughSigReturn(Registers_riscv &);
|
||||||
|
|
@ -1010,7 +1037,7 @@ private:
|
||||||
template <typename Registers> int stepThroughSigReturn(Registers &) {
|
template <typename Registers> int stepThroughSigReturn(Registers &) {
|
||||||
return UNW_STEP_END;
|
return UNW_STEP_END;
|
||||||
}
|
}
|
||||||
#elif defined(_LIBUNWIND_TARGET_HAIKU)
|
#elif defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
|
||||||
bool setInfoForSigReturn();
|
bool setInfoForSigReturn();
|
||||||
int stepThroughSigReturn();
|
int stepThroughSigReturn();
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -2013,6 +2040,61 @@ bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {
|
||||||
_info.handler = 0;
|
_info.handler = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#elif defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_ARM)
|
||||||
|
|
||||||
|
#if defined(_LIBUNWIND_TARGET_AARCH64)
|
||||||
|
#define FUNC_LENGTH_UNIT 4
|
||||||
|
#define XDATA_TYPE IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA
|
||||||
|
#else
|
||||||
|
#define FUNC_LENGTH_UNIT 2
|
||||||
|
#define XDATA_TYPE UNWIND_INFO_ARM
|
||||||
|
#endif
|
||||||
|
if (unwindEntry->Flag != 0) { // Packed unwind info
|
||||||
|
_info.end_ip =
|
||||||
|
_info.start_ip + unwindEntry->FunctionLength * FUNC_LENGTH_UNIT;
|
||||||
|
// Only fill in the handler and LSDA if they're stale.
|
||||||
|
if (pc != getLastPC()) {
|
||||||
|
// Packed unwind info doesn't have an exception handler.
|
||||||
|
_info.lsda = 0;
|
||||||
|
_info.handler = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
XDATA_TYPE *xdata =
|
||||||
|
reinterpret_cast<XDATA_TYPE *>(base + unwindEntry->UnwindData);
|
||||||
|
_info.end_ip = _info.start_ip + xdata->FunctionLength * FUNC_LENGTH_UNIT;
|
||||||
|
// Only fill in the handler and LSDA if they're stale.
|
||||||
|
if (pc != getLastPC()) {
|
||||||
|
if (xdata->ExceptionDataPresent) {
|
||||||
|
uint32_t offset = 1; // The main xdata
|
||||||
|
uint32_t codeWords = xdata->CodeWords;
|
||||||
|
uint32_t epilogScopes = xdata->EpilogCount;
|
||||||
|
if (xdata->EpilogCount == 0 && xdata->CodeWords == 0) {
|
||||||
|
// The extension word has got the same layout for both ARM and ARM64
|
||||||
|
uint32_t extensionWord = reinterpret_cast<uint32_t *>(xdata)[1];
|
||||||
|
codeWords = (extensionWord >> 16) & 0xff;
|
||||||
|
epilogScopes = extensionWord & 0xffff;
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
if (!xdata->EpilogInHeader)
|
||||||
|
offset += epilogScopes;
|
||||||
|
offset += codeWords;
|
||||||
|
uint32_t *exceptionHandlerInfo =
|
||||||
|
reinterpret_cast<uint32_t *>(xdata) + offset;
|
||||||
|
_dispContext.HandlerData = &exceptionHandlerInfo[1];
|
||||||
|
_dispContext.LanguageHandler = reinterpret_cast<EXCEPTION_ROUTINE *>(
|
||||||
|
base + exceptionHandlerInfo[0]);
|
||||||
|
_info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);
|
||||||
|
if (exceptionHandlerInfo[0])
|
||||||
|
_info.handler =
|
||||||
|
reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
|
||||||
|
else
|
||||||
|
_info.handler = 0;
|
||||||
|
} else {
|
||||||
|
_info.lsda = 0;
|
||||||
|
_info.handler = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
setLastPC(pc);
|
setLastPC(pc);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -2554,7 +2636,7 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
|
||||||
template <typename A, typename R>
|
template <typename A, typename R>
|
||||||
void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
|
void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
|
||||||
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
|
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
|
||||||
defined(_LIBUNWIND_TARGET_HAIKU)
|
defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
|
||||||
_isSigReturn = false;
|
_isSigReturn = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -2679,7 +2761,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
|
||||||
#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
|
#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
|
||||||
|
|
||||||
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
|
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
|
||||||
defined(_LIBUNWIND_TARGET_HAIKU)
|
defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
|
||||||
if (setInfoForSigReturn())
|
if (setInfoForSigReturn())
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -2755,65 +2837,63 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {
|
||||||
_isSignalFrame = true;
|
_isSignalFrame = true;
|
||||||
return UNW_STEP_SUCCESS;
|
return UNW_STEP_SUCCESS;
|
||||||
}
|
}
|
||||||
|
#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
|
||||||
|
// defined(_LIBUNWIND_TARGET_AARCH64)
|
||||||
|
|
||||||
#elif defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64)
|
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
|
||||||
#include <commpage_defs.h>
|
defined(_LIBUNWIND_TARGET_LOONGARCH)
|
||||||
#include <signal.h>
|
template <typename A, typename R>
|
||||||
|
bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_loongarch &) {
|
||||||
|
const pint_t pc = static_cast<pint_t>(getReg(UNW_REG_IP));
|
||||||
|
// The PC might contain an invalid address if the unwind info is bad, so
|
||||||
|
// directly accessing it could cause a SIGSEGV.
|
||||||
|
if (!isReadableAddr(pc))
|
||||||
|
return false;
|
||||||
|
const auto *instructions = reinterpret_cast<const uint32_t *>(pc);
|
||||||
|
// Look for the two instructions used in the sigreturn trampoline
|
||||||
|
// __vdso_rt_sigreturn:
|
||||||
|
//
|
||||||
|
// 0x03822c0b li a7,0x8b
|
||||||
|
// 0x002b0000 syscall 0
|
||||||
|
if (instructions[0] != 0x03822c0b || instructions[1] != 0x002b0000)
|
||||||
|
return false;
|
||||||
|
|
||||||
extern "C" {
|
_info = {};
|
||||||
extern void *__gCommPageAddress;
|
_info.start_ip = pc;
|
||||||
|
_info.end_ip = pc + 4;
|
||||||
|
_isSigReturn = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename A, typename R>
|
template <typename A, typename R>
|
||||||
bool UnwindCursor<A, R>::setInfoForSigReturn() {
|
int UnwindCursor<A, R>::stepThroughSigReturn(Registers_loongarch &) {
|
||||||
#if defined(_LIBUNWIND_TARGET_X86_64)
|
// In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
|
||||||
addr_t signal_handler =
|
// - 128-byte siginfo struct
|
||||||
(((addr_t *)__gCommPageAddress)[COMMPAGE_ENTRY_X86_SIGNAL_HANDLER] +
|
// - ucontext_t struct:
|
||||||
(addr_t)__gCommPageAddress);
|
// - 8-byte long (__uc_flags)
|
||||||
addr_t signal_handler_ret = signal_handler + 45;
|
// - 8-byte pointer (*uc_link)
|
||||||
#endif
|
// - 24-byte uc_stack
|
||||||
pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
|
// - 8-byte uc_sigmask
|
||||||
if (pc == signal_handler_ret) {
|
// - 120-byte of padding to allow sigset_t to be expanded in the future
|
||||||
_info = {};
|
// - 8 bytes of padding because sigcontext has 16-byte alignment
|
||||||
_info.start_ip = signal_handler;
|
// - struct sigcontext uc_mcontext
|
||||||
_info.end_ip = signal_handler_ret;
|
// [1]
|
||||||
_isSigReturn = true;
|
// https://github.com/torvalds/linux/blob/master/arch/loongarch/kernel/signal.c
|
||||||
return true;
|
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_LOONGARCH_R1; i <= UNW_LOONGARCH_R31; ++i) {
|
||||||
|
// skip R0
|
||||||
|
uint64_t value =
|
||||||
|
_addressSpace.get64(sigctx + static_cast<pint_t>((i + 1) * 8));
|
||||||
|
_registers.setRegister(i, value);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename A, typename R>
|
|
||||||
int UnwindCursor<A, R>::stepThroughSigReturn() {
|
|
||||||
_isSignalFrame = true;
|
_isSignalFrame = true;
|
||||||
pint_t sp = _registers.getSP();
|
|
||||||
#if defined(_LIBUNWIND_TARGET_X86_64)
|
|
||||||
vregs *regs = (vregs *)(sp + 0x70);
|
|
||||||
|
|
||||||
_registers.setRegister(UNW_REG_IP, regs->rip);
|
|
||||||
_registers.setRegister(UNW_REG_SP, regs->rsp);
|
|
||||||
_registers.setRegister(UNW_X86_64_RAX, regs->rax);
|
|
||||||
_registers.setRegister(UNW_X86_64_RDX, regs->rdx);
|
|
||||||
_registers.setRegister(UNW_X86_64_RCX, regs->rcx);
|
|
||||||
_registers.setRegister(UNW_X86_64_RBX, regs->rbx);
|
|
||||||
_registers.setRegister(UNW_X86_64_RSI, regs->rsi);
|
|
||||||
_registers.setRegister(UNW_X86_64_RDI, regs->rdi);
|
|
||||||
_registers.setRegister(UNW_X86_64_RBP, regs->rbp);
|
|
||||||
_registers.setRegister(UNW_X86_64_R8, regs->r8);
|
|
||||||
_registers.setRegister(UNW_X86_64_R9, regs->r9);
|
|
||||||
_registers.setRegister(UNW_X86_64_R10, regs->r10);
|
|
||||||
_registers.setRegister(UNW_X86_64_R11, regs->r11);
|
|
||||||
_registers.setRegister(UNW_X86_64_R12, regs->r12);
|
|
||||||
_registers.setRegister(UNW_X86_64_R13, regs->r13);
|
|
||||||
_registers.setRegister(UNW_X86_64_R14, regs->r14);
|
|
||||||
_registers.setRegister(UNW_X86_64_R15, regs->r15);
|
|
||||||
// TODO: XMM
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return UNW_STEP_SUCCESS;
|
return UNW_STEP_SUCCESS;
|
||||||
}
|
}
|
||||||
#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
|
#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
|
||||||
// defined(_LIBUNWIND_TARGET_AARCH64)
|
// defined(_LIBUNWIND_TARGET_LOONGARCH)
|
||||||
|
|
||||||
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
|
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
|
||||||
defined(_LIBUNWIND_TARGET_RISCV)
|
defined(_LIBUNWIND_TARGET_RISCV)
|
||||||
|
|
@ -2972,6 +3052,96 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_s390x &) {
|
||||||
#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
|
#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
|
||||||
// defined(_LIBUNWIND_TARGET_S390X)
|
// defined(_LIBUNWIND_TARGET_S390X)
|
||||||
|
|
||||||
|
#if defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
|
||||||
|
template <typename A, typename R>
|
||||||
|
bool UnwindCursor<A, R>::setInfoForSigReturn() {
|
||||||
|
Dl_info dlinfo;
|
||||||
|
const auto isSignalHandler = [&](pint_t addr) {
|
||||||
|
if (!dladdr(reinterpret_cast<void *>(addr), &dlinfo))
|
||||||
|
return false;
|
||||||
|
if (strcmp(dlinfo.dli_fname, "commpage"))
|
||||||
|
return false;
|
||||||
|
if (dlinfo.dli_sname == NULL ||
|
||||||
|
strcmp(dlinfo.dli_sname, "commpage_signal_handler"))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
|
||||||
|
if (!isSignalHandler(pc))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pint_t start = reinterpret_cast<pint_t>(dlinfo.dli_saddr);
|
||||||
|
|
||||||
|
static size_t signalHandlerSize = 0;
|
||||||
|
if (signalHandlerSize == 0) {
|
||||||
|
size_t boundLow = 0;
|
||||||
|
size_t boundHigh = static_cast<size_t>(-1);
|
||||||
|
|
||||||
|
area_info areaInfo;
|
||||||
|
if (get_area_info(area_for(dlinfo.dli_saddr), &areaInfo) == B_OK)
|
||||||
|
boundHigh = areaInfo.size;
|
||||||
|
|
||||||
|
while (boundLow < boundHigh) {
|
||||||
|
size_t boundMid = boundLow + ((boundHigh - boundLow) / 2);
|
||||||
|
pint_t test = start + boundMid;
|
||||||
|
if (test >= start && isSignalHandler(test))
|
||||||
|
boundLow = boundMid + 1;
|
||||||
|
else
|
||||||
|
boundHigh = boundMid;
|
||||||
|
}
|
||||||
|
|
||||||
|
signalHandlerSize = boundHigh;
|
||||||
|
}
|
||||||
|
|
||||||
|
_info = {};
|
||||||
|
_info.start_ip = start;
|
||||||
|
_info.end_ip = start + signalHandlerSize;
|
||||||
|
_isSigReturn = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename A, typename R>
|
||||||
|
int UnwindCursor<A, R>::stepThroughSigReturn() {
|
||||||
|
_isSignalFrame = true;
|
||||||
|
|
||||||
|
#if defined(_LIBUNWIND_TARGET_X86_64)
|
||||||
|
// Layout of the stack before function call:
|
||||||
|
// - signal_frame_data
|
||||||
|
// + siginfo_t (public struct, fairly stable)
|
||||||
|
// + ucontext_t (public struct, fairly stable)
|
||||||
|
// - mcontext_t -> Offset 0x70, this is what we want.
|
||||||
|
// - frame->ip (8 bytes)
|
||||||
|
// - frame->bp (8 bytes). Not written by the kernel,
|
||||||
|
// but the signal handler has a "push %rbp" instruction.
|
||||||
|
pint_t bp = this->getReg(UNW_X86_64_RBP);
|
||||||
|
vregs *regs = (vregs *)(bp + 0x70);
|
||||||
|
|
||||||
|
_registers.setRegister(UNW_REG_IP, regs->rip);
|
||||||
|
_registers.setRegister(UNW_REG_SP, regs->rsp);
|
||||||
|
_registers.setRegister(UNW_X86_64_RAX, regs->rax);
|
||||||
|
_registers.setRegister(UNW_X86_64_RDX, regs->rdx);
|
||||||
|
_registers.setRegister(UNW_X86_64_RCX, regs->rcx);
|
||||||
|
_registers.setRegister(UNW_X86_64_RBX, regs->rbx);
|
||||||
|
_registers.setRegister(UNW_X86_64_RSI, regs->rsi);
|
||||||
|
_registers.setRegister(UNW_X86_64_RDI, regs->rdi);
|
||||||
|
_registers.setRegister(UNW_X86_64_RBP, regs->rbp);
|
||||||
|
_registers.setRegister(UNW_X86_64_R8, regs->r8);
|
||||||
|
_registers.setRegister(UNW_X86_64_R9, regs->r9);
|
||||||
|
_registers.setRegister(UNW_X86_64_R10, regs->r10);
|
||||||
|
_registers.setRegister(UNW_X86_64_R11, regs->r11);
|
||||||
|
_registers.setRegister(UNW_X86_64_R12, regs->r12);
|
||||||
|
_registers.setRegister(UNW_X86_64_R13, regs->r13);
|
||||||
|
_registers.setRegister(UNW_X86_64_R14, regs->r14);
|
||||||
|
_registers.setRegister(UNW_X86_64_R15, regs->r15);
|
||||||
|
// TODO: XMM
|
||||||
|
#endif // defined(_LIBUNWIND_TARGET_X86_64)
|
||||||
|
|
||||||
|
return UNW_STEP_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif // defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
|
||||||
|
|
||||||
template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
|
template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
|
||||||
(void)stage2;
|
(void)stage2;
|
||||||
// Bottom of stack is defined is when unwind info cannot be found.
|
// Bottom of stack is defined is when unwind info cannot be found.
|
||||||
|
|
@ -2981,7 +3151,7 @@ template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
|
||||||
// Use unwinding info to modify register set as if function returned.
|
// Use unwinding info to modify register set as if function returned.
|
||||||
int result;
|
int result;
|
||||||
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
|
#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
|
||||||
defined(_LIBUNWIND_TARGET_HAIKU)
|
defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
|
||||||
if (_isSigReturn) {
|
if (_isSigReturn) {
|
||||||
result = this->stepThroughSigReturn();
|
result = this->stepThroughSigReturn();
|
||||||
} else
|
} else
|
||||||
|
|
@ -3062,7 +3232,7 @@ bool UnwindCursor<A, R>::isReadableAddr(const pint_t addr) const {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)
|
#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)
|
||||||
extern "C" void *__libunwind_cet_get_registers(unw_cursor_t *cursor) {
|
extern "C" void *__libunwind_shstk_get_registers(unw_cursor_t *cursor) {
|
||||||
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
|
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
|
||||||
return co->get_registers();
|
return co->get_registers();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
75
lib/libunwind/src/UnwindLevel1.c
vendored
75
lib/libunwind/src/UnwindLevel1.c
vendored
|
|
@ -25,10 +25,10 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "cet_unwind.h"
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "libunwind.h"
|
#include "libunwind.h"
|
||||||
#include "libunwind_ext.h"
|
#include "libunwind_ext.h"
|
||||||
|
#include "shadow_stack_unwind.h"
|
||||||
#include "unwind.h"
|
#include "unwind.h"
|
||||||
|
|
||||||
#if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) && \
|
#if !defined(_LIBUNWIND_ARM_EHABI) && !defined(__USING_SJLJ_EXCEPTIONS__) && \
|
||||||
|
|
@ -36,14 +36,17 @@
|
||||||
|
|
||||||
#ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND
|
#ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND
|
||||||
|
|
||||||
// When CET is enabled, each "call" instruction will push return address to
|
// When shadow stack is enabled, a separate stack containing only return
|
||||||
// CET shadow stack, each "ret" instruction will pop current CET shadow stack
|
// addresses would be maintained. On function return, the return address would
|
||||||
// top and compare it with target address which program will return.
|
// be compared to the popped address from shadow stack to ensure the return
|
||||||
// In exception handing, some stack frames will be skipped before jumping to
|
// target is not tempered with. When unwinding, we're skipping the normal return
|
||||||
// landing pad and we must adjust CET shadow stack accordingly.
|
// procedure for multiple frames and thus need to pop the return addresses of
|
||||||
// _LIBUNWIND_POP_CET_SSP is used to adjust CET shadow stack pointer and we
|
// the skipped frames from shadow stack to avoid triggering an exception (using
|
||||||
// directly jump to __libunwind_Registers_x86/x86_64_jumpto instead of using
|
// `_LIBUNWIND_POP_SHSTK_SSP()`). Also, some architectures, like the x86-family
|
||||||
// a regular function call to avoid pushing to CET shadow stack again.
|
// CET, push the return adddresses onto shadow stack with common call
|
||||||
|
// instructions, so for these architectures, normal function calls should be
|
||||||
|
// avoided when invoking the `jumpto()` function. To do this, we use inline
|
||||||
|
// assemblies to "goto" the `jumpto()` for these architectures.
|
||||||
#if !defined(_LIBUNWIND_USE_CET) && !defined(_LIBUNWIND_USE_GCS)
|
#if !defined(_LIBUNWIND_USE_CET) && !defined(_LIBUNWIND_USE_GCS)
|
||||||
#define __unw_phase2_resume(cursor, fn) \
|
#define __unw_phase2_resume(cursor, fn) \
|
||||||
do { \
|
do { \
|
||||||
|
|
@ -51,38 +54,38 @@
|
||||||
__unw_resume((cursor)); \
|
__unw_resume((cursor)); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#elif defined(_LIBUNWIND_TARGET_I386)
|
#elif defined(_LIBUNWIND_TARGET_I386)
|
||||||
#define __cet_ss_step_size 4
|
#define __shstk_step_size (4)
|
||||||
#define __unw_phase2_resume(cursor, fn) \
|
#define __unw_phase2_resume(cursor, fn) \
|
||||||
do { \
|
do { \
|
||||||
_LIBUNWIND_POP_CET_SSP((fn)); \
|
_LIBUNWIND_POP_SHSTK_SSP((fn)); \
|
||||||
void *cetRegContext = __libunwind_cet_get_registers((cursor)); \
|
void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \
|
||||||
void *cetJumpAddress = __libunwind_cet_get_jump_target(); \
|
void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \
|
||||||
__asm__ volatile("push %%edi\n\t" \
|
__asm__ volatile("push %%edi\n\t" \
|
||||||
"sub $4, %%esp\n\t" \
|
"sub $4, %%esp\n\t" \
|
||||||
"jmp *%%edx\n\t" :: "D"(cetRegContext), \
|
"jmp *%%edx\n\t" ::"D"(shstkRegContext), \
|
||||||
"d"(cetJumpAddress)); \
|
"d"(shstkJumpAddress)); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#elif defined(_LIBUNWIND_TARGET_X86_64)
|
#elif defined(_LIBUNWIND_TARGET_X86_64)
|
||||||
#define __cet_ss_step_size 8
|
#define __shstk_step_size (8)
|
||||||
#define __unw_phase2_resume(cursor, fn) \
|
#define __unw_phase2_resume(cursor, fn) \
|
||||||
do { \
|
do { \
|
||||||
_LIBUNWIND_POP_CET_SSP((fn)); \
|
_LIBUNWIND_POP_SHSTK_SSP((fn)); \
|
||||||
void *cetRegContext = __libunwind_cet_get_registers((cursor)); \
|
void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \
|
||||||
void *cetJumpAddress = __libunwind_cet_get_jump_target(); \
|
void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \
|
||||||
__asm__ volatile("jmpq *%%rdx\n\t" :: "D"(cetRegContext), \
|
__asm__ volatile("jmpq *%%rdx\n\t" ::"D"(shstkRegContext), \
|
||||||
"d"(cetJumpAddress)); \
|
"d"(shstkJumpAddress)); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#elif defined(_LIBUNWIND_TARGET_AARCH64)
|
#elif defined(_LIBUNWIND_TARGET_AARCH64)
|
||||||
#define __cet_ss_step_size 8
|
#define __shstk_step_size (8)
|
||||||
#define __unw_phase2_resume(cursor, fn) \
|
#define __unw_phase2_resume(cursor, fn) \
|
||||||
do { \
|
do { \
|
||||||
_LIBUNWIND_POP_CET_SSP((fn)); \
|
_LIBUNWIND_POP_SHSTK_SSP((fn)); \
|
||||||
void *cetRegContext = __libunwind_cet_get_registers((cursor)); \
|
void *shstkRegContext = __libunwind_shstk_get_registers((cursor)); \
|
||||||
void *cetJumpAddress = __libunwind_cet_get_jump_target(); \
|
void *shstkJumpAddress = __libunwind_shstk_get_jump_target(); \
|
||||||
__asm__ volatile("mov x0, %0\n\t" \
|
__asm__ volatile("mov x0, %0\n\t" \
|
||||||
"br %1\n\t" \
|
"br %1\n\t" \
|
||||||
: \
|
: \
|
||||||
: "r"(cetRegContext), "r"(cetJumpAddress) \
|
: "r"(shstkRegContext), "r"(shstkJumpAddress) \
|
||||||
: "x0"); \
|
: "x0"); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -185,10 +188,11 @@ extern int __unw_step_stage2(unw_cursor_t *);
|
||||||
|
|
||||||
#if defined(_LIBUNWIND_USE_GCS)
|
#if defined(_LIBUNWIND_USE_GCS)
|
||||||
// Enable the GCS target feature to permit gcspop instructions to be used.
|
// Enable the GCS target feature to permit gcspop instructions to be used.
|
||||||
__attribute__((target("gcs")))
|
__attribute__((target("+gcs")))
|
||||||
#endif
|
#endif
|
||||||
static _Unwind_Reason_Code
|
static _Unwind_Reason_Code
|
||||||
unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
|
unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,
|
||||||
|
_Unwind_Exception *exception_object) {
|
||||||
__unw_init_local(cursor, uc);
|
__unw_init_local(cursor, uc);
|
||||||
|
|
||||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p)",
|
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p)",
|
||||||
|
|
@ -255,16 +259,16 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// In CET enabled environment, we check return address stored in normal stack
|
// In shadow stack enabled environment, we check return address stored in normal
|
||||||
// against return address stored in CET shadow stack, if the 2 addresses don't
|
// stack against return address stored in shadow stack, if the 2 addresses don't
|
||||||
// match, it means return address in normal stack has been corrupted, we return
|
// match, it means return address in normal stack has been corrupted, we return
|
||||||
// _URC_FATAL_PHASE2_ERROR.
|
// _URC_FATAL_PHASE2_ERROR.
|
||||||
#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)
|
#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)
|
||||||
if (shadowStackTop != 0) {
|
if (shadowStackTop != 0) {
|
||||||
unw_word_t retInNormalStack;
|
unw_word_t retInNormalStack;
|
||||||
__unw_get_reg(cursor, UNW_REG_IP, &retInNormalStack);
|
__unw_get_reg(cursor, UNW_REG_IP, &retInNormalStack);
|
||||||
unsigned long retInShadowStack = *(
|
unsigned long retInShadowStack =
|
||||||
unsigned long *)(shadowStackTop + __cet_ss_step_size * framesWalked);
|
*(unsigned long *)(shadowStackTop + __shstk_step_size * framesWalked);
|
||||||
if (retInNormalStack != retInShadowStack)
|
if (retInNormalStack != retInShadowStack)
|
||||||
return _URC_FATAL_PHASE2_ERROR;
|
return _URC_FATAL_PHASE2_ERROR;
|
||||||
}
|
}
|
||||||
|
|
@ -329,12 +333,12 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
|
||||||
|
|
||||||
#if defined(_LIBUNWIND_USE_GCS)
|
#if defined(_LIBUNWIND_USE_GCS)
|
||||||
// Enable the GCS target feature to permit gcspop instructions to be used.
|
// Enable the GCS target feature to permit gcspop instructions to be used.
|
||||||
__attribute__((target("gcs")))
|
__attribute__((target("+gcs")))
|
||||||
#endif
|
#endif
|
||||||
static _Unwind_Reason_Code
|
static _Unwind_Reason_Code
|
||||||
unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
|
unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
|
||||||
_Unwind_Exception *exception_object,
|
_Unwind_Exception *exception_object, _Unwind_Stop_Fn stop,
|
||||||
_Unwind_Stop_Fn stop, void *stop_parameter) {
|
void *stop_parameter) {
|
||||||
__unw_init_local(cursor, uc);
|
__unw_init_local(cursor, uc);
|
||||||
|
|
||||||
// uc is initialized by __unw_getcontext in the parent frame. The first stack
|
// uc is initialized by __unw_getcontext in the parent frame. The first stack
|
||||||
|
|
@ -440,7 +444,6 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
|
||||||
return _URC_FATAL_PHASE2_ERROR;
|
return _URC_FATAL_PHASE2_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Called by __cxa_throw. Only returns if there is a fatal error.
|
/// Called by __cxa_throw. Only returns if there is a fatal error.
|
||||||
_LIBUNWIND_EXPORT _Unwind_Reason_Code
|
_LIBUNWIND_EXPORT _Unwind_Reason_Code
|
||||||
_Unwind_RaiseException(_Unwind_Exception *exception_object) {
|
_Unwind_RaiseException(_Unwind_Exception *exception_object) {
|
||||||
|
|
|
||||||
2
lib/libunwind/src/UnwindRegistersRestore.S
vendored
2
lib/libunwind/src/UnwindRegistersRestore.S
vendored
|
|
@ -66,7 +66,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto)
|
||||||
# skip fs
|
# skip fs
|
||||||
# skip gs
|
# skip gs
|
||||||
|
|
||||||
#elif defined(__x86_64__)
|
#elif defined(__x86_64__) && !defined(__arm64ec__)
|
||||||
|
|
||||||
DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto)
|
DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto)
|
||||||
#
|
#
|
||||||
|
|
|
||||||
49
lib/libunwind/src/UnwindRegistersSave.S
vendored
49
lib/libunwind/src/UnwindRegistersSave.S
vendored
|
|
@ -65,6 +65,47 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
|
||||||
xorl %eax, %eax # return UNW_ESUCCESS
|
xorl %eax, %eax # return UNW_ESUCCESS
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
#elif defined(__arm64ec__)
|
||||||
|
|
||||||
|
//
|
||||||
|
// extern int __unw_getcontext(unw_context_t* thread_state)
|
||||||
|
//
|
||||||
|
// On entry:
|
||||||
|
// thread_state pointer is in x0
|
||||||
|
//
|
||||||
|
.section .text,"xr",discard,"#__unw_getcontext"
|
||||||
|
.p2align 2
|
||||||
|
DEFINE_LIBUNWIND_FUNCTION("#__unw_getcontext")
|
||||||
|
stp x8, x27, [x0, #0x000] // rax, rbx
|
||||||
|
stp x0, x1, [x0, #0x010] // rcx, rdx
|
||||||
|
stp x26,x25, [x0, #0x020] // rdi, rsi
|
||||||
|
mov x1, sp
|
||||||
|
stp fp, x1, [x0, #0x030] // rbp, rsp
|
||||||
|
stp x2, x3, [x0, #0x040] // r8, r9
|
||||||
|
stp x4, x5, [x0, #0x050] // r10, r11
|
||||||
|
stp x19,x20, [x0, #0x060] // r12, r13
|
||||||
|
stp x21,x22, [x0, #0x070] // r14, r15
|
||||||
|
str x30, [x0, #0x080] // store return address as pc
|
||||||
|
stp q0, q1, [x0, #0x0b0] // xmm0, xmm1
|
||||||
|
stp q2, q3, [x0, #0x0d0] // xmm2, xmm3
|
||||||
|
stp q4, q5, [x0, #0x0f0] // xmm4, xmm5
|
||||||
|
stp q6, q7, [x0, #0x110] // xmm6, xmm7
|
||||||
|
stp q8, q9, [x0, #0x130] // xmm8, xmm9
|
||||||
|
stp q10,q11, [x0, #0x150] // xmm10,xmm11
|
||||||
|
stp q12,q13, [x0, #0x170] // xmm12,xmm13
|
||||||
|
stp q14,q15, [x0, #0x190] // xmm14,xmm15
|
||||||
|
mov x0, #0 // return UNW_ESUCCESS
|
||||||
|
ret
|
||||||
|
|
||||||
|
.weak_anti_dep __unw_getcontext
|
||||||
|
.set __unw_getcontext, "#__unw_getcontext"
|
||||||
|
|
||||||
|
.section .hybmp$x,"yi"
|
||||||
|
.symidx "#__unw_getcontext"
|
||||||
|
.symidx $ientry_thunk$cdecl$i8$i8
|
||||||
|
.word 1
|
||||||
|
.text
|
||||||
|
|
||||||
#elif defined(__x86_64__)
|
#elif defined(__x86_64__)
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
@ -1181,7 +1222,15 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __arm64ec__
|
||||||
|
.globl "#unw_getcontext"
|
||||||
|
.set "#unw_getcontext", "#__unw_getcontext"
|
||||||
|
.weak_anti_dep unw_getcontext
|
||||||
|
.set unw_getcontext, "#unw_getcontext"
|
||||||
|
EXPORT_SYMBOL(unw_getcontext)
|
||||||
|
#else
|
||||||
WEAK_ALIAS(__unw_getcontext, unw_getcontext)
|
WEAK_ALIAS(__unw_getcontext, unw_getcontext)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */
|
#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__wasm__) */
|
||||||
|
|
||||||
|
|
|
||||||
2
lib/libunwind/src/gcc_personality_v0.c
vendored
2
lib/libunwind/src/gcc_personality_v0.c
vendored
|
|
@ -6,6 +6,7 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
/* zig patch: remove compiler-rt int_lib.h dependency */
|
||||||
#if __ARM_EABI__
|
#if __ARM_EABI__
|
||||||
#ifdef COMPILER_RT_ARMHF_TARGET
|
#ifdef COMPILER_RT_ARMHF_TARGET
|
||||||
#define COMPILER_RT_ABI
|
#define COMPILER_RT_ABI
|
||||||
|
|
@ -19,6 +20,7 @@
|
||||||
#define compilerrt_abort() __builtin_unreachable()
|
#define compilerrt_abort() __builtin_unreachable()
|
||||||
|
|
||||||
#include <unwind.h>
|
#include <unwind.h>
|
||||||
|
/* zig patch: remove unwind-ehabi-helpers.h dependency */
|
||||||
|
|
||||||
#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
|
#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#ifndef LIBUNWIND_CET_UNWIND_H
|
#ifndef LIBUNWIND_SHADOW_STACK_UNWIND_H
|
||||||
#define LIBUNWIND_CET_UNWIND_H
|
#define LIBUNWIND_SHADOW_STACK_UNWIND_H
|
||||||
|
|
||||||
#include "libunwind.h"
|
#include "libunwind.h"
|
||||||
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
#include <cet.h>
|
#include <cet.h>
|
||||||
#include <immintrin.h>
|
#include <immintrin.h>
|
||||||
|
|
||||||
#define _LIBUNWIND_POP_CET_SSP(x) \
|
#define _LIBUNWIND_POP_SHSTK_SSP(x) \
|
||||||
do { \
|
do { \
|
||||||
unsigned long ssp = _get_ssp(); \
|
unsigned long ssp = _get_ssp(); \
|
||||||
if (ssp != 0) { \
|
if (ssp != 0) { \
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
#define _LIBUNWIND_USE_GCS 1
|
#define _LIBUNWIND_USE_GCS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define _LIBUNWIND_POP_CET_SSP(x) \
|
#define _LIBUNWIND_POP_SHSTK_SSP(x) \
|
||||||
do { \
|
do { \
|
||||||
if (__chkfeat(_CHKFEAT_GCS)) { \
|
if (__chkfeat(_CHKFEAT_GCS)) { \
|
||||||
unsigned tmp = (x); \
|
unsigned tmp = (x); \
|
||||||
|
|
@ -57,7 +57,7 @@
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void *__libunwind_cet_get_registers(unw_cursor_t *);
|
extern void *__libunwind_shstk_get_registers(unw_cursor_t *);
|
||||||
extern void *__libunwind_cet_get_jump_target(void);
|
extern void *__libunwind_shstk_get_jump_target(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Loading…
Add table
Reference in a new issue