diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2021-11-19 20:06:13 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2021-11-19 20:06:13 +0000 |
commit | c0981da47d5696fe36474fcf86b4ce03ae3ff818 (patch) | |
tree | f42add1021b9f2ac6a69ac7cf6c4499962739a45 /libunwind | |
parent | 344a3780b2e33f6ca763666c380202b18aab72a3 (diff) | |
download | src-c0981da47d5696fe36474fcf86b4ce03ae3ff818.tar.gz src-c0981da47d5696fe36474fcf86b4ce03ae3ff818.zip |
Vendor import of llvm-project main llvmorg-14-init-10186-gff7f2cfa959b.vendor/llvm-project/llvmorg-14-init-10186-gff7f2cfa959b
Diffstat (limited to 'libunwind')
29 files changed, 938 insertions, 493 deletions
diff --git a/libunwind/include/__libunwind_config.h b/libunwind/include/__libunwind_config.h index a50ba053884b..221980a24aeb 100644 --- a/libunwind/include/__libunwind_config.h +++ b/libunwind/include/__libunwind_config.h @@ -1,4 +1,4 @@ -//===------------------------- __libunwind_config.h -----------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libunwind/include/libunwind.h b/libunwind/include/libunwind.h index 0feecd7bd6fc..e187ee27b0db 100644 --- a/libunwind/include/libunwind.h +++ b/libunwind/include/libunwind.h @@ -1,4 +1,4 @@ -//===---------------------------- libunwind.h -----------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -493,77 +493,150 @@ enum { // 64-bit ARM64 registers enum { - UNW_ARM64_X0 = 0, - UNW_ARM64_X1 = 1, - UNW_ARM64_X2 = 2, - UNW_ARM64_X3 = 3, - UNW_ARM64_X4 = 4, - UNW_ARM64_X5 = 5, - UNW_ARM64_X6 = 6, - UNW_ARM64_X7 = 7, - UNW_ARM64_X8 = 8, - UNW_ARM64_X9 = 9, - UNW_ARM64_X10 = 10, - UNW_ARM64_X11 = 11, - UNW_ARM64_X12 = 12, - UNW_ARM64_X13 = 13, - UNW_ARM64_X14 = 14, - UNW_ARM64_X15 = 15, - UNW_ARM64_X16 = 16, - UNW_ARM64_X17 = 17, - UNW_ARM64_X18 = 18, - UNW_ARM64_X19 = 19, - UNW_ARM64_X20 = 20, - UNW_ARM64_X21 = 21, - UNW_ARM64_X22 = 22, - UNW_ARM64_X23 = 23, - UNW_ARM64_X24 = 24, - UNW_ARM64_X25 = 25, - UNW_ARM64_X26 = 26, - UNW_ARM64_X27 = 27, - UNW_ARM64_X28 = 28, - UNW_ARM64_X29 = 29, - UNW_ARM64_FP = 29, - UNW_ARM64_X30 = 30, - UNW_ARM64_LR = 30, - UNW_ARM64_X31 = 31, - UNW_ARM64_SP = 31, - UNW_ARM64_PC = 32, - // reserved block - UNW_ARM64_RA_SIGN_STATE = 34, + UNW_AARCH64_X0 = 0, + UNW_AARCH64_X1 = 1, + UNW_AARCH64_X2 = 2, + UNW_AARCH64_X3 = 3, + UNW_AARCH64_X4 = 4, + UNW_AARCH64_X5 = 5, + UNW_AARCH64_X6 = 6, + UNW_AARCH64_X7 = 7, + UNW_AARCH64_X8 = 8, + UNW_AARCH64_X9 = 9, + UNW_AARCH64_X10 = 10, + UNW_AARCH64_X11 = 11, + UNW_AARCH64_X12 = 12, + UNW_AARCH64_X13 = 13, + UNW_AARCH64_X14 = 14, + UNW_AARCH64_X15 = 15, + UNW_AARCH64_X16 = 16, + UNW_AARCH64_X17 = 17, + UNW_AARCH64_X18 = 18, + UNW_AARCH64_X19 = 19, + UNW_AARCH64_X20 = 20, + UNW_AARCH64_X21 = 21, + UNW_AARCH64_X22 = 22, + UNW_AARCH64_X23 = 23, + UNW_AARCH64_X24 = 24, + UNW_AARCH64_X25 = 25, + UNW_AARCH64_X26 = 26, + UNW_AARCH64_X27 = 27, + UNW_AARCH64_X28 = 28, + UNW_AARCH64_X29 = 29, + UNW_AARCH64_FP = 29, + UNW_AARCH64_X30 = 30, + UNW_AARCH64_LR = 30, + UNW_AARCH64_X31 = 31, + UNW_AARCH64_SP = 31, + UNW_AARCH64_PC = 32, + // reserved block - UNW_ARM64_D0 = 64, - UNW_ARM64_D1 = 65, - UNW_ARM64_D2 = 66, - UNW_ARM64_D3 = 67, - UNW_ARM64_D4 = 68, - UNW_ARM64_D5 = 69, - UNW_ARM64_D6 = 70, - UNW_ARM64_D7 = 71, - UNW_ARM64_D8 = 72, - UNW_ARM64_D9 = 73, - UNW_ARM64_D10 = 74, - UNW_ARM64_D11 = 75, - UNW_ARM64_D12 = 76, - UNW_ARM64_D13 = 77, - UNW_ARM64_D14 = 78, - UNW_ARM64_D15 = 79, - UNW_ARM64_D16 = 80, - UNW_ARM64_D17 = 81, - UNW_ARM64_D18 = 82, - UNW_ARM64_D19 = 83, - UNW_ARM64_D20 = 84, - UNW_ARM64_D21 = 85, - UNW_ARM64_D22 = 86, - UNW_ARM64_D23 = 87, - UNW_ARM64_D24 = 88, - UNW_ARM64_D25 = 89, - UNW_ARM64_D26 = 90, - UNW_ARM64_D27 = 91, - UNW_ARM64_D28 = 92, - UNW_ARM64_D29 = 93, - UNW_ARM64_D30 = 94, - UNW_ARM64_D31 = 95, + UNW_AARCH64_RA_SIGN_STATE = 34, + + // FP/vector registers + UNW_AARCH64_V0 = 64, + UNW_AARCH64_V1 = 65, + UNW_AARCH64_V2 = 66, + UNW_AARCH64_V3 = 67, + UNW_AARCH64_V4 = 68, + UNW_AARCH64_V5 = 69, + UNW_AARCH64_V6 = 70, + UNW_AARCH64_V7 = 71, + UNW_AARCH64_V8 = 72, + UNW_AARCH64_V9 = 73, + UNW_AARCH64_V10 = 74, + UNW_AARCH64_V11 = 75, + UNW_AARCH64_V12 = 76, + UNW_AARCH64_V13 = 77, + UNW_AARCH64_V14 = 78, + UNW_AARCH64_V15 = 79, + UNW_AARCH64_V16 = 80, + UNW_AARCH64_V17 = 81, + UNW_AARCH64_V18 = 82, + UNW_AARCH64_V19 = 83, + UNW_AARCH64_V20 = 84, + UNW_AARCH64_V21 = 85, + UNW_AARCH64_V22 = 86, + UNW_AARCH64_V23 = 87, + UNW_AARCH64_V24 = 88, + UNW_AARCH64_V25 = 89, + UNW_AARCH64_V26 = 90, + UNW_AARCH64_V27 = 91, + UNW_AARCH64_V28 = 92, + UNW_AARCH64_V29 = 93, + UNW_AARCH64_V30 = 94, + UNW_AARCH64_V31 = 95, + + // Compatibility aliases + UNW_ARM64_X0 = UNW_AARCH64_X0, + UNW_ARM64_X1 = UNW_AARCH64_X1, + UNW_ARM64_X2 = UNW_AARCH64_X2, + UNW_ARM64_X3 = UNW_AARCH64_X3, + UNW_ARM64_X4 = UNW_AARCH64_X4, + UNW_ARM64_X5 = UNW_AARCH64_X5, + UNW_ARM64_X6 = UNW_AARCH64_X6, + UNW_ARM64_X7 = UNW_AARCH64_X7, + UNW_ARM64_X8 = UNW_AARCH64_X8, + UNW_ARM64_X9 = UNW_AARCH64_X9, + UNW_ARM64_X10 = UNW_AARCH64_X10, + UNW_ARM64_X11 = UNW_AARCH64_X11, + UNW_ARM64_X12 = UNW_AARCH64_X12, + UNW_ARM64_X13 = UNW_AARCH64_X13, + UNW_ARM64_X14 = UNW_AARCH64_X14, + UNW_ARM64_X15 = UNW_AARCH64_X15, + UNW_ARM64_X16 = UNW_AARCH64_X16, + UNW_ARM64_X17 = UNW_AARCH64_X17, + UNW_ARM64_X18 = UNW_AARCH64_X18, + UNW_ARM64_X19 = UNW_AARCH64_X19, + UNW_ARM64_X20 = UNW_AARCH64_X20, + UNW_ARM64_X21 = UNW_AARCH64_X21, + UNW_ARM64_X22 = UNW_AARCH64_X22, + UNW_ARM64_X23 = UNW_AARCH64_X23, + UNW_ARM64_X24 = UNW_AARCH64_X24, + UNW_ARM64_X25 = UNW_AARCH64_X25, + UNW_ARM64_X26 = UNW_AARCH64_X26, + UNW_ARM64_X27 = UNW_AARCH64_X27, + UNW_ARM64_X28 = UNW_AARCH64_X28, + UNW_ARM64_X29 = UNW_AARCH64_X29, + UNW_ARM64_FP = UNW_AARCH64_FP, + UNW_ARM64_X30 = UNW_AARCH64_X30, + UNW_ARM64_LR = UNW_AARCH64_LR, + UNW_ARM64_X31 = UNW_AARCH64_X31, + UNW_ARM64_SP = UNW_AARCH64_SP, + UNW_ARM64_PC = UNW_AARCH64_PC, + UNW_ARM64_RA_SIGN_STATE = UNW_AARCH64_RA_SIGN_STATE, + UNW_ARM64_D0 = UNW_AARCH64_V0, + UNW_ARM64_D1 = UNW_AARCH64_V1, + UNW_ARM64_D2 = UNW_AARCH64_V2, + UNW_ARM64_D3 = UNW_AARCH64_V3, + UNW_ARM64_D4 = UNW_AARCH64_V4, + UNW_ARM64_D5 = UNW_AARCH64_V5, + UNW_ARM64_D6 = UNW_AARCH64_V6, + UNW_ARM64_D7 = UNW_AARCH64_V7, + UNW_ARM64_D8 = UNW_AARCH64_V8, + UNW_ARM64_D9 = UNW_AARCH64_V9, + UNW_ARM64_D10 = UNW_AARCH64_V10, + UNW_ARM64_D11 = UNW_AARCH64_V11, + UNW_ARM64_D12 = UNW_AARCH64_V12, + UNW_ARM64_D13 = UNW_AARCH64_V13, + UNW_ARM64_D14 = UNW_AARCH64_V14, + UNW_ARM64_D15 = UNW_AARCH64_V15, + UNW_ARM64_D16 = UNW_AARCH64_V16, + UNW_ARM64_D17 = UNW_AARCH64_V17, + UNW_ARM64_D18 = UNW_AARCH64_V18, + UNW_ARM64_D19 = UNW_AARCH64_V19, + UNW_ARM64_D20 = UNW_AARCH64_V20, + UNW_ARM64_D21 = UNW_AARCH64_V21, + UNW_ARM64_D22 = UNW_AARCH64_V22, + UNW_ARM64_D23 = UNW_AARCH64_V23, + UNW_ARM64_D24 = UNW_AARCH64_V24, + UNW_ARM64_D25 = UNW_AARCH64_V25, + UNW_ARM64_D26 = UNW_AARCH64_V26, + UNW_ARM64_D27 = UNW_AARCH64_V27, + UNW_ARM64_D28 = UNW_AARCH64_V28, + UNW_ARM64_D29 = UNW_AARCH64_V29, + UNW_ARM64_D30 = UNW_AARCH64_V30, + UNW_ARM64_D31 = UNW_AARCH64_V31, }; // 32-bit ARM registers. Numbers match DWARF for ARM spec #3.1 Table 1. diff --git a/libunwind/include/mach-o/compact_unwind_encoding.h b/libunwind/include/mach-o/compact_unwind_encoding.h index 5301b1055ef9..68d562eec438 100644 --- a/libunwind/include/mach-o/compact_unwind_encoding.h +++ b/libunwind/include/mach-o/compact_unwind_encoding.h @@ -1,4 +1,4 @@ -//===------------------ mach-o/compact_unwind_encoding.h ------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libunwind/include/unwind.h b/libunwind/include/unwind.h index 1d3444cd83b4..b8d6020a3367 100644 --- a/libunwind/include/unwind.h +++ b/libunwind/include/unwind.h @@ -1,4 +1,4 @@ -//===------------------------------- unwind.h -----------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -56,211 +56,23 @@ typedef enum { typedef struct _Unwind_Context _Unwind_Context; // opaque #if defined(_LIBUNWIND_ARM_EHABI) -typedef uint32_t _Unwind_State; - -static const _Unwind_State _US_VIRTUAL_UNWIND_FRAME = 0; -static const _Unwind_State _US_UNWIND_FRAME_STARTING = 1; -static const _Unwind_State _US_UNWIND_FRAME_RESUME = 2; -static const _Unwind_State _US_ACTION_MASK = 3; -/* Undocumented flag for force unwinding. */ -static const _Unwind_State _US_FORCE_UNWIND = 8; - -typedef uint32_t _Unwind_EHT_Header; - -struct _Unwind_Control_Block; -typedef struct _Unwind_Control_Block _Unwind_Control_Block; -typedef struct _Unwind_Control_Block _Unwind_Exception; /* Alias */ - -struct _Unwind_Control_Block { - uint64_t exception_class; - void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block*); - - /* Unwinder cache, private fields for the unwinder's use */ - struct { - uint32_t reserved1; /* init reserved1 to 0, then don't touch */ - uint32_t reserved2; - uint32_t reserved3; - uint32_t reserved4; - uint32_t reserved5; - } unwinder_cache; - - /* Propagation barrier cache (valid after phase 1): */ - struct { - uint32_t sp; - uint32_t bitpattern[5]; - } barrier_cache; - - /* Cleanup cache (preserved over cleanup): */ - struct { - uint32_t bitpattern[4]; - } cleanup_cache; - - /* Pr cache (for pr's benefit): */ - struct { - uint32_t fnstart; /* function start address */ - _Unwind_EHT_Header* ehtp; /* pointer to EHT entry header word */ - uint32_t additional; - uint32_t reserved1; - } pr_cache; - - long long int :0; /* Enforce the 8-byte alignment */ -} __attribute__((__aligned__(8))); - -typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) - (_Unwind_State state, - _Unwind_Exception* exceptionObject, - struct _Unwind_Context* context); - -typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)( - _Unwind_State state, _Unwind_Exception *exceptionObject, - struct _Unwind_Context *context); +#include "unwind_arm_ehabi.h" #else -struct _Unwind_Context; // opaque -struct _Unwind_Exception; // forward declaration -typedef struct _Unwind_Exception _Unwind_Exception; - -struct _Unwind_Exception { - uint64_t exception_class; - void (*exception_cleanup)(_Unwind_Reason_Code reason, - _Unwind_Exception *exc); -#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) - uintptr_t private_[6]; -#else - uintptr_t private_1; // non-zero means forced unwind - uintptr_t private_2; // holds sp that phase1 found for phase2 to use +#include "unwind_itanium.h" #endif -#if __SIZEOF_POINTER__ == 4 - // The implementation of _Unwind_Exception uses an attribute mode on the - // above fields which has the side effect of causing this whole struct to - // round up to 32 bytes in size (48 with SEH). To be more explicit, we add - // pad fields added for binary compatibility. - uint32_t reserved[3]; -#endif - // The Itanium ABI requires that _Unwind_Exception objects are "double-word - // aligned". GCC has interpreted this to mean "use the maximum useful - // alignment for the target"; so do we. -} __attribute__((__aligned__)); typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) (int version, _Unwind_Action actions, - uint64_t exceptionClass, + _Unwind_Exception_Class exceptionClass, _Unwind_Exception* exceptionObject, struct _Unwind_Context* context, - void* stop_parameter ); - -typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)( - int version, _Unwind_Action actions, uint64_t exceptionClass, - _Unwind_Exception *exceptionObject, struct _Unwind_Context *context); -#endif + void* stop_parameter); #ifdef __cplusplus extern "C" { #endif -// -// The following are the base functions documented by the C++ ABI -// -#ifdef __USING_SJLJ_EXCEPTIONS__ -extern _Unwind_Reason_Code - _Unwind_SjLj_RaiseException(_Unwind_Exception *exception_object); -extern void _Unwind_SjLj_Resume(_Unwind_Exception *exception_object); -#else -extern _Unwind_Reason_Code - _Unwind_RaiseException(_Unwind_Exception *exception_object); -extern void _Unwind_Resume(_Unwind_Exception *exception_object); -#endif -extern void _Unwind_DeleteException(_Unwind_Exception *exception_object); - -#if defined(_LIBUNWIND_ARM_EHABI) -typedef enum { - _UVRSC_CORE = 0, /* integer register */ - _UVRSC_VFP = 1, /* vfp */ - _UVRSC_WMMXD = 3, /* Intel WMMX data register */ - _UVRSC_WMMXC = 4 /* Intel WMMX control register */ -} _Unwind_VRS_RegClass; - -typedef enum { - _UVRSD_UINT32 = 0, - _UVRSD_VFPX = 1, - _UVRSD_UINT64 = 3, - _UVRSD_FLOAT = 4, - _UVRSD_DOUBLE = 5 -} _Unwind_VRS_DataRepresentation; - -typedef enum { - _UVRSR_OK = 0, - _UVRSR_NOT_IMPLEMENTED = 1, - _UVRSR_FAILED = 2 -} _Unwind_VRS_Result; - -extern void _Unwind_Complete(_Unwind_Exception* exception_object); - -extern _Unwind_VRS_Result -_Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, - uint32_t regno, _Unwind_VRS_DataRepresentation representation, - void *valuep); - -extern _Unwind_VRS_Result -_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, - uint32_t regno, _Unwind_VRS_DataRepresentation representation, - void *valuep); - -extern _Unwind_VRS_Result -_Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, - uint32_t discriminator, - _Unwind_VRS_DataRepresentation representation); -#endif - -#if !defined(_LIBUNWIND_ARM_EHABI) - -extern uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index); -extern void _Unwind_SetGR(struct _Unwind_Context *context, int index, - uintptr_t new_value); -extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context); -extern void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t new_value); - -#else // defined(_LIBUNWIND_ARM_EHABI) - -#if defined(_LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE) -#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern -#else -#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 static __inline__ -#endif - -// These are de facto helper functions for ARM, which delegate the function -// calls to _Unwind_VRS_Get/Set(). These are not a part of ARM EHABI -// specification, thus these function MUST be inlined. Please don't replace -// these with the "extern" function declaration; otherwise, the program -// including this <unwind.h> header won't be ABI compatible and will result in -// link error when we are linking the program with libgcc. - -_LIBUNWIND_EXPORT_UNWIND_LEVEL1 -uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) { - uintptr_t value = 0; - _Unwind_VRS_Get(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value); - return value; -} - -_LIBUNWIND_EXPORT_UNWIND_LEVEL1 -void _Unwind_SetGR(struct _Unwind_Context *context, int index, - uintptr_t value) { - _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value); -} - -_LIBUNWIND_EXPORT_UNWIND_LEVEL1 -uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { - // remove the thumb-bit before returning - return _Unwind_GetGR(context, 15) & (~(uintptr_t)0x1); -} - -_LIBUNWIND_EXPORT_UNWIND_LEVEL1 -void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t value) { - uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1); - _Unwind_SetGR(context, 15, value | thumb_bit); -} -#endif // defined(_LIBUNWIND_ARM_EHABI) - extern uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context); extern uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context); diff --git a/libunwind/include/unwind_arm_ehabi.h b/libunwind/include/unwind_arm_ehabi.h new file mode 100644 index 000000000000..dc9d403e264c --- /dev/null +++ b/libunwind/include/unwind_arm_ehabi.h @@ -0,0 +1,169 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +// +// C++ ABI Level 1 ABI documented at: +// https://github.com/ARM-software/abi-aa/blob/main/ehabi32/ehabi32.rst +// +//===----------------------------------------------------------------------===// + +#ifndef __ARM_EHABI_UNWIND_H__ +#define __ARM_EHABI_UNWIND_H__ + +typedef uint32_t _Unwind_State; + +static const _Unwind_State _US_VIRTUAL_UNWIND_FRAME = 0; +static const _Unwind_State _US_UNWIND_FRAME_STARTING = 1; +static const _Unwind_State _US_UNWIND_FRAME_RESUME = 2; +static const _Unwind_State _US_ACTION_MASK = 3; +/* Undocumented flag for force unwinding. */ +static const _Unwind_State _US_FORCE_UNWIND = 8; + +typedef uint32_t _Unwind_EHT_Header; + +struct _Unwind_Control_Block; +typedef struct _Unwind_Control_Block _Unwind_Control_Block; +#define _Unwind_Exception _Unwind_Control_Block /* Alias */ +typedef uint8_t _Unwind_Exception_Class[8]; + +struct _Unwind_Control_Block { + _Unwind_Exception_Class exception_class; + void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block*); + + /* Unwinder cache, private fields for the unwinder's use */ + struct { + uint32_t reserved1; /* init reserved1 to 0, then don't touch */ + uint32_t reserved2; + uint32_t reserved3; + uint32_t reserved4; + uint32_t reserved5; + } unwinder_cache; + + /* Propagation barrier cache (valid after phase 1): */ + struct { + uint32_t sp; + uint32_t bitpattern[5]; + } barrier_cache; + + /* Cleanup cache (preserved over cleanup): */ + struct { + uint32_t bitpattern[4]; + } cleanup_cache; + + /* Pr cache (for pr's benefit): */ + struct { + uint32_t fnstart; /* function start address */ + _Unwind_EHT_Header* ehtp; /* pointer to EHT entry header word */ + uint32_t additional; + uint32_t reserved1; + } pr_cache; + + long long int :0; /* Enforce the 8-byte alignment */ +} __attribute__((__aligned__(8))); + +typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)( + _Unwind_State state, _Unwind_Exception *exceptionObject, + struct _Unwind_Context *context); + +#ifdef __cplusplus +extern "C" { +#endif + +// +// The following are the base functions documented by the C++ ABI +// +#ifdef __USING_SJLJ_EXCEPTIONS__ +extern _Unwind_Reason_Code + _Unwind_SjLj_RaiseException(_Unwind_Exception *exception_object); +extern void _Unwind_SjLj_Resume(_Unwind_Exception *exception_object); +#else +extern _Unwind_Reason_Code + _Unwind_RaiseException(_Unwind_Exception *exception_object); +extern void _Unwind_Resume(_Unwind_Exception *exception_object); +#endif +extern void _Unwind_DeleteException(_Unwind_Exception *exception_object); + +typedef enum { + _UVRSC_CORE = 0, /* integer register */ + _UVRSC_VFP = 1, /* vfp */ + _UVRSC_WMMXD = 3, /* Intel WMMX data register */ + _UVRSC_WMMXC = 4 /* Intel WMMX control register */ +} _Unwind_VRS_RegClass; + +typedef enum { + _UVRSD_UINT32 = 0, + _UVRSD_VFPX = 1, + _UVRSD_UINT64 = 3, + _UVRSD_FLOAT = 4, + _UVRSD_DOUBLE = 5 +} _Unwind_VRS_DataRepresentation; + +typedef enum { + _UVRSR_OK = 0, + _UVRSR_NOT_IMPLEMENTED = 1, + _UVRSR_FAILED = 2 +} _Unwind_VRS_Result; + +extern void _Unwind_Complete(_Unwind_Exception* exception_object); + +extern _Unwind_VRS_Result +_Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, + uint32_t regno, _Unwind_VRS_DataRepresentation representation, + void *valuep); + +extern _Unwind_VRS_Result +_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, + uint32_t regno, _Unwind_VRS_DataRepresentation representation, + void *valuep); + +extern _Unwind_VRS_Result +_Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, + uint32_t discriminator, + _Unwind_VRS_DataRepresentation representation); + +#if defined(_LIBUNWIND_UNWIND_LEVEL1_EXTERNAL_LINKAGE) +#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 extern +#else +#define _LIBUNWIND_EXPORT_UNWIND_LEVEL1 static __inline__ +#endif + +// These are de facto helper functions for ARM, which delegate the function +// calls to _Unwind_VRS_Get/Set(). These are not a part of ARM EHABI +// specification, thus these function MUST be inlined. Please don't replace +// these with the "extern" function declaration; otherwise, the program +// including this <unwind.h> header won't be ABI compatible and will result in +// link error when we are linking the program with libgcc. + +_LIBUNWIND_EXPORT_UNWIND_LEVEL1 +uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) { + uintptr_t value = 0; + _Unwind_VRS_Get(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value); + return value; +} + +_LIBUNWIND_EXPORT_UNWIND_LEVEL1 +void _Unwind_SetGR(struct _Unwind_Context *context, int index, + uintptr_t value) { + _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value); +} + +_LIBUNWIND_EXPORT_UNWIND_LEVEL1 +uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { + // remove the thumb-bit before returning + return _Unwind_GetGR(context, 15) & (~(uintptr_t)0x1); +} + +_LIBUNWIND_EXPORT_UNWIND_LEVEL1 +void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t value) { + uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1); + _Unwind_SetGR(context, 15, value | thumb_bit); +} + +#ifdef __cplusplus +} +#endif + +#endif // __ARM_EHABI_UNWIND_H__ diff --git a/libunwind/include/unwind_itanium.h b/libunwind/include/unwind_itanium.h new file mode 100644 index 000000000000..d94a6183be29 --- /dev/null +++ b/libunwind/include/unwind_itanium.h @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +// +// C++ ABI Level 1 ABI documented at: +// https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html +// +//===----------------------------------------------------------------------===// + +#ifndef __ITANIUM_UNWIND_H__ +#define __ITANIUM_UNWIND_H__ + +struct _Unwind_Context; // opaque +struct _Unwind_Exception; // forward declaration +typedef struct _Unwind_Exception _Unwind_Exception; +typedef uint64_t _Unwind_Exception_Class; + +struct _Unwind_Exception { + _Unwind_Exception_Class exception_class; + void (*exception_cleanup)(_Unwind_Reason_Code reason, + _Unwind_Exception *exc); +#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) + uintptr_t private_[6]; +#else + uintptr_t private_1; // non-zero means forced unwind + uintptr_t private_2; // holds sp that phase1 found for phase2 to use +#endif +#if __SIZEOF_POINTER__ == 4 + // The implementation of _Unwind_Exception uses an attribute mode on the + // above fields which has the side effect of causing this whole struct to + // round up to 32 bytes in size (48 with SEH). To be more explicit, we add + // pad fields added for binary compatibility. + uint32_t reserved[3]; +#endif + // The Itanium ABI requires that _Unwind_Exception objects are "double-word + // aligned". GCC has interpreted this to mean "use the maximum useful + // alignment for the target"; so do we. +} __attribute__((__aligned__)); + +typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)( + int version, _Unwind_Action actions, uint64_t exceptionClass, + _Unwind_Exception *exceptionObject, struct _Unwind_Context *context); + +#ifdef __cplusplus +extern "C" { +#endif + +// +// The following are the base functions documented by the C++ ABI +// +#ifdef __USING_SJLJ_EXCEPTIONS__ +extern _Unwind_Reason_Code + _Unwind_SjLj_RaiseException(_Unwind_Exception *exception_object); +extern void _Unwind_SjLj_Resume(_Unwind_Exception *exception_object); +#else +extern _Unwind_Reason_Code + _Unwind_RaiseException(_Unwind_Exception *exception_object); +extern void _Unwind_Resume(_Unwind_Exception *exception_object); +#endif +extern void _Unwind_DeleteException(_Unwind_Exception *exception_object); + + +extern uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index); +extern void _Unwind_SetGR(struct _Unwind_Context *context, int index, + uintptr_t new_value); +extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context); +extern void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t new_value); + +#ifdef __cplusplus +} +#endif + +#endif // __ITANIUM_UNWIND_H__ diff --git a/libunwind/src/AddressSpace.hpp b/libunwind/src/AddressSpace.hpp index 171318ff6370..cfceac29537f 100644 --- a/libunwind/src/AddressSpace.hpp +++ b/libunwind/src/AddressSpace.hpp @@ -1,4 +1,4 @@ -//===------------------------- AddressSpace.hpp ---------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libunwind/src/CompactUnwinder.hpp b/libunwind/src/CompactUnwinder.hpp index 1c3175dff50a..0b2b5e111bfc 100644 --- a/libunwind/src/CompactUnwinder.hpp +++ b/libunwind/src/CompactUnwinder.hpp @@ -1,4 +1,4 @@ -//===-------------------------- CompactUnwinder.hpp -----------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -537,65 +537,65 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrameless( uint64_t savedRegisterLoc = registers.getSP() + stackSize; if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { - registers.setRegister(UNW_ARM64_X19, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { - registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { - registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { - registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { - registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { - registers.setFloatRegister(UNW_ARM64_D8, + registers.setFloatRegister(UNW_AARCH64_V8, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D9, + registers.setFloatRegister(UNW_AARCH64_V9, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { - registers.setFloatRegister(UNW_ARM64_D10, + registers.setFloatRegister(UNW_AARCH64_V10, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D11, + registers.setFloatRegister(UNW_AARCH64_V11, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { - registers.setFloatRegister(UNW_ARM64_D12, + registers.setFloatRegister(UNW_AARCH64_V12, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D13, + registers.setFloatRegister(UNW_AARCH64_V13, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { - registers.setFloatRegister(UNW_ARM64_D14, + registers.setFloatRegister(UNW_AARCH64_V14, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D15, + registers.setFloatRegister(UNW_AARCH64_V15, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } @@ -604,7 +604,7 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrameless( registers.setSP(savedRegisterLoc); // set pc to be value in lr - registers.setIP(registers.getRegister(UNW_ARM64_LR)); + registers.setIP(registers.getRegister(UNW_AARCH64_LR)); return UNW_STEP_SUCCESS; } @@ -616,65 +616,65 @@ int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame( uint64_t savedRegisterLoc = registers.getFP() - 8; if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { - registers.setRegister(UNW_ARM64_X19, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { - registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { - registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { - registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { - registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { - registers.setFloatRegister(UNW_ARM64_D8, + registers.setFloatRegister(UNW_AARCH64_V8, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D9, + registers.setFloatRegister(UNW_AARCH64_V9, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { - registers.setFloatRegister(UNW_ARM64_D10, + registers.setFloatRegister(UNW_AARCH64_V10, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D11, + registers.setFloatRegister(UNW_AARCH64_V11, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { - registers.setFloatRegister(UNW_ARM64_D12, + registers.setFloatRegister(UNW_AARCH64_V12, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D13, + registers.setFloatRegister(UNW_AARCH64_V13, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { - registers.setFloatRegister(UNW_ARM64_D14, + registers.setFloatRegister(UNW_AARCH64_V14, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; - registers.setFloatRegister(UNW_ARM64_D15, + registers.setFloatRegister(UNW_AARCH64_V15, addressSpace.getDouble(savedRegisterLoc)); savedRegisterLoc -= 8; } diff --git a/libunwind/src/DwarfInstructions.hpp b/libunwind/src/DwarfInstructions.hpp index 686c6be0d8fd..19835aad668f 100644 --- a/libunwind/src/DwarfInstructions.hpp +++ b/libunwind/src/DwarfInstructions.hpp @@ -1,4 +1,4 @@ -//===-------------------------- DwarfInstructions.hpp ---------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -115,12 +115,15 @@ double DwarfInstructions<A, R>::getSavedFloatRegister( return addressSpace.getDouble( evaluateExpression((pint_t)savedReg.value, addressSpace, registers, cfa)); - + case CFI_Parser<A>::kRegisterUndefined: + return 0.0; + case CFI_Parser<A>::kRegisterInRegister: +#ifndef _LIBUNWIND_TARGET_ARM + return registers.getFloatRegister((int)savedReg.value); +#endif case CFI_Parser<A>::kRegisterIsExpression: case CFI_Parser<A>::kRegisterUnused: - case CFI_Parser<A>::kRegisterUndefined: case CFI_Parser<A>::kRegisterOffsetFromCFA: - case CFI_Parser<A>::kRegisterInRegister: // FIX ME break; } @@ -219,7 +222,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, // restored. autia1716 is used instead of autia as autia1716 assembles // to a NOP on pre-v8.3a architectures. if ((R::getArch() == REGISTERS_ARM64) && - prolog.savedRegisters[UNW_ARM64_RA_SIGN_STATE].value && + prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value && returnAddress != 0) { #if !defined(_LIBUNWIND_IS_NATIVE_ONLY) return UNW_ECROSSRASIGNING; diff --git a/libunwind/src/DwarfParser.hpp b/libunwind/src/DwarfParser.hpp index de0eb6de9d70..2153a71c2ec0 100644 --- a/libunwind/src/DwarfParser.hpp +++ b/libunwind/src/DwarfParser.hpp @@ -1,4 +1,4 @@ -//===--------------------------- DwarfParser.hpp --------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -154,7 +154,8 @@ public: uintptr_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo, CIE_Info *cieInfo); static const char *decodeFDE(A &addressSpace, pint_t fdeStart, - FDE_Info *fdeInfo, CIE_Info *cieInfo); + FDE_Info *fdeInfo, CIE_Info *cieInfo, + bool useCIEInfo = false); static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo, const CIE_Info &cieInfo, pint_t upToPC, int arch, PrologInfo *results); @@ -162,10 +163,14 @@ public: static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo); }; -/// Parse a FDE into a CIE_Info and an FDE_Info +/// Parse a FDE into a CIE_Info and an FDE_Info. If useCIEInfo is +/// true, treat cieInfo as already-parsed CIE_Info (whose start offset +/// must match the one specified by the FDE) rather than parsing the +/// one indicated within the FDE. template <typename A> const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart, - FDE_Info *fdeInfo, CIE_Info *cieInfo) { + FDE_Info *fdeInfo, CIE_Info *cieInfo, + bool useCIEInfo) { pint_t p = fdeStart; pint_t cfiLength = (pint_t)addressSpace.get32(p); p += 4; @@ -181,9 +186,14 @@ const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart, return "FDE is really a CIE"; // this is a CIE not an FDE pint_t nextCFI = p + cfiLength; pint_t cieStart = p - ciePointer; - const char *err = parseCIE(addressSpace, cieStart, cieInfo); - if (err != NULL) - return err; + if (useCIEInfo) { + if (cieInfo->cieStart != cieStart) + return "CIE start does not match"; + } else { + const char *err = parseCIE(addressSpace, cieStart, cieInfo); + if (err != NULL) + return err; + } p += 4; // Parse pc begin and range. pint_t pcStart = @@ -733,8 +743,8 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, #if defined(_LIBUNWIND_TARGET_AARCH64) case REGISTERS_ARM64: { int64_t value = - results->savedRegisters[UNW_ARM64_RA_SIGN_STATE].value ^ 0x1; - results->setRegisterValue(UNW_ARM64_RA_SIGN_STATE, value, + results->savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value ^ 0x1; + results->setRegisterValue(UNW_AARCH64_RA_SIGN_STATE, value, initialState); _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n"); } break; diff --git a/libunwind/src/EHHeaderParser.hpp b/libunwind/src/EHHeaderParser.hpp index f97cca54825f..9a38070faba9 100644 --- a/libunwind/src/EHHeaderParser.hpp +++ b/libunwind/src/EHHeaderParser.hpp @@ -1,4 +1,4 @@ -//===------------------------- EHHeaderParser.hpp -------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libunwind/src/RWMutex.hpp b/libunwind/src/RWMutex.hpp index fcd3f4967d17..344d35641f07 100644 --- a/libunwind/src/RWMutex.hpp +++ b/libunwind/src/RWMutex.hpp @@ -1,4 +1,4 @@ -//===----------------------------- Registers.hpp --------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libunwind/src/Registers.hpp b/libunwind/src/Registers.hpp index aea84cc22721..c2d5327eade3 100644 --- a/libunwind/src/Registers.hpp +++ b/libunwind/src/Registers.hpp @@ -1,4 +1,4 @@ -//===----------------------------- Registers.hpp --------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -15,8 +15,9 @@ #include <stdint.h> #include <string.h> -#include "libunwind.h" +#include "cet_unwind.h" #include "config.h" +#include "libunwind.h" namespace libunwind { @@ -42,6 +43,13 @@ enum { #if defined(_LIBUNWIND_TARGET_I386) class _LIBUNWIND_HIDDEN Registers_x86; extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *); + +#if defined(_LIBUNWIND_USE_CET) +extern "C" void *__libunwind_cet_get_jump_target() { + return reinterpret_cast<void *>(&__libunwind_Registers_x86_jumpto); +} +#endif + /// Registers_x86 holds the register state of a thread in a 32-bit intel /// process. class _LIBUNWIND_HIDDEN Registers_x86 { @@ -253,6 +261,13 @@ inline void Registers_x86::setVectorRegister(int, v128) { /// process. class _LIBUNWIND_HIDDEN Registers_x86_64; extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *); + +#if defined(_LIBUNWIND_USE_CET) +extern "C" void *__libunwind_cet_get_jump_target() { + return reinterpret_cast<void *>(&__libunwind_Registers_x86_64_jumpto); +} +#endif + class _LIBUNWIND_HIDDEN Registers_x86_64 { public: Registers_x86_64(); @@ -339,7 +354,7 @@ inline bool Registers_x86_64::validRegister(int regNum) const { return true; if (regNum < 0) return false; - if (regNum > 15) + if (regNum > 16) return false; return true; } @@ -347,6 +362,7 @@ inline bool Registers_x86_64::validRegister(int regNum) const { inline uint64_t Registers_x86_64::getRegister(int regNum) const { switch (regNum) { case UNW_REG_IP: + case UNW_X86_64_RIP: return _registers.__rip; case UNW_REG_SP: return _registers.__rsp; @@ -389,6 +405,7 @@ inline uint64_t Registers_x86_64::getRegister(int regNum) const { inline void Registers_x86_64::setRegister(int regNum, uint64_t value) { switch (regNum) { case UNW_REG_IP: + case UNW_X86_64_RIP: _registers.__rip = value; return; case UNW_REG_SP: @@ -449,6 +466,7 @@ inline void Registers_x86_64::setRegister(int regNum, uint64_t value) { inline const char *Registers_x86_64::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: + case UNW_X86_64_RIP: return "rip"; case UNW_REG_SP: return "rsp"; @@ -1847,7 +1865,7 @@ inline bool Registers_arm64::validRegister(int regNum) const { return false; if (regNum > 95) return false; - if (regNum == UNW_ARM64_RA_SIGN_STATE) + if (regNum == UNW_AARCH64_RA_SIGN_STATE) return true; if ((regNum > 32) && (regNum < 64)) return false; @@ -1855,15 +1873,15 @@ inline bool Registers_arm64::validRegister(int regNum) const { } inline uint64_t Registers_arm64::getRegister(int regNum) const { - if (regNum == UNW_REG_IP || regNum == UNW_ARM64_PC) + if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC) return _registers.__pc; - if (regNum == UNW_REG_SP || regNum == UNW_ARM64_SP) + if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP) return _registers.__sp; - if (regNum == UNW_ARM64_RA_SIGN_STATE) + if (regNum == UNW_AARCH64_RA_SIGN_STATE) return _registers.__ra_sign_state; - if (regNum == UNW_ARM64_FP) + if (regNum == UNW_AARCH64_FP) return _registers.__fp; - if (regNum == UNW_ARM64_LR) + if (regNum == UNW_AARCH64_LR) return _registers.__lr; if ((regNum >= 0) && (regNum < 29)) return _registers.__x[regNum]; @@ -1871,15 +1889,15 @@ inline uint64_t Registers_arm64::getRegister(int regNum) const { } inline void Registers_arm64::setRegister(int regNum, uint64_t value) { - if (regNum == UNW_REG_IP || regNum == UNW_ARM64_PC) + if (regNum == UNW_REG_IP || regNum == UNW_AARCH64_PC) _registers.__pc = value; - else if (regNum == UNW_REG_SP || regNum == UNW_ARM64_SP) + else if (regNum == UNW_REG_SP || regNum == UNW_AARCH64_SP) _registers.__sp = value; - else if (regNum == UNW_ARM64_RA_SIGN_STATE) + else if (regNum == UNW_AARCH64_RA_SIGN_STATE) _registers.__ra_sign_state = value; - else if (regNum == UNW_ARM64_FP) + else if (regNum == UNW_AARCH64_FP) _registers.__fp = value; - else if (regNum == UNW_ARM64_LR) + else if (regNum == UNW_AARCH64_LR) _registers.__lr = value; else if ((regNum >= 0) && (regNum < 29)) _registers.__x[regNum] = value; @@ -1893,135 +1911,135 @@ inline const char *Registers_arm64::getRegisterName(int regNum) { return "pc"; case UNW_REG_SP: return "sp"; - case UNW_ARM64_X0: + case UNW_AARCH64_X0: return "x0"; - case UNW_ARM64_X1: + case UNW_AARCH64_X1: return "x1"; - case UNW_ARM64_X2: + case UNW_AARCH64_X2: return "x2"; - case UNW_ARM64_X3: + case UNW_AARCH64_X3: return "x3"; - case UNW_ARM64_X4: + case UNW_AARCH64_X4: return "x4"; - case UNW_ARM64_X5: + case UNW_AARCH64_X5: return "x5"; - case UNW_ARM64_X6: + case UNW_AARCH64_X6: return "x6"; - case UNW_ARM64_X7: + case UNW_AARCH64_X7: return "x7"; - case UNW_ARM64_X8: + case UNW_AARCH64_X8: return "x8"; - case UNW_ARM64_X9: + case UNW_AARCH64_X9: return "x9"; - case UNW_ARM64_X10: + case UNW_AARCH64_X10: return "x10"; - case UNW_ARM64_X11: + case UNW_AARCH64_X11: return "x11"; - case UNW_ARM64_X12: + case UNW_AARCH64_X12: return "x12"; - case UNW_ARM64_X13: + case UNW_AARCH64_X13: return "x13"; - case UNW_ARM64_X14: + case UNW_AARCH64_X14: return "x14"; - case UNW_ARM64_X15: + case UNW_AARCH64_X15: return "x15"; - case UNW_ARM64_X16: + case UNW_AARCH64_X16: return "x16"; - case UNW_ARM64_X17: + case UNW_AARCH64_X17: return "x17"; - case UNW_ARM64_X18: + case UNW_AARCH64_X18: return "x18"; - case UNW_ARM64_X19: + case UNW_AARCH64_X19: return "x19"; - case UNW_ARM64_X20: + case UNW_AARCH64_X20: return "x20"; - case UNW_ARM64_X21: + case UNW_AARCH64_X21: return "x21"; - case UNW_ARM64_X22: + case UNW_AARCH64_X22: return "x22"; - case UNW_ARM64_X23: + case UNW_AARCH64_X23: return "x23"; - case UNW_ARM64_X24: + case UNW_AARCH64_X24: return "x24"; - case UNW_ARM64_X25: + case UNW_AARCH64_X25: return "x25"; - case UNW_ARM64_X26: + case UNW_AARCH64_X26: return "x26"; - case UNW_ARM64_X27: + case UNW_AARCH64_X27: return "x27"; - case UNW_ARM64_X28: + case UNW_AARCH64_X28: return "x28"; - case UNW_ARM64_FP: + case UNW_AARCH64_FP: return "fp"; - case UNW_ARM64_LR: + case UNW_AARCH64_LR: return "lr"; - case UNW_ARM64_SP: + case UNW_AARCH64_SP: return "sp"; - case UNW_ARM64_PC: + case UNW_AARCH64_PC: return "pc"; - case UNW_ARM64_D0: + case UNW_AARCH64_V0: return "d0"; - case UNW_ARM64_D1: + case UNW_AARCH64_V1: return "d1"; - case UNW_ARM64_D2: + case UNW_AARCH64_V2: return "d2"; - case UNW_ARM64_D3: + case UNW_AARCH64_V3: return "d3"; - case UNW_ARM64_D4: + case UNW_AARCH64_V4: return "d4"; - case UNW_ARM64_D5: + case UNW_AARCH64_V5: return "d5"; - case UNW_ARM64_D6: + case UNW_AARCH64_V6: return "d6"; - case UNW_ARM64_D7: + case UNW_AARCH64_V7: return "d7"; - case UNW_ARM64_D8: + case UNW_AARCH64_V8: return "d8"; - case UNW_ARM64_D9: + case UNW_AARCH64_V9: return "d9"; - case UNW_ARM64_D10: + case UNW_AARCH64_V10: return "d10"; - case UNW_ARM64_D11: + case UNW_AARCH64_V11: return "d11"; - case UNW_ARM64_D12: + case UNW_AARCH64_V12: return "d12"; - case UNW_ARM64_D13: + case UNW_AARCH64_V13: return "d13"; - case UNW_ARM64_D14: + case UNW_AARCH64_V14: return "d14"; - case UNW_ARM64_D15: + case UNW_AARCH64_V15: return "d15"; - case UNW_ARM64_D16: + case UNW_AARCH64_V16: return "d16"; - case UNW_ARM64_D17: + case UNW_AARCH64_V17: return "d17"; - case UNW_ARM64_D18: + case UNW_AARCH64_V18: return "d18"; - case UNW_ARM64_D19: + case UNW_AARCH64_V19: return "d19"; - case UNW_ARM64_D20: + case UNW_AARCH64_V20: return "d20"; - case UNW_ARM64_D21: + case UNW_AARCH64_V21: return "d21"; - case UNW_ARM64_D22: + case UNW_AARCH64_V22: return "d22"; - case UNW_ARM64_D23: + case UNW_AARCH64_V23: return "d23"; - case UNW_ARM64_D24: + case UNW_AARCH64_V24: return "d24"; - case UNW_ARM64_D25: + case UNW_AARCH64_V25: return "d25"; - case UNW_ARM64_D26: + case UNW_AARCH64_V26: return "d26"; - case UNW_ARM64_D27: + case UNW_AARCH64_V27: return "d27"; - case UNW_ARM64_D28: + case UNW_AARCH64_V28: return "d28"; - case UNW_ARM64_D29: + case UNW_AARCH64_V29: return "d29"; - case UNW_ARM64_D30: + case UNW_AARCH64_V30: return "d30"; - case UNW_ARM64_D31: + case UNW_AARCH64_V31: return "d31"; default: return "unknown register"; @@ -2029,21 +2047,21 @@ inline const char *Registers_arm64::getRegisterName(int regNum) { } inline bool Registers_arm64::validFloatRegister(int regNum) const { - if (regNum < UNW_ARM64_D0) + if (regNum < UNW_AARCH64_V0) return false; - if (regNum > UNW_ARM64_D31) + if (regNum > UNW_AARCH64_V31) return false; return true; } inline double Registers_arm64::getFloatRegister(int regNum) const { assert(validFloatRegister(regNum)); - return _vectorHalfRegisters[regNum - UNW_ARM64_D0]; + return _vectorHalfRegisters[regNum - UNW_AARCH64_V0]; } inline void Registers_arm64::setFloatRegister(int regNum, double value) { assert(validFloatRegister(regNum)); - _vectorHalfRegisters[regNum - UNW_ARM64_D0] = value; + _vectorHalfRegisters[regNum - UNW_AARCH64_V0] = value; } inline bool Registers_arm64::validVectorRegister(int) const { diff --git a/libunwind/src/Unwind-EHABI.cpp b/libunwind/src/Unwind-EHABI.cpp index 32b5cbc3be92..d3577c9f7cf8 100644 --- a/libunwind/src/Unwind-EHABI.cpp +++ b/libunwind/src/Unwind-EHABI.cpp @@ -1,4 +1,4 @@ -//===--------------------------- Unwind-EHABI.cpp -------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -97,9 +97,11 @@ _Unwind_Reason_Code ProcessDescriptors( case Descriptor::LU32: descriptor = getNextWord(descriptor, &length); descriptor = getNextWord(descriptor, &offset); + break; case Descriptor::LU16: descriptor = getNextNibble(descriptor, &length); descriptor = getNextNibble(descriptor, &offset); + break; default: assert(false); return _URC_FAILURE; @@ -461,6 +463,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except return _URC_FATAL_PHASE1_ERROR; } +#ifndef NDEBUG // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { char functionBuf[512]; @@ -479,6 +482,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler); } +#endif // If there is a personality routine, ask it if it will want to stop at // this frame. @@ -580,6 +584,7 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor return _URC_FATAL_PHASE2_ERROR; } +#ifndef NDEBUG // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { char functionBuf[512]; @@ -596,11 +601,12 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor functionName, sp, frameInfo.lsda, frameInfo.handler); } +#endif // If there is a personality routine, tell it we are unwinding. if (frameInfo.handler != 0) { _Unwind_Personality_Fn p = - (_Unwind_Personality_Fn)(long)(frameInfo.handler); + (_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler); struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor); // EHABI #7.2 exception_object->pr_cache.fnstart = frameInfo.start_ip; @@ -668,6 +674,114 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor return _URC_FATAL_PHASE2_ERROR; } +static _Unwind_Reason_Code +unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, + _Unwind_Exception *exception_object, _Unwind_Stop_Fn stop, + void *stop_parameter) { + // See comment at the start of unwind_phase1 regarding VRS integrity. + __unw_init_local(cursor, uc); + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_force(ex_ojb=%p)", + static_cast<void *>(exception_object)); + // Walk each frame until we reach where search phase said to stop + while (true) { + // 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 " + "failed => _URC_END_OF_STACK", + (void *)exception_object); + return _URC_FATAL_PHASE2_ERROR; + } + +#ifndef NDEBUG + // When tracing, print state information. + if (_LIBUNWIND_TRACING_UNWINDING) { + char functionBuf[512]; + const char *functionName = functionBuf; + unw_word_t offset; + if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf), + &offset) != UNW_ESUCCESS) || + (frameInfo.start_ip + offset > frameInfo.end_ip)) + functionName = ".anonymous."; + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIxPTR + ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR, + (void *)exception_object, frameInfo.start_ip, functionName, + frameInfo.lsda, frameInfo.handler); + } +#endif + + // Call stop function at each frame. + _Unwind_Action action = + (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE); + _Unwind_Reason_Code stopResult = + (*stop)(1, action, exception_object->exception_class, exception_object, + (_Unwind_Context *)(cursor), stop_parameter); + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2_forced(ex_ojb=%p): stop function returned %d", + (void *)exception_object, stopResult); + if (stopResult != _URC_NO_REASON) { + _LIBUNWIND_TRACE_UNWINDING( + "unwind_phase2_forced(ex_ojb=%p): stopped by stop function", + (void *)exception_object); + return _URC_FATAL_PHASE2_ERROR; + } + + // If there is a personality routine, tell it we are unwinding. + if (frameInfo.handler != 0) { + _Unwind_Personality_Fn p = + (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler); + struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor); + // EHABI #7.2 + exception_object->pr_cache.fnstart = frameInfo.start_ip; + exception_object->pr_cache.ehtp = + (_Unwind_EHT_Header *)frameInfo.unwind_info; + exception_object->pr_cache.additional = frameInfo.flags; + _Unwind_Reason_Code personalityResult = + (*p)(_US_FORCE_UNWIND | _US_UNWIND_FRAME_STARTING, exception_object, + context); + switch (personalityResult) { + case _URC_CONTINUE_UNWIND: + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "personality returned " + "_URC_CONTINUE_UNWIND", + (void *)exception_object); + // Destructors called, continue unwinding + break; + case _URC_INSTALL_CONTEXT: + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "personality returned " + "_URC_INSTALL_CONTEXT", + (void *)exception_object); + // We may get control back if landing pad calls _Unwind_Resume(). + __unw_resume(cursor); + break; + default: + // Personality routine returned an unknown result code. + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " + "personality returned %d, " + "_URC_FATAL_PHASE2_ERROR", + (void *)exception_object, personalityResult); + return _URC_FATAL_PHASE2_ERROR; + } + } + } + + // Call stop function one last time and tell it we've reached the end + // of the stack. + _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop " + "function with _UA_END_OF_STACK", + (void *)exception_object); + _Unwind_Action lastAction = + (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK); + (*stop)(1, lastAction, exception_object->exception_class, exception_object, + (struct _Unwind_Context *)(cursor), stop_parameter); + + // Clean up phase did not resume at the frame that the search phase said it + // would. + return _URC_FATAL_PHASE2_ERROR; +} + /// Called by __cxa_throw. Only returns if there is a fatal error. _LIBUNWIND_EXPORT _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Exception *exception_object) { @@ -715,10 +829,13 @@ _Unwind_Resume(_Unwind_Exception *exception_object) { unw_cursor_t cursor; __unw_getcontext(&uc); - // _Unwind_RaiseException on EHABI will always set the reserved1 field to 0, - // which is in the same position as private_1 below. - // TODO(ajwong): Who wronte the above? Why is it true? - unwind_phase2(&uc, &cursor, exception_object, true); + if (exception_object->unwinder_cache.reserved1) + unwind_phase2_forced( + &uc, &cursor, exception_object, + (_Unwind_Stop_Fn)exception_object->unwinder_cache.reserved1, + (void *)exception_object->unwinder_cache.reserved3); + else + unwind_phase2(&uc, &cursor, exception_object, true); // Clients assume _Unwind_Resume() does not return, so all we can do is abort. _LIBUNWIND_ABORT("_Unwind_Resume() can't return"); @@ -965,6 +1082,27 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, _LIBUNWIND_ABORT("unsupported register class"); } +/// Not used by C++. +/// Unwinds stack, calling "stop" function at each frame. +/// Could be used to implement longjmp(). +_LIBUNWIND_EXPORT _Unwind_Reason_Code +_Unwind_ForcedUnwind(_Unwind_Exception *exception_object, _Unwind_Stop_Fn stop, + void *stop_parameter) { + _LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)", + (void *)exception_object, (void *)(uintptr_t)stop); + unw_context_t uc; + unw_cursor_t cursor; + __unw_getcontext(&uc); + + // Mark that this is a forced unwind, so _Unwind_Resume() can do + // the right thing. + exception_object->unwinder_cache.reserved1 = (uintptr_t)stop; + exception_object->unwinder_cache.reserved3 = (uintptr_t)stop_parameter; + + return unwind_phase2_forced(&uc, &cursor, exception_object, stop, + stop_parameter); +} + /// Called by personality handler during phase 2 to find the start of the /// function. _LIBUNWIND_EXPORT uintptr_t diff --git a/libunwind/src/Unwind-EHABI.h b/libunwind/src/Unwind-EHABI.h index 6897082a337f..ff3b5fc6fea7 100644 --- a/libunwind/src/Unwind-EHABI.h +++ b/libunwind/src/Unwind-EHABI.h @@ -1,4 +1,4 @@ -//===------------------------- Unwind-EHABI.hpp ---------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libunwind/src/Unwind-seh.cpp b/libunwind/src/Unwind-seh.cpp index 6e2b4e73e41e..f00bc4721ba4 100644 --- a/libunwind/src/Unwind-seh.cpp +++ b/libunwind/src/Unwind-seh.cpp @@ -1,4 +1,4 @@ -//===--------------------------- Unwind-seh.cpp ---------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -169,8 +169,8 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, __unw_get_reg(&cursor, UNW_ARM_R1, &exc->private_[3]); #elif defined(__aarch64__) exc->private_[2] = disp->TargetPc; - __unw_get_reg(&cursor, UNW_ARM64_X0, &retval); - __unw_get_reg(&cursor, UNW_ARM64_X1, &exc->private_[3]); + __unw_get_reg(&cursor, UNW_AARCH64_X0, &retval); + __unw_get_reg(&cursor, UNW_AARCH64_X1, &exc->private_[3]); #endif __unw_get_reg(&cursor, UNW_REG_IP, &target); ms_exc->ExceptionCode = STATUS_GCC_UNWIND; @@ -244,6 +244,7 @@ unwind_phase2_forced(unw_context_t *uc, return _URC_FATAL_PHASE2_ERROR; } +#ifndef NDEBUG // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { char functionBuf[512]; @@ -259,6 +260,7 @@ unwind_phase2_forced(unw_context_t *uc, (void *)exception_object, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler); } +#endif // Call stop function at each frame. _Unwind_Action action = diff --git a/libunwind/src/Unwind-sjlj.c b/libunwind/src/Unwind-sjlj.c index fd2a95b74c44..d487995bb78e 100644 --- a/libunwind/src/Unwind-sjlj.c +++ b/libunwind/src/Unwind-sjlj.c @@ -1,4 +1,4 @@ -//===--------------------------- Unwind-sjlj.c ----------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp index 757d9808a978..3931df0b3351 100644 --- a/libunwind/src/UnwindCursor.hpp +++ b/libunwind/src/UnwindCursor.hpp @@ -1,4 +1,4 @@ -//===------------------------- UnwindCursor.hpp ---------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -11,6 +11,7 @@ #ifndef __UNWINDCURSOR_HPP__ #define __UNWINDCURSOR_HPP__ +#include "cet_unwind.h" #include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -449,6 +450,12 @@ public: #ifdef __arm__ virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); } #endif + +#if defined(_LIBUNWIND_USE_CET) + virtual void *get_registers() { + _LIBUNWIND_ABORT("get_registers not implemented"); + } +#endif }; #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32) @@ -620,12 +627,12 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as) _msContext.D[i - UNW_ARM_D0] = d.w; } #elif defined(_LIBUNWIND_TARGET_AARCH64) - for (int i = UNW_ARM64_X0; i <= UNW_ARM64_X30; ++i) - _msContext.X[i - UNW_ARM64_X0] = r.getRegister(i); + for (int i = UNW_AARCH64_X0; i <= UNW_ARM64_X30; ++i) + _msContext.X[i - UNW_AARCH64_X0] = r.getRegister(i); _msContext.Sp = r.getRegister(UNW_REG_SP); _msContext.Pc = r.getRegister(UNW_REG_IP); - for (int i = UNW_ARM64_D0; i <= UNW_ARM64_D31; ++i) - _msContext.V[i - UNW_ARM64_D0].D[0] = r.getFloatRegister(i); + for (int i = UNW_AARCH64_V0; i <= UNW_ARM64_D31; ++i) + _msContext.V[i - UNW_AARCH64_V0].D[0] = r.getFloatRegister(i); #endif } @@ -650,7 +657,7 @@ bool UnwindCursor<A, R>::validReg(int regNum) { #elif defined(_LIBUNWIND_TARGET_ARM) if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) return true; #elif defined(_LIBUNWIND_TARGET_AARCH64) - if (regNum >= UNW_ARM64_X0 && regNum <= UNW_ARM64_X30) return true; + if (regNum >= UNW_AARCH64_X0 && regNum <= UNW_ARM64_X30) return true; #endif return false; } @@ -699,7 +706,7 @@ unw_word_t UnwindCursor<A, R>::getReg(int regNum) { #elif defined(_LIBUNWIND_TARGET_AARCH64) case UNW_REG_SP: return _msContext.Sp; case UNW_REG_IP: return _msContext.Pc; - default: return _msContext.X[regNum - UNW_ARM64_X0]; + default: return _msContext.X[regNum - UNW_AARCH64_X0]; #endif } _LIBUNWIND_ABORT("unsupported register"); @@ -749,37 +756,37 @@ void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) { #elif defined(_LIBUNWIND_TARGET_AARCH64) case UNW_REG_SP: _msContext.Sp = value; break; case UNW_REG_IP: _msContext.Pc = value; break; - case UNW_ARM64_X0: - case UNW_ARM64_X1: - case UNW_ARM64_X2: - case UNW_ARM64_X3: - case UNW_ARM64_X4: - case UNW_ARM64_X5: - case UNW_ARM64_X6: - case UNW_ARM64_X7: - case UNW_ARM64_X8: - case UNW_ARM64_X9: - case UNW_ARM64_X10: - case UNW_ARM64_X11: - case UNW_ARM64_X12: - case UNW_ARM64_X13: - case UNW_ARM64_X14: - case UNW_ARM64_X15: - case UNW_ARM64_X16: - case UNW_ARM64_X17: - case UNW_ARM64_X18: - case UNW_ARM64_X19: - case UNW_ARM64_X20: - case UNW_ARM64_X21: - case UNW_ARM64_X22: - case UNW_ARM64_X23: - case UNW_ARM64_X24: - case UNW_ARM64_X25: - case UNW_ARM64_X26: - case UNW_ARM64_X27: - case UNW_ARM64_X28: - case UNW_ARM64_FP: - case UNW_ARM64_LR: _msContext.X[regNum - UNW_ARM64_X0] = value; break; + case UNW_AARCH64_X0: + case UNW_AARCH64_X1: + case UNW_AARCH64_X2: + case UNW_AARCH64_X3: + case UNW_AARCH64_X4: + case UNW_AARCH64_X5: + case UNW_AARCH64_X6: + case UNW_AARCH64_X7: + case UNW_AARCH64_X8: + case UNW_AARCH64_X9: + case UNW_AARCH64_X10: + case UNW_AARCH64_X11: + case UNW_AARCH64_X12: + case UNW_AARCH64_X13: + case UNW_AARCH64_X14: + case UNW_AARCH64_X15: + case UNW_AARCH64_X16: + case UNW_AARCH64_X17: + case UNW_AARCH64_X18: + case UNW_AARCH64_X19: + case UNW_AARCH64_X20: + case UNW_AARCH64_X21: + case UNW_AARCH64_X22: + case UNW_AARCH64_X23: + case UNW_AARCH64_X24: + case UNW_AARCH64_X25: + case UNW_AARCH64_X26: + case UNW_AARCH64_X27: + case UNW_AARCH64_X28: + case UNW_AARCH64_FP: + case UNW_AARCH64_LR: _msContext.X[regNum - UNW_ARM64_X0] = value; break; #endif default: _LIBUNWIND_ABORT("unsupported register"); @@ -792,7 +799,7 @@ bool UnwindCursor<A, R>::validFloatReg(int regNum) { if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) return true; if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) return true; #elif defined(_LIBUNWIND_TARGET_AARCH64) - if (regNum >= UNW_ARM64_D0 && regNum <= UNW_ARM64_D31) return true; + if (regNum >= UNW_AARCH64_V0 && regNum <= UNW_ARM64_D31) return true; #else (void)regNum; #endif @@ -820,7 +827,7 @@ unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) { } _LIBUNWIND_ABORT("unsupported float register"); #elif defined(_LIBUNWIND_TARGET_AARCH64) - return _msContext.V[regNum - UNW_ARM64_D0].D[0]; + return _msContext.V[regNum - UNW_AARCH64_V0].D[0]; #else (void)regNum; _LIBUNWIND_ABORT("float registers unimplemented"); @@ -848,7 +855,7 @@ void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) { } _LIBUNWIND_ABORT("unsupported float register"); #elif defined(_LIBUNWIND_TARGET_AARCH64) - _msContext.V[regNum - UNW_ARM64_D0].D[0] = value; + _msContext.V[regNum - UNW_AARCH64_V0].D[0] = value; #else (void)regNum; (void)value; @@ -901,6 +908,9 @@ public: virtual void saveVFPAsX(); #endif +#if defined(_LIBUNWIND_USE_CET) + virtual void *get_registers() { return &_registers; } +#endif // libunwind does not and should not depend on C++ library which means that we // need our own defition of inline placement new. static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; } @@ -2061,7 +2071,7 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) { for (int i = 0; i <= 30; ++i) { uint64_t value = _addressSpace.get64(sigctx + kOffsetGprs + static_cast<pint_t>(i * 8)); - _registers.setRegister(UNW_ARM64_X0 + i, value); + _registers.setRegister(UNW_AARCH64_X0 + i, value); } _registers.setSP(_addressSpace.get64(sigctx + kOffsetSp)); _registers.setIP(_addressSpace.get64(sigctx + kOffsetPc)); @@ -2125,6 +2135,12 @@ bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen, buf, bufLen, offset); } +#if defined(_LIBUNWIND_USE_CET) +extern "C" void *__libunwind_cet_get_registers(unw_cursor_t *cursor) { + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + return co->get_registers(); +} +#endif } // namespace libunwind #endif // __UNWINDCURSOR_HPP__ diff --git a/libunwind/src/UnwindLevel1-gcc-ext.c b/libunwind/src/UnwindLevel1-gcc-ext.c index 310b836d129e..951d5d219a3e 100644 --- a/libunwind/src/UnwindLevel1-gcc-ext.c +++ b/libunwind/src/UnwindLevel1-gcc-ext.c @@ -1,4 +1,4 @@ -//===--------------------- UnwindLevel1-gcc-ext.c -------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -25,31 +25,24 @@ #if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS) #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) -#define private_1 private_[0] +#define PRIVATE_1 private_[0] +#elif defined(_LIBUNWIND_ARM_EHABI) +#define PRIVATE_1 unwinder_cache.reserved1 +#else +#define PRIVATE_1 private_1 #endif /// Called by __cxa_rethrow(). _LIBUNWIND_EXPORT _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) { -#if defined(_LIBUNWIND_ARM_EHABI) - _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%ld", - (void *)exception_object, - (long)exception_object->unwinder_cache.reserved1); -#else - _LIBUNWIND_TRACE_API("_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%" PRIdPTR, - (void *)exception_object, - (intptr_t)exception_object->private_1); -#endif + _LIBUNWIND_TRACE_API( + "_Unwind_Resume_or_Rethrow(ex_obj=%p), private_1=%" PRIdPTR, + (void *)exception_object, (intptr_t)exception_object->PRIVATE_1); -#if defined(_LIBUNWIND_ARM_EHABI) - // _Unwind_RaiseException on EHABI will always set the reserved1 field to 0, - // which is in the same position as private_1 below. - return _Unwind_RaiseException(exception_object); -#else // If this is non-forced and a stopping place was found, then this is a // re-throw. // Call _Unwind_RaiseException() as if this was a new exception - if (exception_object->private_1 == 0) { + if (exception_object->PRIVATE_1 == 0) { return _Unwind_RaiseException(exception_object); // Will return if there is no catch clause, so that __cxa_rethrow can call // std::terminate(). @@ -60,10 +53,8 @@ _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) { _Unwind_Resume(exception_object); _LIBUNWIND_ABORT("_Unwind_Resume_or_Rethrow() called _Unwind_RaiseException()" " which unexpectedly returned"); -#endif } - /// Called by personality handler during phase 2 to get base address for data /// relative encodings. _LIBUNWIND_EXPORT uintptr_t @@ -118,7 +109,7 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) { // Create a mock exception object for force unwinding. _Unwind_Exception ex; memset(&ex, '\0', sizeof(ex)); - ex.exception_class = 0x434C4E47554E5700; // CLNGUNW\0 + strcpy((char *)&ex.exception_class, "CLNGUNW"); #endif // walk each frame diff --git a/libunwind/src/UnwindLevel1.c b/libunwind/src/UnwindLevel1.c index 68e5e48b8c05..5c1f99d4bfa5 100644 --- a/libunwind/src/UnwindLevel1.c +++ b/libunwind/src/UnwindLevel1.c @@ -1,4 +1,4 @@ -//===------------------------- UnwindLevel1.c -----------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -25,6 +25,7 @@ #include <stdio.h> #include <string.h> +#include "cet_unwind.h" #include "config.h" #include "libunwind.h" #include "libunwind_ext.h" @@ -34,6 +35,38 @@ #ifndef _LIBUNWIND_SUPPORT_SEH_UNWIND +// When CET is enabled, each "call" instruction will push return address to +// CET shadow stack, each "ret" instruction will pop current CET shadow stack +// top and compare it with target address which program will return. +// In exception handing, some stack frames will be skipped before jumping to +// landing pad and we must adjust CET shadow stack accordingly. +// _LIBUNWIND_POP_CET_SSP is used to adjust CET shadow stack pointer and we +// directly jump to __libunwind_Registerts_x86/x86_64_jumpto instead of using +// a regular function call to avoid pushing to CET shadow stack again. +#if !defined(_LIBUNWIND_USE_CET) +#define __unw_phase2_resume(cursor, fn) __unw_resume((cursor)) +#elif defined(_LIBUNWIND_TARGET_I386) +#define __unw_phase2_resume(cursor, fn) \ + do { \ + _LIBUNWIND_POP_CET_SSP((fn)); \ + void *cetRegContext = __libunwind_cet_get_registers((cursor)); \ + void *cetJumpAddress = __libunwind_cet_get_jump_target(); \ + __asm__ volatile("push %%edi\n\t" \ + "sub $4, %%esp\n\t" \ + "jmp *%%edx\n\t" :: "D"(cetRegContext), \ + "d"(cetJumpAddress)); \ + } while (0) +#elif defined(_LIBUNWIND_TARGET_X86_64) +#define __unw_phase2_resume(cursor, fn) \ + do { \ + _LIBUNWIND_POP_CET_SSP((fn)); \ + void *cetRegContext = __libunwind_cet_get_registers((cursor)); \ + void *cetJumpAddress = __libunwind_cet_get_jump_target(); \ + __asm__ volatile("jmpq *%%rdx\n\t" :: "D"(cetRegContext), \ + "d"(cetJumpAddress)); \ + } while (0) +#endif + static _Unwind_Reason_Code unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { __unw_init_local(cursor, uc); @@ -68,6 +101,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except return _URC_FATAL_PHASE1_ERROR; } +#ifndef NDEBUG // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { char functionBuf[512]; @@ -85,6 +119,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except (void *)exception_object, pc, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler); } +#endif // If there is a personality routine, ask it if it will want to stop at // this frame. @@ -135,6 +170,9 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", (void *)exception_object); + // uc is initialized by __unw_getcontext in the parent frame. The first stack + // frame walked is unwind_phase2. + unsigned framesWalked = 1; // Walk each frame until we reach where search phase said to stop. while (true) { @@ -167,6 +205,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except return _URC_FATAL_PHASE2_ERROR; } +#ifndef NDEBUG // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { char functionBuf[512]; @@ -183,7 +222,9 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except functionName, sp, frameInfo.lsda, frameInfo.handler); } +#endif + ++framesWalked; // If there is a personality routine, tell it we are unwinding. if (frameInfo.handler != 0) { _Unwind_Personality_Fn p = @@ -223,8 +264,9 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except ", sp=0x%" PRIxPTR, (void *)exception_object, pc, sp); } - __unw_resume(cursor); - // __unw_resume() only returns if there was an error. + + __unw_phase2_resume(cursor, framesWalked); + // __unw_phase2_resume() only returns if there was an error. return _URC_FATAL_PHASE2_ERROR; default: // Personality routine returned an unknown result code. @@ -246,6 +288,9 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Stop_Fn stop, void *stop_parameter) { __unw_init_local(cursor, uc); + // uc is initialized by __unw_getcontext in the parent frame. The first stack + // frame walked is unwind_phase2_forced. + unsigned framesWalked = 1; // Walk each frame until we reach where search phase said to stop while (__unw_step(cursor) > 0) { @@ -258,6 +303,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, return _URC_FATAL_PHASE2_ERROR; } +#ifndef NDEBUG // When tracing, print state information. if (_LIBUNWIND_TRACING_UNWINDING) { char functionBuf[512]; @@ -273,6 +319,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, (void *)exception_object, frameInfo.start_ip, functionName, frameInfo.lsda, frameInfo.handler); } +#endif // Call stop function at each frame. _Unwind_Action action = @@ -290,6 +337,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, return _URC_FATAL_PHASE2_ERROR; } + ++framesWalked; // If there is a personality routine, tell it we are unwinding. if (frameInfo.handler != 0) { _Unwind_Personality_Fn p = @@ -314,7 +362,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, "_URC_INSTALL_CONTEXT", (void *)exception_object); // We may get control back if landing pad calls _Unwind_Resume(). - __unw_resume(cursor); + __unw_phase2_resume(cursor, framesWalked); break; default: // Personality routine returned an unknown result code. diff --git a/libunwind/src/UnwindRegistersRestore.S b/libunwind/src/UnwindRegistersRestore.S index d8bf1adee416..497bf46dbdd4 100644 --- a/libunwind/src/UnwindRegistersRestore.S +++ b/libunwind/src/UnwindRegistersRestore.S @@ -1,4 +1,4 @@ -//===-------------------- UnwindRegistersRestore.S ------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -25,6 +25,8 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto) # + return address + # +-----------------------+ <-- SP # + + + + _LIBUNWIND_CET_ENDBR movl 4(%esp), %eax # set up eax and ret on new stack location movl 28(%eax), %edx # edx holds new stack pointer @@ -46,7 +48,8 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto) # skip ss # skip eflags pop %eax # eax was already pushed on new stack - ret # eip was already pushed on new stack + pop %ecx + jmp *%ecx # skip cs # skip ds # skip es @@ -70,6 +73,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto) # On entry, thread_state pointer is in rdi #endif + _LIBUNWIND_CET_ENDBR movq 56(%rdi), %rax # rax holds new stack pointer subq $16, %rax movq %rax, 56(%rdi) @@ -119,7 +123,8 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto) #endif movq 56(%rdi), %rsp # cut back rsp to new location pop %rdi # rdi was saved here earlier - ret # rip was saved here + pop %rcx + jmpq *%rcx #elif defined(__powerpc64__) @@ -800,11 +805,12 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv) l.lwz r30,120(r3) l.lwz r31,124(r3) + # load new pc into ra + l.lwz r9, 128(r3) + # at last, restore r3 l.lwz r3, 12(r3) - # load new pc into ra - l.lwz r9, 128(r3) # jump to pc l.jr r9 l.nop diff --git a/libunwind/src/UnwindRegistersSave.S b/libunwind/src/UnwindRegistersSave.S index f66dc532c23c..e77012e5c613 100644 --- a/libunwind/src/UnwindRegistersSave.S +++ b/libunwind/src/UnwindRegistersSave.S @@ -1,4 +1,4 @@ -//===------------------------ UnwindRegistersSave.S -----------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -27,6 +27,8 @@ # + + # DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) + + _LIBUNWIND_CET_ENDBR push %eax movl 8(%esp), %eax movl %ebx, 4(%eax) @@ -70,6 +72,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) #define TMP %rsi #endif + _LIBUNWIND_CET_ENDBR movq %rax, (PTR) movq %rbx, 8(PTR) movq %rcx, 16(PTR) diff --git a/libunwind/src/Unwind_AppleExtras.cpp b/libunwind/src/Unwind_AppleExtras.cpp index e3d41ca2b4e9..ffb49a89e54f 100644 --- a/libunwind/src/Unwind_AppleExtras.cpp +++ b/libunwind/src/Unwind_AppleExtras.cpp @@ -1,4 +1,4 @@ -//===--------------------- Unwind_AppleExtras.cpp -------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libunwind/src/assembly.h b/libunwind/src/assembly.h index 76ef82553283..e38d32336929 100644 --- a/libunwind/src/assembly.h +++ b/libunwind/src/assembly.h @@ -15,6 +15,13 @@ #ifndef UNWIND_ASSEMBLY_H #define UNWIND_ASSEMBLY_H +#if (defined(__i386__) || defined(__x86_64__)) && defined(__linux__) +#include <cet.h> +#define _LIBUNWIND_CET_ENDBR _CET_ENDBR +#else +#define _LIBUNWIND_CET_ENDBR +#endif + #if defined(__powerpc64__) #define SEPARATOR ; #define PPC64_OFFS_SRR0 0 diff --git a/libunwind/src/cet_unwind.h b/libunwind/src/cet_unwind.h new file mode 100644 index 000000000000..e371be20c452 --- /dev/null +++ b/libunwind/src/cet_unwind.h @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +// +//===----------------------------------------------------------------------===// + +#ifndef LIBUNWIND_CET_UNWIND_H +#define LIBUNWIND_CET_UNWIND_H + +#include "libunwind.h" + +// Currently, CET is implemented on Linux x86 platforms. +#if defined(_LIBUNWIND_TARGET_LINUX) && defined(__CET__) && defined(__SHSTK__) +#define _LIBUNWIND_USE_CET 1 +#endif + +#if defined(_LIBUNWIND_USE_CET) +#include <cet.h> +#include <immintrin.h> + +#define _LIBUNWIND_POP_CET_SSP(x) \ + do { \ + unsigned long ssp = _get_ssp(); \ + if (ssp != 0) { \ + unsigned int tmp = (x); \ + while (tmp > 255) { \ + _inc_ssp(255); \ + tmp -= 255; \ + } \ + _inc_ssp(tmp); \ + } \ + } while (0) +#endif + +extern void *__libunwind_cet_get_registers(unw_cursor_t *); +extern void *__libunwind_cet_get_jump_target(); + +#endif diff --git a/libunwind/src/config.h b/libunwind/src/config.h index 2ab9d2f5e0c9..f469d3c232e6 100644 --- a/libunwind/src/config.h +++ b/libunwind/src/config.h @@ -1,4 +1,4 @@ -//===----------------------------- config.h -------------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libunwind/src/dwarf2.h b/libunwind/src/dwarf2.h index 40f0daf46805..174277d5a795 100644 --- a/libunwind/src/dwarf2.h +++ b/libunwind/src/dwarf2.h @@ -1,4 +1,4 @@ -//===------------------------------- dwarf2.h -----------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libunwind/src/libunwind.cpp b/libunwind/src/libunwind.cpp index 1faf000ce44a..48750ce670fb 100644 --- a/libunwind/src/libunwind.cpp +++ b/libunwind/src/libunwind.cpp @@ -1,4 +1,4 @@ -//===--------------------------- libunwind.cpp ----------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -11,8 +11,8 @@ #include <libunwind.h> -#include "libunwind_ext.h" #include "config.h" +#include "libunwind_ext.h" #include <stdlib.h> @@ -292,6 +292,35 @@ void __unw_remove_dynamic_fde(unw_word_t fde) { // fde is own mh_group DwarfFDECache<LocalAddressSpace>::removeAllIn((LocalAddressSpace::pint_t)fde); } + +void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start) { + // The eh_frame section start serves as the mh_group + unw_word_t mh_group = eh_frame_start; + CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo; + CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo; + auto p = (LocalAddressSpace::pint_t)eh_frame_start; + while (true) { + if (CFI_Parser<LocalAddressSpace>::decodeFDE( + LocalAddressSpace::sThisAddressSpace, p, &fdeInfo, &cieInfo, + true) == NULL) { + DwarfFDECache<LocalAddressSpace>::add((LocalAddressSpace::pint_t)mh_group, + fdeInfo.pcStart, fdeInfo.pcEnd, + fdeInfo.fdeStart); + p += fdeInfo.fdeLength; + } else if (CFI_Parser<LocalAddressSpace>::parseCIE( + LocalAddressSpace::sThisAddressSpace, p, &cieInfo) == NULL) { + p += cieInfo.cieLength; + } else + return; + } +} + +void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) { + // The eh_frame section start serves as the mh_group + DwarfFDECache<LocalAddressSpace>::removeAllIn( + (LocalAddressSpace::pint_t)eh_frame_start); +} + #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) #endif // !defined(__USING_SJLJ_EXCEPTIONS__) diff --git a/libunwind/src/libunwind_ext.h b/libunwind/src/libunwind_ext.h index 316dee298246..7065ffcdaeff 100644 --- a/libunwind/src/libunwind_ext.h +++ b/libunwind/src/libunwind_ext.h @@ -1,4 +1,4 @@ -//===------------------------ libunwind_ext.h -----------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -51,6 +51,9 @@ extern void __unw_iterate_dwarf_unwind_cache(void (*func)( extern void __unw_add_dynamic_fde(unw_word_t fde); 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); + #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, |