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__
+
+