diff --git a/src/coreclr/nativeaot/libunwind/CMakeLists.txt b/src/coreclr/nativeaot/libunwind/CMakeLists.txt index 836b286523ef1..b51922a48fe28 100644 --- a/src/coreclr/nativeaot/libunwind/CMakeLists.txt +++ b/src/coreclr/nativeaot/libunwind/CMakeLists.txt @@ -83,7 +83,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBUNWIND_STANDALONE_B endif() set(PACKAGE_NAME libunwind) - set(PACKAGE_VERSION 9.0.0) + set(PACKAGE_VERSION 9.0.0svn) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") diff --git a/src/coreclr/nativeaot/libunwind/include/__libunwind_config.h b/src/coreclr/nativeaot/libunwind/include/__libunwind_config.h index 6e7e5e6f7f86b..753085c7fe0c0 100644 --- a/src/coreclr/nativeaot/libunwind/include/__libunwind_config.h +++ b/src/coreclr/nativeaot/libunwind/include/__libunwind_config.h @@ -27,8 +27,8 @@ #if defined(_LIBUNWIND_IS_NATIVE_ONLY) # if defined(__i386__) # define _LIBUNWIND_TARGET_I386 -# define _LIBUNWIND_CONTEXT_SIZE 8 -# define _LIBUNWIND_CURSOR_SIZE 15 +# define _LIBUNWIND_CONTEXT_SIZE 13 +# define _LIBUNWIND_CURSOR_SIZE 19 # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86 # elif defined(__x86_64__) # define _LIBUNWIND_TARGET_X86_64 1 @@ -40,8 +40,8 @@ # define _LIBUNWIND_CURSOR_SIZE 66 # endif # else -# define _LIBUNWIND_CONTEXT_SIZE 21 -# define _LIBUNWIND_CURSOR_SIZE 33 +# define _LIBUNWIND_CONTEXT_SIZE 38 +# define _LIBUNWIND_CURSOR_SIZE 50 # endif # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64 # elif defined(__powerpc64__) @@ -56,11 +56,11 @@ # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC # elif defined(__aarch64__) # define _LIBUNWIND_TARGET_AARCH64 1 -# define _LIBUNWIND_CONTEXT_SIZE 66 +# define _LIBUNWIND_CONTEXT_SIZE 100 # if defined(__SEH__) -# define _LIBUNWIND_CURSOR_SIZE 164 +# define _LIBUNWIND_CURSOR_SIZE 198 # else -# define _LIBUNWIND_CURSOR_SIZE 78 +# define _LIBUNWIND_CURSOR_SIZE 112 # endif # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64 # elif defined(__arm__) @@ -72,8 +72,8 @@ # define _LIBUNWIND_CONTEXT_SIZE 61 # define _LIBUNWIND_CURSOR_SIZE 68 # else -# define _LIBUNWIND_CONTEXT_SIZE 42 -# define _LIBUNWIND_CURSOR_SIZE 49 +# define _LIBUNWIND_CONTEXT_SIZE 50 +# define _LIBUNWIND_CURSOR_SIZE 57 # endif # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM # elif defined(__or1k__) @@ -118,7 +118,12 @@ #define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC #define _LIBUNWIND_CONTEXT_SIZE 16 #define _LIBUNWIND_CURSOR_SIZE 23 -# else +#elif defined(HOST_WASM) +#define _LIBUNWIND_TARGET_WASM 1 +// TODO: Determine the right values +#define _LIBUNWIND_CONTEXT_SIZE 0xbadf00d +#define _LIBUNWIND_CURSOR_SIZE 0xbadf00d +#else # error "Unsupported architecture." # endif #else // !_LIBUNWIND_IS_NATIVE_ONLY diff --git a/src/coreclr/nativeaot/libunwind/include/libunwind.h b/src/coreclr/nativeaot/libunwind/include/libunwind.h index d06724d3c31fe..6e70f264f9f36 100644 --- a/src/coreclr/nativeaot/libunwind/include/libunwind.h +++ b/src/coreclr/nativeaot/libunwind/include/libunwind.h @@ -96,6 +96,26 @@ struct unw_proc_info_t { }; typedef struct unw_proc_info_t unw_proc_info_t; +enum unw_save_loc_type_t +{ + UNW_SLT_NONE, /* register is not saved ("not an l-value") */ + UNW_SLT_MEMORY, /* register has been saved in memory */ + UNW_SLT_REG /* register has been saved in (another) register */ +}; +typedef enum unw_save_loc_type_t unw_save_loc_type_t; + +struct unw_save_loc_t +{ + unw_save_loc_type_t type; + union + { + unw_word_t addr; /* valid if type==UNW_SLT_MEMORY */ + unw_regnum_t regnum; /* valid if type==UNW_SLT_REG */ + } + u; +}; +typedef struct unw_save_loc_t unw_save_loc_t; + #ifdef __cplusplus extern "C" { #endif @@ -105,7 +125,7 @@ extern int unw_init_local(unw_cursor_t *, unw_context_t *) LIBUNWIND_AVAIL; extern int unw_step(unw_cursor_t *) LIBUNWIND_AVAIL; extern int unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *) LIBUNWIND_AVAIL; extern int unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *) LIBUNWIND_AVAIL; -extern int unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t) LIBUNWIND_AVAIL; +extern int unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t, unw_word_t *) LIBUNWIND_AVAIL; extern int unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t) LIBUNWIND_AVAIL; extern int unw_resume(unw_cursor_t *) LIBUNWIND_AVAIL; @@ -120,7 +140,7 @@ extern int unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *) LIBUNWIND_AVAIL; extern int unw_is_fpreg(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL; extern int unw_is_signal_frame(unw_cursor_t *) LIBUNWIND_AVAIL; extern int unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *) LIBUNWIND_AVAIL; -//extern int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*); +extern int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*) LIBUNWIND_AVAIL; extern unw_addr_space_t unw_local_addr_space; diff --git a/src/coreclr/nativeaot/libunwind/include/mach-o/compact_unwind_encoding.h b/src/coreclr/nativeaot/libunwind/include/mach-o/compact_unwind_encoding.h index 5301b1055ef93..08f943fef2a91 100644 --- a/src/coreclr/nativeaot/libunwind/include/mach-o/compact_unwind_encoding.h +++ b/src/coreclr/nativeaot/libunwind/include/mach-o/compact_unwind_encoding.h @@ -108,7 +108,7 @@ enum { // are encoded in the UNWIND_X86_EBP_FRAME_REGISTERS bits as five 3-bit entries. // Each entry contains which register to restore. // UNWIND_X86_MODE_STACK_IMMD: -// A "frameless" (EBP not used as frame pointer) function with a small +// A "frameless" (EBP not used as frame pointer) function with a small // constant stack size. To return, a constant (encoded in the compact // unwind encoding) is added to the ESP. Then the return is done by // popping the stack into the pc. @@ -119,16 +119,16 @@ enum { // UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION constains which registers were // saved and their order. // UNWIND_X86_MODE_STACK_IND: -// A "frameless" (EBP not used as frame pointer) function large constant +// A "frameless" (EBP not used as frame pointer) function large constant // stack size. This case is like the previous, except the stack size is too -// large to encode in the compact unwind encoding. Instead it requires that -// the function contains "subl $nnnnnnnn,ESP" in its prolog. The compact +// large to encode in the compact unwind encoding. Instead it requires that +// the function contains "subl $nnnnnnnn,ESP" in its prolog. The compact // encoding contains the offset to the nnnnnnnn value in the function in -// UNWIND_X86_FRAMELESS_STACK_SIZE. +// UNWIND_X86_FRAMELESS_STACK_SIZE. // UNWIND_X86_MODE_DWARF: // No compact unwind encoding is available. Instead the low 24-bits of the // compact encoding is the offset of the DWARF FDE in the __eh_frame section. -// This mode is never used in object files. It is only generated by the +// This mode is never used in object files. It is only generated by the // linker in final linked images which have only DWARF unwind info for a // function. // @@ -233,36 +233,36 @@ enum { // For x86_64 there are four modes for the compact unwind encoding: // UNWIND_X86_64_MODE_RBP_FRAME: // RBP based frame where RBP is push on stack immediately after return address, -// then RSP is moved to RBP. Thus, to unwind RSP is restored with the current -// EPB value, then RBP is restored by popping off the stack, and the return +// then RSP is moved to RBP. Thus, to unwind RSP is restored with the current +// EPB value, then RBP is restored by popping off the stack, and the return // is done by popping the stack once more into the pc. // All non-volatile registers that need to be restored must have been saved -// in a small range in the stack that starts RBP-8 to RBP-2040. The offset/8 +// in a small range in the stack that starts RBP-8 to RBP-2040. The offset/8 // is encoded in the UNWIND_X86_64_RBP_FRAME_OFFSET bits. The registers saved // are encoded in the UNWIND_X86_64_RBP_FRAME_REGISTERS bits as five 3-bit entries. -// Each entry contains which register to restore. +// Each entry contains which register to restore. // UNWIND_X86_64_MODE_STACK_IMMD: -// A "frameless" (RBP not used as frame pointer) function with a small -// constant stack size. To return, a constant (encoded in the compact -// unwind encoding) is added to the RSP. Then the return is done by +// A "frameless" (RBP not used as frame pointer) function with a small +// constant stack size. To return, a constant (encoded in the compact +// unwind encoding) is added to the RSP. Then the return is done by // popping the stack into the pc. // All non-volatile registers that need to be restored must have been saved // on the stack immediately after the return address. The stack_size/8 is // encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is 2048). // The number of registers saved is encoded in UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT. // UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION constains which registers were -// saved and their order. +// saved and their order. // UNWIND_X86_64_MODE_STACK_IND: -// A "frameless" (RBP not used as frame pointer) function large constant +// A "frameless" (RBP not used as frame pointer) function large constant // stack size. This case is like the previous, except the stack size is too -// large to encode in the compact unwind encoding. Instead it requires that -// the function contains "subq $nnnnnnnn,RSP" in its prolog. The compact +// large to encode in the compact unwind encoding. Instead it requires that +// the function contains "subq $nnnnnnnn,RSP" in its prolog. The compact // encoding contains the offset to the nnnnnnnn value in the function in -// UNWIND_X86_64_FRAMELESS_STACK_SIZE. +// UNWIND_X86_64_FRAMELESS_STACK_SIZE. // UNWIND_X86_64_MODE_DWARF: // No compact unwind encoding is available. Instead the low 24-bits of the // compact encoding is the offset of the DWARF FDE in the __eh_frame section. -// This mode is never used in object files. It is only generated by the +// This mode is never used in object files. It is only generated by the // linker in final linked images which have only DWARF unwind info for a // function. // @@ -307,20 +307,20 @@ enum { // This is a standard arm64 prolog where FP/LR are immediately pushed on the // stack, then SP is copied to FP. If there are any non-volatile registers // saved, then are copied into the stack frame in pairs in a contiguous -// range right below the saved FP/LR pair. Any subset of the five X pairs +// range right below the saved FP/LR pair. Any subset of the five X pairs // and four D pairs can be saved, but the memory layout must be in register -// number order. +// number order. // UNWIND_ARM64_MODE_FRAMELESS: -// A "frameless" leaf function, where FP/LR are not saved. The return address +// A "frameless" leaf function, where FP/LR are not saved. The return address // remains in LR throughout the function. If any non-volatile registers // are saved, they must be pushed onto the stack before any stack space is // allocated for local variables. The stack sized (including any saved -// non-volatile registers) divided by 16 is encoded in the bits +// non-volatile registers) divided by 16 is encoded in the bits // UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK. // UNWIND_ARM64_MODE_DWARF: // No compact unwind encoding is available. Instead the low 24-bits of the // compact encoding is the offset of the DWARF FDE in the __eh_frame section. -// This mode is never used in object files. It is only generated by the +// This mode is never used in object files. It is only generated by the // linker in final linked images which have only DWARF unwind info for a // function. // @@ -337,19 +337,19 @@ enum { // // A compiler can generated compact unwind information for a function by adding -// a "row" to the __LD,__compact_unwind section. This section has the -// S_ATTR_DEBUG bit set, so the section will be ignored by older linkers. -// It is removed by the new linker, so never ends up in final executables. -// This section is a table, initially with one row per function (that needs +// a "row" to the __LD,__compact_unwind section. This section has the +// S_ATTR_DEBUG bit set, so the section will be ignored by older linkers. +// It is removed by the new linker, so never ends up in final executables. +// This section is a table, initially with one row per function (that needs // unwind info). The table columns and some conceptual entries are: // // range-start pointer to start of function/range -// range-length -// compact-unwind-encoding 32-bit encoding +// range-length +// compact-unwind-encoding 32-bit encoding // personality-function or zero if no personality function // lsda or zero if no LSDA data // -// The length and encoding fields are 32-bits. The other are all pointer sized. +// The length and encoding fields are 32-bits. The other are all pointer sized. // // In x86_64 assembly, these entry would look like: // @@ -372,23 +372,23 @@ enum { // .quad except_tab1 // // -// Notes: There is no need for any labels in the the __compact_unwind section. -// The use of the .set directive is to force the evaluation of the +// Notes: There is no need for any labels in the __compact_unwind section. +// The use of the .set directive is to force the evaluation of the // range-length at assembly time, instead of generating relocations. // -// To support future compiler optimizations where which non-volatile registers +// To support future compiler optimizations where which non-volatile registers // are saved changes within a function (e.g. delay saving non-volatiles until // necessary), there can by multiple lines in the __compact_unwind table for one -// function, each with a different (non-overlapping) range and each with -// different compact unwind encodings that correspond to the non-volatiles +// function, each with a different (non-overlapping) range and each with +// different compact unwind encodings that correspond to the non-volatiles // saved at that range of the function. // // If a particular function is so wacky that there is no compact unwind way -// to encode it, then the compiler can emit traditional DWARF unwind info. +// to encode it, then the compiler can emit traditional DWARF unwind info. // The runtime will use which ever is available. // -// Runtime support for compact unwind encodings are only available on 10.6 -// and later. So, the compiler should not generate it when targeting pre-10.6. +// Runtime support for compact unwind encodings are only available on 10.6 +// and later. So, the compiler should not generate it when targeting pre-10.6. @@ -402,7 +402,7 @@ enum { // // The __TEXT,__unwind_info section is laid out for an efficient two level lookup. // The header of the section contains a coarse index that maps function address -// to the page (4096 byte block) containing the unwind info for that function. +// to the page (4096 byte block) containing the unwind info for that function. // #define UNWIND_SECTION_VERSION 1 diff --git a/src/coreclr/nativeaot/libunwind/include/unwind.h b/src/coreclr/nativeaot/libunwind/include/unwind.h index b6cc70498b378..47d303c3f095a 100644 --- a/src/coreclr/nativeaot/libunwind/include/unwind.h +++ b/src/coreclr/nativeaot/libunwind/include/unwind.h @@ -208,7 +208,7 @@ _Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, extern _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, uint32_t regno, _Unwind_VRS_DataRepresentation representation, - void *valuep); + void *valuep, uint32_t *pos); extern _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, @@ -220,7 +220,7 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, 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); + uintptr_t new_value, uintptr_t *pos); extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context); extern void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t new_value); @@ -248,8 +248,8 @@ uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) { _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); + uintptr_t value,uintptr_t *pos) { + _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value, pos); } _LIBUNWIND_EXPORT_UNWIND_LEVEL1 @@ -261,7 +261,7 @@ uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) { _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); + _Unwind_SetGR(context, 15, value | thumb_bit, NULL); } #endif // defined(_LIBUNWIND_ARM_EHABI) diff --git a/src/coreclr/nativeaot/libunwind/src/AddressSpace.hpp b/src/coreclr/nativeaot/libunwind/src/AddressSpace.hpp index fb07c807db9e9..389be0a506672 100644 --- a/src/coreclr/nativeaot/libunwind/src/AddressSpace.hpp +++ b/src/coreclr/nativeaot/libunwind/src/AddressSpace.hpp @@ -117,12 +117,23 @@ namespace libunwind { // __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0; // __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0; +#ifndef _LIBUNWIND_USE_ONLY_DWARF_INDEX extern char __eh_frame_start; extern char __eh_frame_end; +#endif #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) -extern char __eh_frame_hdr_start; -extern char __eh_frame_hdr_end; + +#ifndef _LIBUNWIND_BAREMETAL_DWARF_INDEX_SEC_START +#define _LIBUNWIND_BAREMETAL_DWARF_INDEX_SEC_START __eh_frame_hdr_start +#endif + +#ifndef _LIBUNWIND_BAREMETAL_DWARF_INDEX_SEC_END +#define _LIBUNWIND_BAREMETAL_DWARF_INDEX_SEC_END __eh_frame_hdr_end +#endif + +extern char _LIBUNWIND_BAREMETAL_DWARF_INDEX_SEC_START; +extern char _LIBUNWIND_BAREMETAL_DWARF_INDEX_SEC_END; #endif #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) @@ -161,9 +172,11 @@ struct UnwindInfoSections { uintptr_t dso_base; #endif #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) +#ifndef _LIBUNWIND_USE_ONLY_DWARF_INDEX uintptr_t dwarf_section; uintptr_t dwarf_section_length; #endif +#endif #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) uintptr_t dwarf_index_section; uintptr_t dwarf_index_section_length; @@ -401,18 +414,31 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, } #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) // Bare metal is statically linked, so no need to ask the dynamic loader +#ifndef _LIBUNWIND_USE_ONLY_DWARF_INDEX info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start); - info.dwarf_section = (uintptr_t)(&__eh_frame_start); + info.dwarf_section = (uintptr_t)(&__eh_frame_start); _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", - (void *)info.dwarf_section, (void *)info.dwarf_section_length); + (void *)info.dwarf_section, + (void *)info.dwarf_section_length); +#endif #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) - info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start); - info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start); + info.dwarf_index_section = + (uintptr_t)(&(_LIBUNWIND_BAREMETAL_DWARF_INDEX_SEC_START)); + info.dwarf_index_section_length = + (uintptr_t)(&(_LIBUNWIND_BAREMETAL_DWARF_INDEX_SEC_END) - + &(_LIBUNWIND_BAREMETAL_DWARF_INDEX_SEC_START)); _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p", - (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length); + (void *)info.dwarf_index_section, + (void *)info.dwarf_index_section_length); #endif + +#ifndef _LIBUNWIND_USE_ONLY_DWARF_INDEX if (info.dwarf_section_length) return true; +#else + if (info.dwarf_index_section_length > 0) + return true; +#endif #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) // Bare metal is statically linked, so no need to ask the dynamic loader info.arm_section = (uintptr_t)(&__exidx_start); diff --git a/src/coreclr/nativeaot/libunwind/src/CompactUnwinder.hpp b/src/coreclr/nativeaot/libunwind/src/CompactUnwinder.hpp index 1c3175dff50a4..3546f195120a1 100644 --- a/src/coreclr/nativeaot/libunwind/src/CompactUnwinder.hpp +++ b/src/coreclr/nativeaot/libunwind/src/CompactUnwinder.hpp @@ -86,19 +86,19 @@ int CompactUnwinder_x86::stepWithCompactEncodingEBPFrame( // no register saved in this slot break; case UNWIND_X86_REG_EBX: - registers.setEBX(addressSpace.get32(savedRegisters)); + registers.setEBX(addressSpace.get32(savedRegisters), savedRegisters); break; case UNWIND_X86_REG_ECX: - registers.setECX(addressSpace.get32(savedRegisters)); + registers.setECX(addressSpace.get32(savedRegisters), savedRegisters); break; case UNWIND_X86_REG_EDX: - registers.setEDX(addressSpace.get32(savedRegisters)); + registers.setEDX(addressSpace.get32(savedRegisters), savedRegisters); break; case UNWIND_X86_REG_EDI: - registers.setEDI(addressSpace.get32(savedRegisters)); + registers.setEDI(addressSpace.get32(savedRegisters), savedRegisters); break; case UNWIND_X86_REG_ESI: - registers.setESI(addressSpace.get32(savedRegisters)); + registers.setESI(addressSpace.get32(savedRegisters), savedRegisters); break; default: (void)functionStart; @@ -203,22 +203,22 @@ int CompactUnwinder_x86::stepWithCompactEncodingFrameless( for (uint32_t i = 0; i < regCount; ++i) { switch (registersSaved[i]) { case UNWIND_X86_REG_EBX: - registers.setEBX(addressSpace.get32(savedRegisters)); + registers.setEBX(addressSpace.get32(savedRegisters), savedRegisters); break; case UNWIND_X86_REG_ECX: - registers.setECX(addressSpace.get32(savedRegisters)); + registers.setECX(addressSpace.get32(savedRegisters), savedRegisters); break; case UNWIND_X86_REG_EDX: - registers.setEDX(addressSpace.get32(savedRegisters)); + registers.setEDX(addressSpace.get32(savedRegisters), savedRegisters); break; case UNWIND_X86_REG_EDI: - registers.setEDI(addressSpace.get32(savedRegisters)); + registers.setEDI(addressSpace.get32(savedRegisters), savedRegisters); break; case UNWIND_X86_REG_ESI: - registers.setESI(addressSpace.get32(savedRegisters)); + registers.setESI(addressSpace.get32(savedRegisters), savedRegisters); break; case UNWIND_X86_REG_EBP: - registers.setEBP(addressSpace.get32(savedRegisters)); + registers.setEBP(addressSpace.get32(savedRegisters), savedRegisters); break; default: _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for " @@ -238,11 +238,11 @@ void CompactUnwinder_x86::frameUnwind(A &addressSpace, Registers_x86 ®isters) { typename A::pint_t bp = registers.getEBP(); // ebp points to old ebp - registers.setEBP(addressSpace.get32(bp)); + registers.setEBP(addressSpace.get32(bp), bp); // old esp is ebp less saved ebp and return address - registers.setSP((uint32_t)bp + 8); + registers.setSP((uint32_t)bp + 8, 0); // pop return address into eip - registers.setIP(addressSpace.get32(bp + 4)); + registers.setIP(addressSpace.get32(bp + 4), bp + 4); } template @@ -250,9 +250,9 @@ void CompactUnwinder_x86::framelessUnwind( A &addressSpace, typename A::pint_t returnAddressLocation, Registers_x86 ®isters) { // return address is on stack after last saved register - registers.setIP(addressSpace.get32(returnAddressLocation)); + registers.setIP(addressSpace.get32(returnAddressLocation), returnAddressLocation); // old esp is before return address - registers.setSP((uint32_t)returnAddressLocation + 4); + registers.setSP((uint32_t)returnAddressLocation + 4, 0); } #endif // _LIBUNWIND_TARGET_I386 @@ -317,19 +317,19 @@ int CompactUnwinder_x86_64::stepWithCompactEncodingRBPFrame( // no register saved in this slot break; case UNWIND_X86_64_REG_RBX: - registers.setRBX(addressSpace.get64(savedRegisters)); + registers.setRBX(addressSpace.get64(savedRegisters), savedRegisters); break; case UNWIND_X86_64_REG_R12: - registers.setR12(addressSpace.get64(savedRegisters)); + registers.setR12(addressSpace.get64(savedRegisters), savedRegisters); break; case UNWIND_X86_64_REG_R13: - registers.setR13(addressSpace.get64(savedRegisters)); + registers.setR13(addressSpace.get64(savedRegisters), savedRegisters); break; case UNWIND_X86_64_REG_R14: - registers.setR14(addressSpace.get64(savedRegisters)); + registers.setR14(addressSpace.get64(savedRegisters), savedRegisters); break; case UNWIND_X86_64_REG_R15: - registers.setR15(addressSpace.get64(savedRegisters)); + registers.setR15(addressSpace.get64(savedRegisters), savedRegisters); break; default: (void)functionStart; @@ -434,22 +434,22 @@ int CompactUnwinder_x86_64::stepWithCompactEncodingFrameless( for (uint32_t i = 0; i < regCount; ++i) { switch (registersSaved[i]) { case UNWIND_X86_64_REG_RBX: - registers.setRBX(addressSpace.get64(savedRegisters)); + registers.setRBX(addressSpace.get64(savedRegisters), savedRegisters); break; case UNWIND_X86_64_REG_R12: - registers.setR12(addressSpace.get64(savedRegisters)); + registers.setR12(addressSpace.get64(savedRegisters), savedRegisters); break; case UNWIND_X86_64_REG_R13: - registers.setR13(addressSpace.get64(savedRegisters)); + registers.setR13(addressSpace.get64(savedRegisters), savedRegisters); break; case UNWIND_X86_64_REG_R14: - registers.setR14(addressSpace.get64(savedRegisters)); + registers.setR14(addressSpace.get64(savedRegisters), savedRegisters); break; case UNWIND_X86_64_REG_R15: - registers.setR15(addressSpace.get64(savedRegisters)); + registers.setR15(addressSpace.get64(savedRegisters), savedRegisters); break; case UNWIND_X86_64_REG_RBP: - registers.setRBP(addressSpace.get64(savedRegisters)); + registers.setRBP(addressSpace.get64(savedRegisters), savedRegisters); break; default: _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for " @@ -469,11 +469,11 @@ void CompactUnwinder_x86_64::frameUnwind(A &addressSpace, Registers_x86_64 ®isters) { uint64_t rbp = registers.getRBP(); // ebp points to old ebp - registers.setRBP(addressSpace.get64(rbp)); + registers.setRBP(addressSpace.get64(rbp), rbp); // old esp is ebp less saved ebp and return address - registers.setSP(rbp + 16); + registers.setSP(rbp + 16, 0); // pop return address into eip - registers.setIP(addressSpace.get64(rbp + 8)); + registers.setIP(addressSpace.get64(rbp + 8), rbp + 8); } template @@ -481,9 +481,9 @@ void CompactUnwinder_x86_64::framelessUnwind(A &addressSpace, uint64_t returnAddressLocation, Registers_x86_64 ®isters) { // return address is on stack after last saved register - registers.setIP(addressSpace.get64(returnAddressLocation)); + registers.setIP(addressSpace.get64(returnAddressLocation), returnAddressLocation); // old esp is before return address - registers.setSP(returnAddressLocation + 8); + registers.setSP(returnAddressLocation + 8, 0); } #endif // _LIBUNWIND_TARGET_X86_64 @@ -537,74 +537,74 @@ int CompactUnwinder_arm64::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_ARM64_X19, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { - registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { - registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { - registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { - registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { registers.setFloatRegister(UNW_ARM64_D8, - addressSpace.getDouble(savedRegisterLoc)); + addressSpace.getDouble(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; registers.setFloatRegister(UNW_ARM64_D9, - addressSpace.getDouble(savedRegisterLoc)); + addressSpace.getDouble(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { registers.setFloatRegister(UNW_ARM64_D10, - addressSpace.getDouble(savedRegisterLoc)); + addressSpace.getDouble(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; registers.setFloatRegister(UNW_ARM64_D11, - addressSpace.getDouble(savedRegisterLoc)); + addressSpace.getDouble(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { registers.setFloatRegister(UNW_ARM64_D12, - addressSpace.getDouble(savedRegisterLoc)); + addressSpace.getDouble(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; registers.setFloatRegister(UNW_ARM64_D13, - addressSpace.getDouble(savedRegisterLoc)); + addressSpace.getDouble(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { registers.setFloatRegister(UNW_ARM64_D14, - addressSpace.getDouble(savedRegisterLoc)); + addressSpace.getDouble(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; registers.setFloatRegister(UNW_ARM64_D15, - addressSpace.getDouble(savedRegisterLoc)); + addressSpace.getDouble(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } // subtract stack size off of sp - registers.setSP(savedRegisterLoc); + registers.setSP(savedRegisterLoc, 0); // set pc to be value in lr - registers.setIP(registers.getRegister(UNW_ARM64_LR)); + registers.setIP(registers.getRegister(UNW_ARM64_LR), 0); return UNW_STEP_SUCCESS; } @@ -616,33 +616,33 @@ int CompactUnwinder_arm64::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_ARM64_X19, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_ARM64_X20, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { - registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_ARM64_X21, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_ARM64_X22, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { - registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_ARM64_X23, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_ARM64_X24, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { - registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_ARM64_X25, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_ARM64_X26, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { - registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_ARM64_X27, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; - registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc)); + registers.setRegister(UNW_ARM64_X28, addressSpace.get64(savedRegisterLoc), savedRegisterLoc); savedRegisterLoc -= 8; } @@ -681,11 +681,11 @@ int CompactUnwinder_arm64::stepWithCompactEncodingFrame( uint64_t fp = registers.getFP(); // fp points to old fp - registers.setFP(addressSpace.get64(fp)); + registers.setFP(addressSpace.get64(fp), fp); // old sp is fp less saved fp and lr - registers.setSP(fp + 16); + registers.setSP(fp + 16, 0); // pop return address into pc - registers.setIP(addressSpace.get64(fp + 8)); + registers.setIP(addressSpace.get64(fp + 8), fp + 8); return UNW_STEP_SUCCESS; } diff --git a/src/coreclr/nativeaot/libunwind/src/DwarfInstructions.hpp b/src/coreclr/nativeaot/libunwind/src/DwarfInstructions.hpp index 29a070fa3e043..1eb9c472c58e2 100644 --- a/src/coreclr/nativeaot/libunwind/src/DwarfInstructions.hpp +++ b/src/coreclr/nativeaot/libunwind/src/DwarfInstructions.hpp @@ -55,7 +55,8 @@ class DwarfInstructions { const R ®isters, pint_t initialStackValue); static pint_t getSavedRegister(A &addressSpace, const R ®isters, - pint_t cfa, const RegisterLocation &savedReg); + pint_t cfa, const RegisterLocation &savedReg, + pint_t& location); static double getSavedFloatRegister(A &addressSpace, const R ®isters, pint_t cfa, const RegisterLocation &savedReg); static v128 getSavedVectorRegister(A &addressSpace, const R ®isters, @@ -78,20 +79,24 @@ class DwarfInstructions { template typename A::pint_t DwarfInstructions::getSavedRegister( A &addressSpace, const R ®isters, pint_t cfa, - const RegisterLocation &savedReg) { + const RegisterLocation &savedReg, + typename A::pint_t& location) { switch (savedReg.location) { case CFI_Parser::kRegisterInCFA: - return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value); + location = cfa + (pint_t)savedReg.value; + return (pint_t)addressSpace.getP(location); case CFI_Parser::kRegisterAtExpression: - return (pint_t)addressSpace.getRegister(evaluateExpression( - (pint_t)savedReg.value, addressSpace, registers, cfa)); + location = evaluateExpression((pint_t)savedReg.value, addressSpace, + registers, cfa); + return (pint_t)addressSpace.getP(location); case CFI_Parser::kRegisterIsExpression: + location = 0; return evaluateExpression((pint_t)savedReg.value, addressSpace, registers, cfa); - case CFI_Parser::kRegisterInRegister: + location = 0; return registers.getRegister((int)savedReg.value); case CFI_Parser::kRegisterUnused: @@ -164,6 +169,7 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, // restore registers that DWARF says were saved R newRegisters = registers; pint_t returnAddress = 0; + pint_t returnAddressLocation = 0; const int lastReg = R::lastDwarfRegNum(); assert(static_cast(CFI_Parser::kMaxRegisterNumber) >= lastReg && "register range too large"); @@ -180,13 +186,23 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, newRegisters.setVectorRegister( i, getSavedVectorRegister(addressSpace, registers, cfa, prolog.savedRegisters[i])); - else if (i == (int)cieInfo.returnAddressRegister) + else if (i == (int)cieInfo.returnAddressRegister) { returnAddress = getSavedRegister(addressSpace, registers, cfa, - prolog.savedRegisters[i]); - else if (registers.validRegister(i)) - newRegisters.setRegister( - i, getSavedRegister(addressSpace, registers, cfa, - prolog.savedRegisters[i])); + prolog.savedRegisters[i], + returnAddressLocation); + if (registers.validRegister(i)) { + newRegisters.setRegister(i, returnAddress, returnAddressLocation); + } + } + else if (registers.validRegister(i)) { + pint_t value; + pint_t location; + value = getSavedRegister(addressSpace, registers, cfa, + prolog.savedRegisters[i], + location); + + newRegisters.setRegister(i, value, location); + } else return UNW_EBADREG; } @@ -194,7 +210,7 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, // By definition, the CFA is the stack pointer at the call site, so // restoring SP means setting it to CFA. - newRegisters.setSP(cfa); + newRegisters.setSP(cfa, 0); #if defined(_LIBUNWIND_TARGET_AARCH64) // If the target is aarch64 then the return address may have been signed @@ -259,7 +275,7 @@ int DwarfInstructions::stepWithDwarf(A &addressSpace, pint_t pc, // Return address is address after call site instruction, so setting IP to // that does simualates a return. - newRegisters.setIP(returnAddress); + newRegisters.setIP(returnAddress, returnAddressLocation); // Simulate the step by replacing the register set with the new ones. registers = newRegisters; diff --git a/src/coreclr/nativeaot/libunwind/src/DwarfParser.hpp b/src/coreclr/nativeaot/libunwind/src/DwarfParser.hpp index df69c2a4bd237..a2ebf3bb0e189 100644 --- a/src/coreclr/nativeaot/libunwind/src/DwarfParser.hpp +++ b/src/coreclr/nativeaot/libunwind/src/DwarfParser.hpp @@ -11,6 +11,7 @@ #ifndef __DWARF_PARSER_HPP__ #define __DWARF_PARSER_HPP__ +#define __STDC_FORMAT_MACROS #include #include diff --git a/src/coreclr/nativeaot/libunwind/src/Registers.hpp b/src/coreclr/nativeaot/libunwind/src/Registers.hpp index a36c6cf90d3fe..e2f05fb0990d0 100644 --- a/src/coreclr/nativeaot/libunwind/src/Registers.hpp +++ b/src/coreclr/nativeaot/libunwind/src/Registers.hpp @@ -46,7 +46,8 @@ class _LIBUNWIND_HIDDEN Registers_x86 { bool validRegister(int num) const; uint32_t getRegister(int num) const; - void setRegister(int num, uint32_t value); + void setRegister(int num, uint32_t value, uint32_t location); + uint32_t getRegisterLocation(int num) const; bool validFloatRegister(int) const { return false; } double getFloatRegister(int num) const; void setFloatRegister(int num, double value); @@ -59,21 +60,21 @@ class _LIBUNWIND_HIDDEN Registers_x86 { static int getArch() { return REGISTERS_X86; } uint32_t getSP() const { return _registers.__esp; } - void setSP(uint32_t value) { _registers.__esp = value; } + void setSP(uint32_t value, uint32_t location) { _registers.__esp = value; _registerLocations.__esp = location; } uint32_t getIP() const { return _registers.__eip; } - void setIP(uint32_t value) { _registers.__eip = value; } + void setIP(uint32_t value, uint32_t location) { _registers.__eip = value; _registerLocations.__eip = location; } uint32_t getEBP() const { return _registers.__ebp; } - void setEBP(uint32_t value) { _registers.__ebp = value; } + void setEBP(uint32_t value, uint32_t location) { _registers.__ebp = value; _registerLocations.__ebp = location; } uint32_t getEBX() const { return _registers.__ebx; } - void setEBX(uint32_t value) { _registers.__ebx = value; } + void setEBX(uint32_t value, uint32_t location) { _registers.__ebx = value; _registerLocations.__ebx = location; } uint32_t getECX() const { return _registers.__ecx; } - void setECX(uint32_t value) { _registers.__ecx = value; } + void setECX(uint32_t value, uint32_t location) { _registers.__ecx = value; _registerLocations.__ecx = location; } uint32_t getEDX() const { return _registers.__edx; } - void setEDX(uint32_t value) { _registers.__edx = value; } + void setEDX(uint32_t value, uint32_t location) { _registers.__edx = value; _registerLocations.__edx = location; } uint32_t getESI() const { return _registers.__esi; } - void setESI(uint32_t value) { _registers.__esi = value; } + void setESI(uint32_t value, uint32_t location) { _registers.__esi = value; _registerLocations.__esi = location; } uint32_t getEDI() const { return _registers.__edi; } - void setEDI(uint32_t value) { _registers.__edi = value; } + void setEDI(uint32_t value, uint32_t location) { _registers.__edi = value; _registerLocations.__edi = location; } private: struct GPRs { @@ -94,18 +95,32 @@ class _LIBUNWIND_HIDDEN Registers_x86 { unsigned int __fs; unsigned int __gs; }; + struct GPRLocations { + unsigned int __eax; + unsigned int __ebx; + unsigned int __ecx; + unsigned int __edx; + unsigned int __edi; + unsigned int __esi; + unsigned int __ebp; + unsigned int __esp; + unsigned int __eip; + }; GPRs _registers; + GPRLocations _registerLocations; }; inline Registers_x86::Registers_x86(const void *registers) { static_assert((check_fit::does_fit), "x86 registers do not fit into unw_context_t"); memcpy(&_registers, registers, sizeof(_registers)); + memset(&_registerLocations, 0, sizeof(_registerLocations)); } inline Registers_x86::Registers_x86() { memset(&_registers, 0, sizeof(_registers)); + memset(&_registerLocations, 0, sizeof(_registerLocations)); } inline bool Registers_x86::validRegister(int regNum) const { @@ -154,25 +169,31 @@ inline uint32_t Registers_x86::getRegister(int regNum) const { _LIBUNWIND_ABORT("unsupported x86 register"); } -inline void Registers_x86::setRegister(int regNum, uint32_t value) { +inline void Registers_x86::setRegister(int regNum, uint32_t value, uint32_t location) { switch (regNum) { case UNW_REG_IP: _registers.__eip = value; + _registerLocations.__eip = location; return; case UNW_REG_SP: _registers.__esp = value; + _registerLocations.__esp = location; return; case UNW_X86_EAX: _registers.__eax = value; + _registerLocations.__eax = location; return; case UNW_X86_ECX: _registers.__ecx = value; + _registerLocations.__ecx = location; return; case UNW_X86_EDX: _registers.__edx = value; + _registerLocations.__edx = location; return; case UNW_X86_EBX: _registers.__ebx = value; + _registerLocations.__ebx = location; return; #if !defined(__APPLE__) case UNW_X86_ESP: @@ -180,6 +201,7 @@ inline void Registers_x86::setRegister(int regNum, uint32_t value) { case UNW_X86_EBP: #endif _registers.__ebp = value; + _registerLocations.__ebp = location; return; #if !defined(__APPLE__) case UNW_X86_EBP: @@ -187,17 +209,46 @@ inline void Registers_x86::setRegister(int regNum, uint32_t value) { case UNW_X86_ESP: #endif _registers.__esp = value; + _registerLocations.__esp = location; return; case UNW_X86_ESI: _registers.__esi = value; + _registerLocations.__esi = location; return; case UNW_X86_EDI: _registers.__edi = value; + _registerLocations.__edi = location; return; } _LIBUNWIND_ABORT("unsupported x86 register"); } +inline uint32_t Registers_x86::getRegisterLocation(int regNum) const { + switch (regNum) { + case UNW_REG_IP: + return _registerLocations.__eip; + case UNW_REG_SP: + return _registerLocations.__esp; + case UNW_X86_EAX: + return _registerLocations.__eax; + case UNW_X86_ECX: + return _registerLocations.__ecx; + case UNW_X86_EDX: + return _registerLocations.__edx; + case UNW_X86_EBX: + return _registerLocations.__ebx; + case UNW_X86_EBP: + return _registerLocations.__ebp; + case UNW_X86_ESP: + return _registerLocations.__esp; + case UNW_X86_ESI: + return _registerLocations.__esi; + case UNW_X86_EDI: + return _registerLocations.__edi; + } + _LIBUNWIND_ABORT("unsupported x86 register"); +} + inline const char *Registers_x86::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: @@ -253,7 +304,8 @@ class _LIBUNWIND_HIDDEN Registers_x86_64 { bool validRegister(int num) const; uint64_t getRegister(int num) const; - void setRegister(int num, uint64_t value); + void setRegister(int num, uint64_t value, uint64_t location); + uint64_t getRegisterLocation(int num) const; bool validFloatRegister(int) const { return false; } double getFloatRegister(int num) const; void setFloatRegister(int num, double value); @@ -266,21 +318,21 @@ class _LIBUNWIND_HIDDEN Registers_x86_64 { static int getArch() { return REGISTERS_X86_64; } uint64_t getSP() const { return _registers.__rsp; } - void setSP(uint64_t value) { _registers.__rsp = value; } + void setSP(uint64_t value, uint64_t location) { _registers.__rsp = value; _registerLocations.__rsp = location;} uint64_t getIP() const { return _registers.__rip; } - void setIP(uint64_t value) { _registers.__rip = value; } + void setIP(uint64_t value, uint64_t location) { _registers.__rip = value; _registerLocations.__rip = location; } uint64_t getRBP() const { return _registers.__rbp; } - void setRBP(uint64_t value) { _registers.__rbp = value; } + void setRBP(uint64_t value, uint64_t location) { _registers.__rbp = value; _registerLocations.__rbp = location; } uint64_t getRBX() const { return _registers.__rbx; } - void setRBX(uint64_t value) { _registers.__rbx = value; } + void setRBX(uint64_t value, uint64_t location) { _registers.__rbx = value; _registerLocations.__rbx = location; } uint64_t getR12() const { return _registers.__r12; } - void setR12(uint64_t value) { _registers.__r12 = value; } + void setR12(uint64_t value, uint64_t location) { _registers.__r12 = value; _registerLocations.__r12 = location; } uint64_t getR13() const { return _registers.__r13; } - void setR13(uint64_t value) { _registers.__r13 = value; } + void setR13(uint64_t value, uint64_t location) { _registers.__r13 = value; _registerLocations.__r13 = location; } uint64_t getR14() const { return _registers.__r14; } - void setR14(uint64_t value) { _registers.__r14 = value; } + void setR14(uint64_t value, uint64_t location) { _registers.__r14 = value; _registerLocations.__r14 = location; } uint64_t getR15() const { return _registers.__r15; } - void setR15(uint64_t value) { _registers.__r15 = value; } + void setR15(uint64_t value, uint64_t location) { _registers.__r15 = value; _registerLocations.__r15 = location; } private: struct GPRs { @@ -309,7 +361,27 @@ class _LIBUNWIND_HIDDEN Registers_x86_64 { uint64_t __padding; // 16-byte align #endif }; + struct GPRLocations { + uint64_t __rax; + uint64_t __rbx; + uint64_t __rcx; + uint64_t __rdx; + uint64_t __rdi; + uint64_t __rsi; + uint64_t __rbp; + uint64_t __rsp; + uint64_t __r8; + uint64_t __r9; + uint64_t __r10; + uint64_t __r11; + uint64_t __r12; + uint64_t __r13; + uint64_t __r14; + uint64_t __r15; + uint64_t __rip; + }; GPRs _registers; + GPRLocations _registerLocations; #if defined(_WIN64) v128 _xmm[16]; #endif @@ -319,10 +391,12 @@ inline Registers_x86_64::Registers_x86_64(const void *registers) { static_assert((check_fit::does_fit), "x86_64 registers do not fit into unw_context_t"); memcpy(&_registers, registers, sizeof(_registers)); + memset(&_registerLocations, 0, sizeof(_registerLocations)); } inline Registers_x86_64::Registers_x86_64() { memset(&_registers, 0, sizeof(_registers)); + memset(&_registerLocations, 0, sizeof(_registerLocations)); } inline bool Registers_x86_64::validRegister(int regNum) const { @@ -379,61 +453,121 @@ inline uint64_t Registers_x86_64::getRegister(int regNum) const { _LIBUNWIND_ABORT("unsupported x86_64 register"); } -inline void Registers_x86_64::setRegister(int regNum, uint64_t value) { +inline uint64_t Registers_x86_64::getRegisterLocation(int regNum) const { + switch (regNum) { + case UNW_REG_IP: + return _registerLocations.__rip; + case UNW_REG_SP: + return _registerLocations.__rsp; + case UNW_X86_64_RAX: + return _registerLocations.__rax; + case UNW_X86_64_RDX: + return _registerLocations.__rdx; + case UNW_X86_64_RCX: + return _registerLocations.__rcx; + case UNW_X86_64_RBX: + return _registerLocations.__rbx; + case UNW_X86_64_RSI: + return _registerLocations.__rsi; + case UNW_X86_64_RDI: + return _registerLocations.__rdi; + case UNW_X86_64_RBP: + return _registerLocations.__rbp; + case UNW_X86_64_RSP: + return _registerLocations.__rsp; + case UNW_X86_64_R8: + return _registerLocations.__r8; + case UNW_X86_64_R9: + return _registerLocations.__r9; + case UNW_X86_64_R10: + return _registerLocations.__r10; + case UNW_X86_64_R11: + return _registerLocations.__r11; + case UNW_X86_64_R12: + return _registerLocations.__r12; + case UNW_X86_64_R13: + return _registerLocations.__r13; + case UNW_X86_64_R14: + return _registerLocations.__r14; + case UNW_X86_64_R15: + return _registerLocations.__r15; + } + _LIBUNWIND_ABORT("unsupported x86_64 register"); +} + +inline void Registers_x86_64::setRegister(int regNum, uint64_t value, uint64_t location) { switch (regNum) { case UNW_REG_IP: _registers.__rip = value; + _registerLocations.__rip = location; return; case UNW_REG_SP: _registers.__rsp = value; + _registerLocations.__rsp = location; return; case UNW_X86_64_RAX: _registers.__rax = value; + _registerLocations.__rax = location; return; case UNW_X86_64_RDX: _registers.__rdx = value; + _registerLocations.__rdx = location; return; case UNW_X86_64_RCX: _registers.__rcx = value; + _registerLocations.__rcx = location; return; case UNW_X86_64_RBX: _registers.__rbx = value; + _registerLocations.__rbx = location; return; case UNW_X86_64_RSI: _registers.__rsi = value; + _registerLocations.__rsi = location; return; case UNW_X86_64_RDI: _registers.__rdi = value; + _registerLocations.__rdi = location; return; case UNW_X86_64_RBP: _registers.__rbp = value; + _registerLocations.__rbp = location; return; case UNW_X86_64_RSP: _registers.__rsp = value; + _registerLocations.__rsp = location; return; case UNW_X86_64_R8: _registers.__r8 = value; + _registerLocations.__r8 = location; return; case UNW_X86_64_R9: _registers.__r9 = value; + _registerLocations.__r9 = location; return; case UNW_X86_64_R10: _registers.__r10 = value; + _registerLocations.__r10 = location; return; case UNW_X86_64_R11: _registers.__r11 = value; + _registerLocations.__r11 = location; return; case UNW_X86_64_R12: _registers.__r12 = value; + _registerLocations.__r12 = location; return; case UNW_X86_64_R13: _registers.__r13 = value; + _registerLocations.__r13 = location; return; case UNW_X86_64_R14: _registers.__r14 = value; + _registerLocations.__r14 = location; return; case UNW_X86_64_R15: _registers.__r15 = value; + _registerLocations.__r15 = location; return; } _LIBUNWIND_ABORT("unsupported x86_64 register"); @@ -1133,7 +1267,8 @@ class _LIBUNWIND_HIDDEN Registers_ppc64 { bool validRegister(int num) const; uint64_t getRegister(int num) const; - void setRegister(int num, uint64_t value); + void setRegister(int num, uint64_t value, uint64_t location); + uint64_t getRegisterLocation(int num) const; bool validFloatRegister(int num) const; double getFloatRegister(int num) const; void setFloatRegister(int num, double value); @@ -1776,24 +1911,25 @@ class _LIBUNWIND_HIDDEN Registers_arm64 { bool validRegister(int num) const; uint64_t getRegister(int num) const; - void setRegister(int num, uint64_t value); + void setRegister(int num, uint64_t value, uint64_t location); bool validFloatRegister(int num) const; double getFloatRegister(int num) const; void setFloatRegister(int num, double value); bool validVectorRegister(int num) const; v128 getVectorRegister(int num) const; void setVectorRegister(int num, v128 value); + uint64_t getRegisterLocation(int regNum) const; static const char *getRegisterName(int num); void jumpto(); static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; } static int getArch() { return REGISTERS_ARM64; } uint64_t getSP() const { return _registers.__sp; } - void setSP(uint64_t value) { _registers.__sp = value; } + void setSP(uint64_t value, uint64_t location) { _registers.__sp = value; } uint64_t getIP() const { return _registers.__pc; } - void setIP(uint64_t value) { _registers.__pc = value; } + void setIP(uint64_t value, uint64_t location) { _registers.__pc = value; } uint64_t getFP() const { return _registers.__fp; } - void setFP(uint64_t value) { _registers.__fp = value; } + void setFP(uint64_t value, uint64_t location) { _registers.__fp = value; } private: struct GPRs { @@ -1805,7 +1941,17 @@ class _LIBUNWIND_HIDDEN Registers_arm64 { uint64_t __ra_sign_state; // RA sign state register }; + struct GPRLocations { + uint64_t __x[29]; // x0-x28 + uint64_t __fp; // Frame pointer x29 + uint64_t __lr; // Link register x30 + uint64_t __sp; // Stack pointer x31 + uint64_t __pc; // Program counter + uint64_t padding; // 16-byte align + }; + GPRs _registers; + GPRLocations _registerLocations; double _vectorHalfRegisters[32]; // Currently only the lower double in 128-bit vectore registers // is perserved during unwinding. We could define new register @@ -1817,7 +1963,9 @@ inline Registers_arm64::Registers_arm64(const void *registers) { static_assert((check_fit::does_fit), "arm64 registers do not fit into unw_context_t"); memcpy(&_registers, registers, sizeof(_registers)); - static_assert(sizeof(GPRs) == 0x110, + memset(&_registerLocations, 0, sizeof(_registerLocations)); + static_assert( + sizeof(GPRs) == 0x110, "expected VFP registers to be at offset 272"); memcpy(_vectorHalfRegisters, static_cast(registers) + sizeof(GPRs), @@ -1826,6 +1974,7 @@ inline Registers_arm64::Registers_arm64(const void *registers) { inline Registers_arm64::Registers_arm64() { memset(&_registers, 0, sizeof(_registers)); + memset(&_registerLocations, 0, sizeof(_registerLocations)); memset(&_vectorHalfRegisters, 0, sizeof(_vectorHalfRegisters)); } @@ -1857,19 +2006,35 @@ inline uint64_t Registers_arm64::getRegister(int regNum) const { _LIBUNWIND_ABORT("unsupported arm64 register"); } -inline void Registers_arm64::setRegister(int regNum, uint64_t value) { - if (regNum == UNW_REG_IP) +inline void Registers_arm64::setRegister(int regNum, uint64_t value, uint64_t location) { + if (regNum == UNW_REG_IP) { _registers.__pc = value; - else if (regNum == UNW_REG_SP) + _registerLocations.__pc = location; + } + else if (regNum == UNW_REG_SP) { _registers.__sp = value; + _registerLocations.__sp = location; + } else if (regNum == UNW_ARM64_RA_SIGN_STATE) _registers.__ra_sign_state = value; - else if ((regNum >= 0) && (regNum < 32)) + else if ((regNum >= 0) && (regNum < 32)) { _registers.__x[regNum] = value; + _registerLocations.__x[regNum] = location; + } else _LIBUNWIND_ABORT("unsupported arm64 register"); } +inline uint64_t Registers_arm64::getRegisterLocation(int regNum) const { + if (regNum == UNW_REG_IP) + return _registerLocations.__pc; + if (regNum == UNW_REG_SP) + return _registerLocations.__sp; + if ((regNum >= 0) && (regNum < 32)) + return _registerLocations.__x[regNum]; + _LIBUNWIND_ABORT("unsupported arm64 register"); +} + inline const char *Registers_arm64::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: @@ -2009,6 +2174,8 @@ inline const char *Registers_arm64::getRegisterName(int regNum) { } } +inline void Registers_arm64::jumpto() {} + inline bool Registers_arm64::validFloatRegister(int regNum) const { if (regNum < UNW_ARM64_D0) return false; @@ -2053,7 +2220,8 @@ class _LIBUNWIND_HIDDEN Registers_arm { bool validRegister(int num) const; uint32_t getRegister(int num) const; - void setRegister(int num, uint32_t value); + void setRegister(int num, uint32_t value, uint32_t location); + uint32_t getRegisterLocation(int num) const; bool validFloatRegister(int num) const; unw_fpreg_t getFloatRegister(int num); void setFloatRegister(int num, unw_fpreg_t value); @@ -2069,9 +2237,9 @@ class _LIBUNWIND_HIDDEN Registers_arm { static int getArch() { return REGISTERS_ARM; } uint32_t getSP() const { return _registers.__sp; } - void setSP(uint32_t value) { _registers.__sp = value; } + void setSP(uint32_t value, uint32_t location) { _registers.__sp = value; _registerLocations.__sp = location; } uint32_t getIP() const { return _registers.__pc; } - void setIP(uint32_t value) { _registers.__pc = value; } + void setIP(uint32_t value, uint32_t location) { _registers.__pc = value; _registerLocations.__pc = location; } void saveVFPAsX() { assert(_use_X_for_vfp_save || !_saved_vfp_d0_d15); @@ -2103,7 +2271,14 @@ class _LIBUNWIND_HIDDEN Registers_arm { uint32_t __pc; // Program counter r15 }; - static void saveVFPWithFSTMD(void*); + struct GPRLocations { + uint32_t __r[13]; // r0-r12 + uint32_t __sp; // Stack pointer r13 + uint32_t __lr; // Link register r14 + uint32_t __pc; // Program counter r15 + }; + + static void saveVFPWithFSTMD(void *); static void saveVFPWithFSTMX(void*); static void saveVFPv3(void*); static void restoreVFPWithFLDMD(void*); @@ -2119,6 +2294,7 @@ class _LIBUNWIND_HIDDEN Registers_arm { // ARM registers GPRs _registers; + GPRLocations _registerLocations; // We save floating point registers lazily because we can't know ahead of // time which ones are used. See EHABI #4.7. @@ -2156,6 +2332,7 @@ inline Registers_arm::Registers_arm(const void *registers) "arm registers do not fit into unw_context_t"); // See __unw_getcontext() note about data. memcpy(&_registers, registers, sizeof(_registers)); + memset(&_registerLocations, 0, sizeof(_registerLocations)); memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad)); memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31)); #if defined(__ARM_WMMX) @@ -2171,6 +2348,7 @@ inline Registers_arm::Registers_arm() _saved_vfp_d0_d15(false), _saved_vfp_d16_d31(false) { memset(&_registers, 0, sizeof(_registers)); + memset(&_registerLocations, 0, sizeof(_registerLocations)); memset(&_vfp_d0_d15_pad, 0, sizeof(_vfp_d0_d15_pad)); memset(&_vfp_d16_d31, 0, sizeof(_vfp_d16_d31)); #if defined(__ARM_WMMX) @@ -2227,24 +2405,28 @@ inline uint32_t Registers_arm::getRegister(int regNum) const { _LIBUNWIND_ABORT("unsupported arm register"); } -inline void Registers_arm::setRegister(int regNum, uint32_t value) { +inline void Registers_arm::setRegister(int regNum, uint32_t value, uint32_t location) { if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) { _registers.__sp = value; + _registerLocations.__sp = location; return; } if (regNum == UNW_ARM_LR) { _registers.__lr = value; + _registerLocations.__lr = location; return; } if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) { _registers.__pc = value; + _registerLocations.__pc = location; return; } if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) { _registers.__r[regNum] = value; + _registerLocations.__r[regNum] = location; return; } @@ -2262,6 +2444,22 @@ inline void Registers_arm::setRegister(int regNum, uint32_t value) { _LIBUNWIND_ABORT("unsupported arm register"); } +inline uint32_t Registers_arm::getRegisterLocation(int regNum) const { + if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP) + return _registerLocations.__sp; + + if (regNum == UNW_ARM_LR) + return _registerLocations.__lr; + + if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP) + return _registerLocations.__pc; + + if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R12) + return _registerLocations.__r[regNum]; + + _LIBUNWIND_ABORT("unsupported arm register"); +} + inline const char *Registers_arm::getRegisterName(int regNum) { switch (regNum) { case UNW_REG_IP: diff --git a/src/coreclr/nativeaot/libunwind/src/Unwind-EHABI.cpp b/src/coreclr/nativeaot/libunwind/src/Unwind-EHABI.cpp index 4ff5e318b5f10..90acd50e395f4 100644 --- a/src/coreclr/nativeaot/libunwind/src/Unwind-EHABI.cpp +++ b/src/coreclr/nativeaot/libunwind/src/Unwind-EHABI.cpp @@ -31,11 +31,7 @@ namespace { // signinficant byte. uint8_t getByte(const uint32_t* data, size_t offset) { const uint8_t* byteData = reinterpret_cast(data); -#ifdef __LITTLE_ENDIAN__ return byteData[(offset & ~(size_t)0x03) + (3 - (offset & (size_t)0x03))]; -#else - return byteData[offset]; -#endif } const char* getNextWord(const char* data, uint32_t* out) { @@ -95,9 +91,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; @@ -219,7 +217,7 @@ decode_eht_entry(const uint32_t* data, size_t* off, size_t* len) { // only by the personality routine. Fortunately, all existing assembler // implementations, including GNU assembler, LLVM integrated assembler, // and ARM assembler, assume that the unwind opcodes come after the - // personality rountine address. + // personality routine address. *off = 1; // First byte is size data. *len = (((data[1] >> 24) & 0xff) + 1) * 4; data++; // Skip the first word, which is the prel31 offset. @@ -261,7 +259,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, sp -= (((uint32_t)byte & 0x3f) << 2) + 4; else sp += ((uint32_t)byte << 2) + 4; - _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp); + _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp, NULL); } else { switch (byte & 0xf0) { case 0x80: { @@ -285,7 +283,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_R0 + reg, _UVRSD_UINT32, &sp); _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, - &sp); + &sp, NULL); break; } case 0xa0: { @@ -327,7 +325,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, &sp); sp += 0x204 + (addend << 2); _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, - &sp); + &sp, NULL); break; } case 0xb3: { @@ -413,7 +411,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data, if (!wrotePC) { uint32_t lr; _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_LR, _UVRSD_UINT32, &lr); - _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr); + _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr, NULL); } return _URC_CONTINUE_UNWIND; } @@ -562,7 +560,7 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor // // See #7.4.6 for details. __unw_set_reg(cursor, UNW_REG_IP, - exception_object->unwinder_cache.reserved2); + exception_object->unwinder_cache.reserved2, NULL); resume = false; } @@ -699,7 +697,7 @@ _LIBUNWIND_EXPORT void _Unwind_Complete(_Unwind_Exception* exception_object) { /// may force a jump to a landing pad in that function, the landing /// pad code may then call _Unwind_Resume() to continue with the /// unwinding. Note: the call to _Unwind_Resume() is from compiler -/// geneated user code. All other _Unwind_* routines are called +/// generated user code. All other _Unwind_* routines are called /// by the C++ runtime __cxa_* routines. /// /// Note: re-throwing an exception (as opposed to continuing the unwind) @@ -757,7 +755,7 @@ static uint64_t ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation, _LIBUNWIND_EXPORT _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, uint32_t regno, _Unwind_VRS_DataRepresentation representation, - void *valuep) { + void *valuep, unw_word_t *pos) { _LIBUNWIND_TRACE_API("_Unwind_VRS_Set(context=%p, regclass=%d, reg=%d, " "rep=%d, value=0x%llX)", static_cast(context), regclass, regno, @@ -769,7 +767,7 @@ _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, if (representation != _UVRSD_UINT32 || regno > 15) return _UVRSR_FAILED; return __unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno), - *(unw_word_t *)valuep) == UNW_ESUCCESS + *(unw_word_t *)valuep,(unw_word_t *)pos) == UNW_ESUCCESS ? _UVRSR_OK : _UVRSR_FAILED; case _UVRSC_VFP: @@ -901,6 +899,7 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, // computed new stack location. See EHABI #7.5.4 table 3. bool poppedSP = false; uint32_t* sp; + uint32_t* pos; if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp) != _UVRSR_OK) { return _UVRSR_FAILED; @@ -908,17 +907,18 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, for (uint32_t i = 0; i < 16; ++i) { if (!(discriminator & static_cast(1 << i))) continue; + pos = sp; uint32_t value = *sp++; if (regclass == _UVRSC_CORE && i == 13) poppedSP = true; if (_Unwind_VRS_Set(context, regclass, i, - _UVRSD_UINT32, &value) != _UVRSR_OK) { + _UVRSD_UINT32, &value, pos) != _UVRSR_OK) { return _UVRSR_FAILED; } } if (!poppedSP) { return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, - _UVRSD_UINT32, &sp); + _UVRSD_UINT32, &sp, NULL); } return _UVRSR_OK; } @@ -943,14 +943,14 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, // SP is only 32-bit aligned so don't copy 64-bit at a time. uint64_t value = *sp++; value |= ((uint64_t)(*sp++)) << 32; - if (_Unwind_VRS_Set(context, regclass, i, representation, &value) != + if (_Unwind_VRS_Set(context, regclass, i, representation, &value, NULL) != _UVRSR_OK) return _UVRSR_FAILED; } if (representation == _UVRSD_VFPX) ++sp; return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, - &sp); + &sp, NULL); } } _LIBUNWIND_ABORT("unsupported register class"); diff --git a/src/coreclr/nativeaot/libunwind/src/UnwindCursor.hpp b/src/coreclr/nativeaot/libunwind/src/UnwindCursor.hpp index a96c9f39958d6..3a6c5131c93bc 100644 --- a/src/coreclr/nativeaot/libunwind/src/UnwindCursor.hpp +++ b/src/coreclr/nativeaot/libunwind/src/UnwindCursor.hpp @@ -416,9 +416,12 @@ class _LIBUNWIND_HIDDEN AbstractUnwindCursor { virtual ~AbstractUnwindCursor() {} virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); } virtual unw_word_t getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); } - virtual void setReg(int, unw_word_t) { + virtual void setReg(int, unw_word_t, unw_word_t) { _LIBUNWIND_ABORT("setReg not implemented"); } + virtual unw_word_t getRegLocation(int) { + _LIBUNWIND_ABORT("getRegLocation not implemented"); + } virtual bool validFloatReg(int) { _LIBUNWIND_ABORT("validFloatReg not implemented"); } @@ -878,12 +881,14 @@ template class UnwindCursor : public AbstractUnwindCursor{ typedef typename A::pint_t pint_t; public: + UnwindCursor(A &as); UnwindCursor(unw_context_t *context, A &as); UnwindCursor(A &as, void *threadArg); virtual ~UnwindCursor() {} virtual bool validReg(int); virtual unw_word_t getReg(int); - virtual void setReg(int, unw_word_t); + virtual void setReg(int, unw_word_t, unw_word_t); + virtual unw_word_t getRegLocation(int); virtual bool validFloatReg(int); virtual unw_fpreg_t getFloatReg(int); virtual void setFloatReg(int, unw_fpreg_t); @@ -923,6 +928,7 @@ class UnwindCursor : public AbstractUnwindCursor{ #endif #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) +public: bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections §s, uint32_t fdeSectionOffsetHint=0); int stepWithDwarfFDE() { @@ -1151,6 +1157,13 @@ class UnwindCursor : public AbstractUnwindCursor{ bool _isSignalFrame; }; +template +UnwindCursor::UnwindCursor(A &as) + : _addressSpace(as) + , _unwindInfoMissing(false) + , _isSignalFrame(false) { + memset(&_info, 0, sizeof(_info)); +} template UnwindCursor::UnwindCursor(unw_context_t *context, A &as) @@ -1162,9 +1175,11 @@ UnwindCursor::UnwindCursor(unw_context_t *context, A &as) } template -UnwindCursor::UnwindCursor(A &as, void *) - : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) { +UnwindCursor::UnwindCursor(A &as, void *arg) + : _addressSpace(as),_registers(arg), _unwindInfoMissing(false), + _isSignalFrame(false) { memset(&_info, 0, sizeof(_info)); + // FIXME // fill in _registers from thread arg } @@ -1181,8 +1196,13 @@ unw_word_t UnwindCursor::getReg(int regNum) { } template -void UnwindCursor::setReg(int regNum, unw_word_t value) { - _registers.setRegister(regNum, (typename A::pint_t)value); +void UnwindCursor::setReg(int regNum, unw_word_t value, unw_word_t location) { + _registers.setRegister(regNum, (typename A::pint_t)value, (typename A::pint_t)location); +} + +template +unw_word_t UnwindCursor::getRegLocation(int regNum) { + return _registers.getRegisterLocation(regNum); } template @@ -1439,7 +1459,7 @@ bool UnwindCursor::getInfoFromEHABISection( _info.unwind_info = exceptionTableAddr; _info.lsda = lsda; // flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0. - _info.flags = isSingleWordEHT ? 1 : 0 | scope32 ? 0x2 : 0; // Use enum? + _info.flags = (isSingleWordEHT ? 1 : 0) | (scope32 ? 0x2 : 0); // Use enum? return true; } @@ -1454,6 +1474,8 @@ bool UnwindCursor::getInfoFromDwarfSection(pint_t pc, typename CFI_Parser::CIE_Info cieInfo; bool foundFDE = false; bool foundInCache = false; + +#ifndef _LIBUNWIND_USE_ONLY_DWARF_INDEX // If compact encoding table gave offset into dwarf section, go directly there if (fdeSectionOffsetHint != 0) { foundFDE = CFI_Parser::findFDE(_addressSpace, pc, sects.dwarf_section, @@ -1461,6 +1483,8 @@ bool UnwindCursor::getInfoFromDwarfSection(pint_t pc, sects.dwarf_section + fdeSectionOffsetHint, &fdeInfo, &cieInfo); } +#endif + #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) if (!foundFDE && (sects.dwarf_index_section != 0)) { foundFDE = EHHeaderParser::findFDE( @@ -1468,6 +1492,8 @@ bool UnwindCursor::getInfoFromDwarfSection(pint_t pc, (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo); } #endif + +#ifndef _LIBUNWIND_USE_ONLY_DWARF_INDEX if (!foundFDE) { // otherwise, search cache of previously found FDEs. pint_t cachedFDE = DwarfFDECache::findFDE(sects.dso_base, pc); @@ -1485,6 +1511,7 @@ bool UnwindCursor::getInfoFromDwarfSection(pint_t pc, (uint32_t)sects.dwarf_section_length, 0, &fdeInfo, &cieInfo); } +#endif if (foundFDE) { typename CFI_Parser::PrologInfo prolog; if (CFI_Parser::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc, @@ -1876,7 +1903,11 @@ void UnwindCursor::setInfoBasedOnIPRegister(bool isReturnAddress) { #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) // If there is dwarf unwind info, look there next. +#if defined(_LIBUNWIND_USE_ONLY_DWARF_INDEX) + if (sects.dwarf_index_section != 0) { +#else if (sects.dwarf_section != 0) { +#endif if (this->getInfoFromDwarfSection(pc, sects)) { // found info in dwarf, done return; diff --git a/src/coreclr/nativeaot/libunwind/src/UnwindRegistersRestore.S b/src/coreclr/nativeaot/libunwind/src/UnwindRegistersRestore.S index 8122bf3e1b2ea..01113565e8e00 100644 --- a/src/coreclr/nativeaot/libunwind/src/UnwindRegistersRestore.S +++ b/src/coreclr/nativeaot/libunwind/src/UnwindRegistersRestore.S @@ -575,8 +575,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv) ldp x10,x11, [x0, #0x050] ldp x12,x13, [x0, #0x060] ldp x14,x15, [x0, #0x070] - // x16 and x17 were clobbered by the call into the unwinder, so no point in - // restoring them. + ldp x16,x17, [x0, #0x080] ldp x18,x19, [x0, #0x090] ldp x20,x21, [x0, #0x0A0] ldp x22,x23, [x0, #0x0B0] @@ -584,6 +583,8 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv) ldp x26,x27, [x0, #0x0D0] ldp x28,x29, [x0, #0x0E0] ldr x30, [x0, #0x100] // restore pc into lr + ldr x1, [x0, #0x0F8] + mov sp,x1 // restore sp ldp d0, d1, [x0, #0x110] ldp d2, d3, [x0, #0x120] @@ -603,13 +604,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv) ldr d30, [x0, #0x200] ldr d31, [x0, #0x208] - // Finally, restore sp. This must be done after the the last read from the - // context struct, because it is allocated on the stack, and an exception - // could clobber the de-allocated portion of the stack after sp has been - // restored. - ldr x16, [x0, #0x0F8] ldp x0, x1, [x0, #0x000] // restore x0,x1 - mov sp,x16 // restore sp ret x30 // jump to pc #elif defined(__arm__) && !defined(__APPLE__) diff --git a/src/coreclr/nativeaot/libunwind/src/libunwind.cpp b/src/coreclr/nativeaot/libunwind/src/libunwind.cpp index c90032bd66c95..387ad0fe1616f 100644 --- a/src/coreclr/nativeaot/libunwind/src/libunwind.cpp +++ b/src/coreclr/nativeaot/libunwind/src/libunwind.cpp @@ -90,15 +90,15 @@ _LIBUNWIND_WEAK_ALIAS(__unw_get_reg, unw_get_reg) /// Set value of specified register at cursor position in stack frame. _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, - unw_word_t value) { + unw_word_t value, unw_word_t *pos) { _LIBUNWIND_TRACE_API("__unw_set_reg(cursor=%p, regNum=%d, value=0x%" PRIxPTR ")", static_cast(cursor), regNum, value); typedef LocalAddressSpace::pint_t pint_t; AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; if (co->validReg(regNum)) { - co->setReg(regNum, (pint_t)value); - // specical case altering IP to re-find info (being called by personality + co->setReg(regNum, (pint_t)value, (pint_t)pos); + // special case altering IP to re-find info (being called by personality // function) if (regNum == UNW_REG_IP) { unw_proc_info_t info; @@ -112,7 +112,7 @@ _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, // this should actually be - info.gp. LLVM doesn't currently support // any such platforms and Clang doesn't export a macro for them. if (info.gp) - co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + info.gp); + co->setReg(UNW_REG_SP, co->getReg(UNW_REG_SP) + info.gp, 0); } return UNW_ESUCCESS; } @@ -154,6 +154,21 @@ _LIBUNWIND_HIDDEN int __unw_set_fpreg(unw_cursor_t *cursor, unw_regnum_t regNum, } _LIBUNWIND_WEAK_ALIAS(__unw_set_fpreg, unw_set_fpreg) +/// Get location of specified register at cursor position in stack frame. +_LIBUNWIND_HIDDEN int __unw_get_save_loc(unw_cursor_t *cursor, int regNum, + unw_save_loc_t* location) +{ + AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; + if (co->validReg(regNum)) { + // We only support memory locations, not register locations + location->u.addr = co->getRegLocation(regNum); + location->type = (location->u.addr == 0) ? UNW_SLT_NONE : UNW_SLT_MEMORY; + return UNW_ESUCCESS; + } + return UNW_EBADREG; +} +_LIBUNWIND_WEAK_ALIAS(__unw_get_save_loc, unw_get_save_loc) + /// Move cursor to next frame. _LIBUNWIND_HIDDEN int __unw_step(unw_cursor_t *cursor) { _LIBUNWIND_TRACE_API("__unw_step(cursor=%p)", static_cast(cursor)); diff --git a/src/coreclr/nativeaot/libunwind/src/libunwind_ext.h b/src/coreclr/nativeaot/libunwind/src/libunwind_ext.h index 316dee2982460..b240ba7fbcacd 100644 --- a/src/coreclr/nativeaot/libunwind/src/libunwind_ext.h +++ b/src/coreclr/nativeaot/libunwind/src/libunwind_ext.h @@ -28,7 +28,7 @@ extern int __unw_init_local(unw_cursor_t *, unw_context_t *); extern int __unw_step(unw_cursor_t *); extern int __unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *); extern int __unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *); -extern int __unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t); +extern int __unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t, unw_word_t *); extern int __unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t); extern int __unw_resume(unw_cursor_t *); @@ -42,6 +42,7 @@ extern int __unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *); extern int __unw_is_fpreg(unw_cursor_t *, unw_regnum_t); extern int __unw_is_signal_frame(unw_cursor_t *); extern int __unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *); +extern int __unw_get_save_loc(unw_cursor_t *, int, unw_save_loc_t *); // SPI extern void __unw_iterate_dwarf_unwind_cache(void (*func)( diff --git a/src/coreclr/nativeaot/libunwind/src/unwind_ext.h b/src/coreclr/nativeaot/libunwind/src/unwind_ext.h new file mode 100644 index 0000000000000..c40ce6a1610f4 --- /dev/null +++ b/src/coreclr/nativeaot/libunwind/src/unwind_ext.h @@ -0,0 +1,37 @@ +//===-------------------------- unwind_ext.h ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +// +// Extensions to unwind API. +// +//===----------------------------------------------------------------------===// + +#ifndef __UNWIND_EXT__ +#define __UNWIND_EXT__ + +#include "unwind.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// These platform specific functions to get and set the top context are +// implemented elsewhere. + +extern struct _Unwind_FunctionContext * +__Unwind_SjLj_GetTopOfFunctionStack(); + +extern void +__Unwind_SjLj_SetTopOfFunctionStack(struct _Unwind_FunctionContext *fc); + +#ifdef __cplusplus +} +#endif + +#endif // __UNWIND_EXT__ + +