aboutsummaryrefslogtreecommitdiffstats
path: root/contrib
diff options
context:
space:
mode:
authordtorilov <dtorilov@yandex-team.com>2024-02-02 17:47:32 +0300
committerAlexander Smirnov <alex@ydb.tech>2024-02-09 19:17:21 +0300
commitac6be7a8607c3a62daae289c6dac983a013cd486 (patch)
tree72138e2bb7b8ab172ebf422d8bdac5f66a096aef /contrib
parentbf45c42c5fc90bf8d855cdf4e382aa29ba041fdb (diff)
downloadydb-ac6be7a8607c3a62daae289c6dac983a013cd486.tar.gz
Update contrib/libs/libunwind to 18.1.0-rc1
Diffstat (limited to 'contrib')
-rw-r--r--contrib/libs/libunwind/include/__libunwind_config.h28
-rw-r--r--contrib/libs/libunwind/include/libunwind.h128
-rw-r--r--contrib/libs/libunwind/include/mach-o/compact_unwind_encoding.h86
-rw-r--r--contrib/libs/libunwind/include/unwind.h4
-rw-r--r--contrib/libs/libunwind/src/AddressSpace.hpp126
-rw-r--r--contrib/libs/libunwind/src/CompactUnwinder.hpp1
-rw-r--r--contrib/libs/libunwind/src/DwarfInstructions.hpp81
-rw-r--r--contrib/libs/libunwind/src/DwarfParser.hpp9
-rw-r--r--contrib/libs/libunwind/src/EHHeaderParser.hpp16
-rw-r--r--contrib/libs/libunwind/src/FrameHeaderCache.hpp6
-rw-r--r--contrib/libs/libunwind/src/Registers.hpp645
-rw-r--r--contrib/libs/libunwind/src/Unwind-EHABI.cpp24
-rw-r--r--contrib/libs/libunwind/src/Unwind-seh.cpp31
-rw-r--r--contrib/libs/libunwind/src/Unwind-sjlj.c17
-rw-r--r--contrib/libs/libunwind/src/Unwind-wasm.c123
-rw-r--r--contrib/libs/libunwind/src/UnwindCursor.hpp944
-rw-r--r--contrib/libs/libunwind/src/UnwindLevel1-gcc-ext.c44
-rw-r--r--contrib/libs/libunwind/src/UnwindLevel1.c92
-rw-r--r--contrib/libs/libunwind/src/UnwindRegistersRestore.S382
-rw-r--r--contrib/libs/libunwind/src/UnwindRegistersSave.S265
-rw-r--r--contrib/libs/libunwind/src/Unwind_AppleExtras.cpp113
-rw-r--r--contrib/libs/libunwind/src/assembly.h49
-rw-r--r--contrib/libs/libunwind/src/cet_unwind.h2
-rw-r--r--contrib/libs/libunwind/src/config.h39
-rw-r--r--contrib/libs/libunwind/src/libunwind.cpp112
-rw-r--r--contrib/libs/libunwind/src/libunwind_ext.h69
-rw-r--r--contrib/libs/libunwind/ya.make11
27 files changed, 2766 insertions, 681 deletions
diff --git a/contrib/libs/libunwind/include/__libunwind_config.h b/contrib/libs/libunwind/include/__libunwind_config.h
index e87bcf4003..8db336b2d7 100644
--- a/contrib/libs/libunwind/include/__libunwind_config.h
+++ b/contrib/libs/libunwind/include/__libunwind_config.h
@@ -9,8 +9,10 @@
#ifndef ____LIBUNWIND_CONFIG_H__
#define ____LIBUNWIND_CONFIG_H__
+#define _LIBUNWIND_VERSION 15000
+
#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \
- !defined(__ARM_DWARF_EH__)
+ !defined(__ARM_DWARF_EH__) && !defined(__SEH__)
#define _LIBUNWIND_ARM_EHABI
#endif
@@ -27,11 +29,16 @@
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON 34
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 64
#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE 143
+#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X 83
+#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH 64
#if defined(_LIBUNWIND_IS_NATIVE_ONLY)
# if defined(__linux__)
# define _LIBUNWIND_TARGET_LINUX 1
# endif
+# if defined(__HAIKU__)
+# define _LIBUNWIND_TARGET_HAIKU 1
+# endif
# if defined(__i386__)
# define _LIBUNWIND_TARGET_I386
# define _LIBUNWIND_CONTEXT_SIZE 8
@@ -158,6 +165,21 @@
# define _LIBUNWIND_CONTEXT_SIZE 67
# define _LIBUNWIND_CURSOR_SIZE 79
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE
+# elif defined(__s390x__)
+# define _LIBUNWIND_TARGET_S390X 1
+# define _LIBUNWIND_CONTEXT_SIZE 34
+# define _LIBUNWIND_CURSOR_SIZE 46
+# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X
+#elif defined(__loongarch__)
+#define _LIBUNWIND_TARGET_LOONGARCH 1
+#if __loongarch_grlen == 64
+#define _LIBUNWIND_CONTEXT_SIZE 65
+#define _LIBUNWIND_CURSOR_SIZE 77
+#else
+#error "Unsupported LoongArch ABI"
+#endif
+#define _LIBUNWIND_HIGHEST_DWARF_REGISTER \
+ _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH
# else
# error "Unsupported architecture."
# endif
@@ -176,8 +198,10 @@
# define _LIBUNWIND_TARGET_HEXAGON 1
# define _LIBUNWIND_TARGET_RISCV 1
# define _LIBUNWIND_TARGET_VE 1
+# define _LIBUNWIND_TARGET_S390X 1
+# define _LIBUNWIND_TARGET_LOONGARCH 1
# define _LIBUNWIND_CONTEXT_SIZE 167
-# define _LIBUNWIND_CURSOR_SIZE 179
+# define _LIBUNWIND_CURSOR_SIZE 204
# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287
#endif // _LIBUNWIND_IS_NATIVE_ONLY
diff --git a/contrib/libs/libunwind/include/libunwind.h b/contrib/libs/libunwind/include/libunwind.h
index 8303c1a04c..02739b384e 100644
--- a/contrib/libs/libunwind/include/libunwind.h
+++ b/contrib/libs/libunwind/include/libunwind.h
@@ -81,7 +81,7 @@ typedef struct unw_addr_space *unw_addr_space_t;
typedef int unw_regnum_t;
typedef uintptr_t unw_word_t;
-#if defined(__arm__) && !defined(__ARM_DWARF_EH__)
+#if defined(__arm__) && !defined(__ARM_DWARF_EH__) && !defined(__SEH__)
typedef uint64_t unw_fpreg_t;
#else
typedef double unw_fpreg_t;
@@ -120,6 +120,9 @@ extern int unw_resume(unw_cursor_t *) LIBUNWIND_AVAIL;
extern void unw_save_vfp_as_X(unw_cursor_t *) LIBUNWIND_AVAIL;
#endif
+#ifdef _AIX
+extern uintptr_t unw_get_data_rel_base(unw_cursor_t *) LIBUNWIND_AVAIL;
+#endif
extern const char *unw_regname(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL;
extern int unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *) LIBUNWIND_AVAIL;
@@ -873,6 +876,9 @@ enum {
UNW_MIPS_F29 = 61,
UNW_MIPS_F30 = 62,
UNW_MIPS_F31 = 63,
+ // HI,LO have been dropped since r6, we keep them here.
+ // So, when we add DSP/MSA etc, we can use the same register indexes
+ // for r6 and pre-r6.
UNW_MIPS_HI = 64,
UNW_MIPS_LO = 65,
};
@@ -1020,6 +1026,16 @@ enum {
UNW_RISCV_F29 = 61,
UNW_RISCV_F30 = 62,
UNW_RISCV_F31 = 63,
+ // 65-95 -- Reserved for future standard extensions
+ // 96-127 -- v0-v31 (Vector registers)
+ // 128-3071 -- Reserved for future standard extensions
+ // 3072-4095 -- Reserved for custom extensions
+ // 4096-8191 -- CSRs
+ //
+ // VLENB CSR number: 0xC22 -- defined by section 3 of v-spec:
+ // https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#3-vector-extension-programmers-model
+ // VLENB DWARF number: 0x1000 + 0xC22
+ UNW_RISCV_VLENB = 0x1C22,
};
// VE register numbers
@@ -1174,4 +1190,114 @@ enum {
UNW_VE_VL = 145,
};
+// s390x register numbers
+enum {
+ UNW_S390X_R0 = 0,
+ UNW_S390X_R1 = 1,
+ UNW_S390X_R2 = 2,
+ UNW_S390X_R3 = 3,
+ UNW_S390X_R4 = 4,
+ UNW_S390X_R5 = 5,
+ UNW_S390X_R6 = 6,
+ UNW_S390X_R7 = 7,
+ UNW_S390X_R8 = 8,
+ UNW_S390X_R9 = 9,
+ UNW_S390X_R10 = 10,
+ UNW_S390X_R11 = 11,
+ UNW_S390X_R12 = 12,
+ UNW_S390X_R13 = 13,
+ UNW_S390X_R14 = 14,
+ UNW_S390X_R15 = 15,
+ UNW_S390X_F0 = 16,
+ UNW_S390X_F2 = 17,
+ UNW_S390X_F4 = 18,
+ UNW_S390X_F6 = 19,
+ UNW_S390X_F1 = 20,
+ UNW_S390X_F3 = 21,
+ UNW_S390X_F5 = 22,
+ UNW_S390X_F7 = 23,
+ UNW_S390X_F8 = 24,
+ UNW_S390X_F10 = 25,
+ UNW_S390X_F12 = 26,
+ UNW_S390X_F14 = 27,
+ UNW_S390X_F9 = 28,
+ UNW_S390X_F11 = 29,
+ UNW_S390X_F13 = 30,
+ UNW_S390X_F15 = 31,
+ // 32-47 Control Registers
+ // 48-63 Access Registers
+ UNW_S390X_PSWM = 64,
+ UNW_S390X_PSWA = 65,
+ // 66-67 Reserved
+ // 68-83 Vector Registers %v16-%v31
+};
+
+// LoongArch registers.
+enum {
+ UNW_LOONGARCH_R0 = 0,
+ UNW_LOONGARCH_R1 = 1,
+ UNW_LOONGARCH_R2 = 2,
+ UNW_LOONGARCH_R3 = 3,
+ UNW_LOONGARCH_R4 = 4,
+ UNW_LOONGARCH_R5 = 5,
+ UNW_LOONGARCH_R6 = 6,
+ UNW_LOONGARCH_R7 = 7,
+ UNW_LOONGARCH_R8 = 8,
+ UNW_LOONGARCH_R9 = 9,
+ UNW_LOONGARCH_R10 = 10,
+ UNW_LOONGARCH_R11 = 11,
+ UNW_LOONGARCH_R12 = 12,
+ UNW_LOONGARCH_R13 = 13,
+ UNW_LOONGARCH_R14 = 14,
+ UNW_LOONGARCH_R15 = 15,
+ UNW_LOONGARCH_R16 = 16,
+ UNW_LOONGARCH_R17 = 17,
+ UNW_LOONGARCH_R18 = 18,
+ UNW_LOONGARCH_R19 = 19,
+ UNW_LOONGARCH_R20 = 20,
+ UNW_LOONGARCH_R21 = 21,
+ UNW_LOONGARCH_R22 = 22,
+ UNW_LOONGARCH_R23 = 23,
+ UNW_LOONGARCH_R24 = 24,
+ UNW_LOONGARCH_R25 = 25,
+ UNW_LOONGARCH_R26 = 26,
+ UNW_LOONGARCH_R27 = 27,
+ UNW_LOONGARCH_R28 = 28,
+ UNW_LOONGARCH_R29 = 29,
+ UNW_LOONGARCH_R30 = 30,
+ UNW_LOONGARCH_R31 = 31,
+ UNW_LOONGARCH_F0 = 32,
+ UNW_LOONGARCH_F1 = 33,
+ UNW_LOONGARCH_F2 = 34,
+ UNW_LOONGARCH_F3 = 35,
+ UNW_LOONGARCH_F4 = 36,
+ UNW_LOONGARCH_F5 = 37,
+ UNW_LOONGARCH_F6 = 38,
+ UNW_LOONGARCH_F7 = 39,
+ UNW_LOONGARCH_F8 = 40,
+ UNW_LOONGARCH_F9 = 41,
+ UNW_LOONGARCH_F10 = 42,
+ UNW_LOONGARCH_F11 = 43,
+ UNW_LOONGARCH_F12 = 44,
+ UNW_LOONGARCH_F13 = 45,
+ UNW_LOONGARCH_F14 = 46,
+ UNW_LOONGARCH_F15 = 47,
+ UNW_LOONGARCH_F16 = 48,
+ UNW_LOONGARCH_F17 = 49,
+ UNW_LOONGARCH_F18 = 50,
+ UNW_LOONGARCH_F19 = 51,
+ UNW_LOONGARCH_F20 = 52,
+ UNW_LOONGARCH_F21 = 53,
+ UNW_LOONGARCH_F22 = 54,
+ UNW_LOONGARCH_F23 = 55,
+ UNW_LOONGARCH_F24 = 56,
+ UNW_LOONGARCH_F25 = 57,
+ UNW_LOONGARCH_F26 = 58,
+ UNW_LOONGARCH_F27 = 59,
+ UNW_LOONGARCH_F28 = 60,
+ UNW_LOONGARCH_F29 = 61,
+ UNW_LOONGARCH_F30 = 62,
+ UNW_LOONGARCH_F31 = 63,
+};
+
#endif
diff --git a/contrib/libs/libunwind/include/mach-o/compact_unwind_encoding.h b/contrib/libs/libunwind/include/mach-o/compact_unwind_encoding.h
index 68d562eec4..4c48e33c3c 100644
--- a/contrib/libs/libunwind/include/mach-o/compact_unwind_encoding.h
+++ b/contrib/libs/libunwind/include/mach-o/compact_unwind_encoding.h
@@ -33,7 +33,7 @@
//
-// The compact unwind endoding is a 32-bit value which encoded in an
+// The compact unwind encoding is a 32-bit value which encoded in an
// architecture specific way, which registers to restore from where, and how
// to unwind out of the function.
//
@@ -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.
@@ -116,19 +116,19 @@ enum {
// on the stack immediately after the return address. The stack_size/4 is
// encoded in the UNWIND_X86_FRAMELESS_STACK_SIZE (max stack size is 1024).
// The number of registers saved is encoded in UNWIND_X86_FRAMELESS_STACK_REG_COUNT.
-// UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION constains which registers were
+// UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION contains 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.
+// UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION contains which registers were
+// 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/contrib/libs/libunwind/include/unwind.h b/contrib/libs/libunwind/include/unwind.h
index 6949e063dd..0e6e9f279d 100644
--- a/contrib/libs/libunwind/include/unwind.h
+++ b/contrib/libs/libunwind/include/unwind.h
@@ -93,7 +93,7 @@ extern void _Unwind_SjLj_Unregister(_Unwind_FunctionContext_t fc);
#endif
//
-// The following are semi-suppoted extensions to the C++ ABI
+// The following are semi-supported extensions to the C++ ABI
//
//
@@ -160,7 +160,7 @@ extern const void *_Unwind_Find_FDE(const void *pc, struct dwarf_eh_bases *);
extern void *_Unwind_FindEnclosingFunction(void *pc);
// Mac OS X does not support text-rel and data-rel addressing so these functions
-// are unimplemented
+// are unimplemented.
extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context)
LIBUNWIND_UNAVAIL;
extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context)
diff --git a/contrib/libs/libunwind/src/AddressSpace.hpp b/contrib/libs/libunwind/src/AddressSpace.hpp
index 0c4dfeb4e6..5551c7d4be 100644
--- a/contrib/libs/libunwind/src/AddressSpace.hpp
+++ b/contrib/libs/libunwind/src/AddressSpace.hpp
@@ -24,7 +24,7 @@
#include "Registers.hpp"
#ifndef _LIBUNWIND_USE_DLADDR
- #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)
+ #if !(defined(_LIBUNWIND_IS_BAREMETAL) || defined(_WIN32) || defined(_AIX))
#define _LIBUNWIND_USE_DLADDR 1
#else
#define _LIBUNWIND_USE_DLADDR 0
@@ -45,6 +45,13 @@ struct EHABIIndexEntry {
};
#endif
+#if defined(_AIX)
+namespace libunwind {
+char *getFuncNameFromTBTable(uintptr_t pc, uint16_t &NameLen,
+ unw_word_t *offset);
+}
+#endif
+
#ifdef __APPLE__
struct dyld_unwind_sections
@@ -59,6 +66,10 @@ struct EHABIIndexEntry {
// In 10.7.0 or later, libSystem.dylib implements this function.
extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *);
+namespace libunwind {
+ bool findDynamicUnwindSections(void *, unw_dynamic_unwind_sections *);
+}
+
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
// When statically linked on bare-metal, the symbols for the EH table are looked
@@ -239,7 +250,7 @@ inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) {
inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) {
const uint8_t *p = (uint8_t *)addr;
const uint8_t *pend = (uint8_t *)end;
- int64_t result = 0;
+ uint64_t result = 0;
int bit = 0;
uint8_t byte;
do {
@@ -253,7 +264,7 @@ inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) {
if ((byte & 0x40) != 0 && bit < 64)
result |= (-1ULL) << bit;
addr = (pint_t) p;
- return result;
+ return (int64_t)result;
}
inline LocalAddressSpace::pint_t
@@ -366,28 +377,6 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding,
typedef ElfW(Addr) Elf_Addr;
#endif
-static Elf_Addr calculateImageBase(struct dl_phdr_info *pinfo) {
- Elf_Addr image_base = pinfo->dlpi_addr;
-#if defined(__ANDROID__) && __ANDROID_API__ < 18
- if (image_base == 0) {
- // Normally, an image base of 0 indicates a non-PIE executable. On
- // versions of Android prior to API 18, the dynamic linker reported a
- // dlpi_addr of 0 for PIE executables. Compute the true image base
- // using the PT_PHDR segment.
- // See https://github.com/android/ndk/issues/505.
- for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) {
- const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i];
- if (phdr->p_type == PT_PHDR) {
- image_base = reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) -
- phdr->p_vaddr;
- break;
- }
- }
- }
-#endif
- return image_base;
-}
-
struct _LIBUNWIND_HIDDEN dl_iterate_cb_data {
LocalAddressSpace *addressSpace;
UnwindInfoSections *sects;
@@ -425,8 +414,8 @@ static bool checkForUnwindInfoSegment(const Elf_Phdr *phdr, size_t image_base,
cbdata->sects->dwarf_index_section = eh_frame_hdr_start;
cbdata->sects->dwarf_index_section_length = phdr->p_memsz;
if (EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
- *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
- hdrInfo)) {
+ *cbdata->addressSpace, eh_frame_hdr_start,
+ eh_frame_hdr_start + phdr->p_memsz, hdrInfo)) {
// .eh_frame_hdr records the start of .eh_frame, but not its size.
// Rely on a zero terminator to find the end of the section.
cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr;
@@ -461,7 +450,7 @@ static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo,
(void)pinfo_size;
#endif
- Elf_Addr image_base = calculateImageBase(pinfo);
+ Elf_Addr image_base = pinfo->dlpi_addr;
// Most shared objects seen in this callback function likely don't contain the
// target address, so optimize for that. Scan for a matching PT_LOAD segment
@@ -512,6 +501,22 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
info.compact_unwind_section_length = (size_t)dyldInfo.compact_unwind_section_length;
return true;
}
+
+ unw_dynamic_unwind_sections dynamicUnwindSectionInfo;
+ if (findDynamicUnwindSections((void *)targetAddr,
+ &dynamicUnwindSectionInfo)) {
+ info.dso_base = dynamicUnwindSectionInfo.dso_base;
+#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
+ info.dwarf_section = (uintptr_t)dynamicUnwindSectionInfo.dwarf_section;
+ info.dwarf_section_length = dynamicUnwindSectionInfo.dwarf_section_length;
+#endif
+ info.compact_unwind_section =
+ (uintptr_t)dynamicUnwindSectionInfo.compact_unwind_section;
+ info.compact_unwind_section_length =
+ dynamicUnwindSectionInfo.compact_unwind_section_length;
+ return true;
+ }
+
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL)
info.dso_base = 0;
// Bare metal is statically linked, so no need to ask the dynamic loader
@@ -544,6 +549,7 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
DWORD err = GetLastError();
_LIBUNWIND_TRACE_UNWINDING("findUnwindSections: EnumProcessModules failed, "
"returned error %d", (int)err);
+ (void)err;
return false;
}
@@ -580,6 +586,11 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
(void)targetAddr;
(void)info;
return true;
+#elif defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
+ // The traceback table is used for unwinding.
+ (void)targetAddr;
+ (void)info;
+ return true;
#elif defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX)
int length = 0;
info.arm_section =
@@ -588,6 +599,57 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
if (info.arm_section && info.arm_section_length)
return true;
#elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
+ // Use DLFO_STRUCT_HAS_EH_DBASE to determine the existence of
+ // `_dl_find_object`. Use _LIBUNWIND_SUPPORT_DWARF_INDEX, because libunwind
+ // support for _dl_find_object on other unwind formats is not implemented,
+ // yet.
+#if defined(DLFO_STRUCT_HAS_EH_DBASE) & defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
+ // We expect `_dl_find_object` to return PT_GNU_EH_FRAME.
+#if DLFO_EH_SEGMENT_TYPE != PT_GNU_EH_FRAME
+#error _dl_find_object retrieves an unexpected section type
+#endif
+ // We look-up `dl_find_object` dynamically at runtime to ensure backwards
+ // compatibility with earlier version of glibc not yet providing it. On older
+ // systems, we gracefully fallback to `dl_iterate_phdr`. Cache the pointer
+ // so we only look it up once. Do manual lock to avoid _cxa_guard_acquire.
+ static decltype(_dl_find_object) *dlFindObject;
+ static bool dlFindObjectChecked = false;
+ if (!dlFindObjectChecked) {
+ dlFindObject = reinterpret_cast<decltype(_dl_find_object) *>(
+ dlsym(RTLD_DEFAULT, "_dl_find_object"));
+ dlFindObjectChecked = true;
+ }
+ // Try to find the unwind info using `dl_find_object`
+ dl_find_object findResult;
+ if (dlFindObject && dlFindObject((void *)targetAddr, &findResult) == 0) {
+ if (findResult.dlfo_eh_frame == nullptr) {
+ // Found an entry for `targetAddr`, but there is no unwind info.
+ return false;
+ }
+ info.dso_base = reinterpret_cast<uintptr_t>(findResult.dlfo_map_start);
+ info.text_segment_length = static_cast<size_t>(
+ (char *)findResult.dlfo_map_end - (char *)findResult.dlfo_map_start);
+
+ // Record the start of PT_GNU_EH_FRAME.
+ info.dwarf_index_section =
+ reinterpret_cast<uintptr_t>(findResult.dlfo_eh_frame);
+ // `_dl_find_object` does not give us the size of PT_GNU_EH_FRAME.
+ // Setting length to `SIZE_MAX` effectively disables all range checks.
+ info.dwarf_index_section_length = SIZE_MAX;
+ EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo;
+ if (!EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
+ *this, info.dwarf_index_section,
+ info.dwarf_index_section + info.dwarf_index_section_length,
+ hdrInfo)) {
+ return false;
+ }
+ // Record the start of the FDE and use SIZE_MAX to indicate that we do
+ // not know the end address.
+ info.dwarf_section = hdrInfo.eh_frame_ptr;
+ info.dwarf_section_length = SIZE_MAX;
+ return true;
+ }
+#endif
dl_iterate_cb_data cb_data = {this, &info, targetAddr};
int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data);
return static_cast<bool>(found);
@@ -596,7 +658,6 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
return false;
}
-
inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
// TO DO: if OS has way to dynamically register FDEs, check that.
(void)targetAddr;
@@ -616,6 +677,13 @@ inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
return true;
}
}
+#elif defined(_AIX)
+ uint16_t nameLen;
+ char *funcName = getFuncNameFromTBTable(addr, nameLen, offset);
+ if (funcName != NULL) {
+ snprintf(buf, bufLen, "%.*s", nameLen, funcName);
+ return true;
+ }
#else
(void)addr;
(void)buf;
diff --git a/contrib/libs/libunwind/src/CompactUnwinder.hpp b/contrib/libs/libunwind/src/CompactUnwinder.hpp
index 0b2b5e111b..a7a8a153d8 100644
--- a/contrib/libs/libunwind/src/CompactUnwinder.hpp
+++ b/contrib/libs/libunwind/src/CompactUnwinder.hpp
@@ -19,6 +19,7 @@
#include <mach-o/compact_unwind_encoding.h>
#include "Registers.hpp"
+#include "libunwind_ext.h"
#define EXTRACT_BITS(value, mask) \
((value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask))) - 1))
diff --git a/contrib/libs/libunwind/src/DwarfInstructions.hpp b/contrib/libs/libunwind/src/DwarfInstructions.hpp
index ab83b0c87a..bd9ece60ee 100644
--- a/contrib/libs/libunwind/src/DwarfInstructions.hpp
+++ b/contrib/libs/libunwind/src/DwarfInstructions.hpp
@@ -16,16 +16,17 @@
#include <stdio.h>
#include <stdlib.h>
-#include "dwarf2.h"
-#include "Registers.hpp"
#include "DwarfParser.hpp"
+#include "Registers.hpp"
#include "config.h"
+#include "dwarf2.h"
+#include "libunwind_ext.h"
namespace libunwind {
-/// DwarfInstructions maps abtract DWARF unwind instructions to a particular
+/// DwarfInstructions maps abstract DWARF unwind instructions to a particular
/// architecture
template <typename A, typename R>
class DwarfInstructions {
@@ -34,7 +35,7 @@ public:
typedef typename A::sint_t sint_t;
static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart,
- R &registers, bool &isSignalFrame);
+ R &registers, bool &isSignalFrame, bool stage2);
private:
@@ -67,11 +68,15 @@ private:
return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
prolog.cfaRegisterOffset);
if (prolog.cfaExpression != 0)
- return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
+ return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
registers, 0);
assert(0 && "getCFA(): unknown location");
__builtin_unreachable();
}
+#if defined(_LIBUNWIND_TARGET_AARCH64)
+ static bool getRA_SIGN_STATE(A &addressSpace, R registers, pint_t cfa,
+ PrologInfo &prolog);
+#endif
};
template <typename R>
@@ -166,11 +171,26 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister(
}
_LIBUNWIND_ABORT("unsupported restore location for vector register");
}
+#if defined(_LIBUNWIND_TARGET_AARCH64)
+template <typename A, typename R>
+bool DwarfInstructions<A, R>::getRA_SIGN_STATE(A &addressSpace, R registers,
+ pint_t cfa, PrologInfo &prolog) {
+ pint_t raSignState;
+ auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE];
+ if (regloc.location == CFI_Parser<A>::kRegisterUnused)
+ raSignState = static_cast<pint_t>(regloc.value);
+ else
+ raSignState = getSavedRegister(addressSpace, registers, cfa, regloc);
+
+ // Only bit[0] is meaningful.
+ return raSignState & 0x01;
+}
+#endif
template <typename A, typename R>
int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
pint_t fdeStart, R &registers,
- bool &isSignalFrame) {
+ bool &isSignalFrame, bool stage2) {
FDE_Info fdeInfo;
CIE_Info cieInfo;
if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo,
@@ -181,7 +201,39 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
// get pointer to cfa (architecture specific)
pint_t cfa = getCFA(addressSpace, prolog, registers);
- // restore registers that DWARF says were saved
+ (void)stage2;
+ // __unw_step_stage2 is not used for cross unwinding, so we use
+ // __aarch64__ rather than LIBUNWIND_TARGET_AARCH64 to make sure we are
+ // building for AArch64 natively.
+#if defined(__aarch64__)
+ if (stage2 && cieInfo.mteTaggedFrame) {
+ pint_t sp = registers.getSP();
+ pint_t p = sp;
+ // AArch64 doesn't require the value of SP to be 16-byte aligned at
+ // all times, only at memory accesses and public interfaces [1]. Thus,
+ // a signal could arrive at a point where SP is not aligned properly.
+ // In that case, the kernel fixes up [2] the signal frame, but we
+ // still have a misaligned SP in the previous frame. If that signal
+ // handler caused stack unwinding, we would have an unaligned SP.
+ // We do not need to fix up the CFA, as that is the SP at a "public
+ // interface".
+ // [1]:
+ // https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#622the-stack
+ // [2]:
+ // https://github.com/torvalds/linux/blob/1930a6e739c4b4a654a69164dbe39e554d228915/arch/arm64/kernel/signal.c#L718
+ p &= ~0xfULL;
+ // CFA is the bottom of the current stack frame.
+ for (; p < cfa; p += 16) {
+ __asm__ __volatile__(".arch armv8.5-a\n"
+ ".arch_extension memtag\n"
+ "stg %[Ptr], [%[Ptr]]\n"
+ :
+ : [Ptr] "r"(p)
+ : "memory");
+ }
+ }
+#endif
+ // restore registers that DWARF says were saved
R newRegisters = registers;
// Typically, the CFA is the stack pointer at the call site in
@@ -194,9 +246,10 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
newRegisters.setSP(cfa);
pint_t returnAddress = 0;
- const int lastReg = R::lastDwarfRegNum();
- assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >= lastReg &&
- "register range too large");
+ constexpr int lastReg = R::lastDwarfRegNum();
+ static_assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >=
+ lastReg,
+ "register range too large");
assert(lastReg >= (int)cieInfo.returnAddressRegister &&
"register range does not contain return address register");
for (int i = 0; i <= lastReg; ++i) {
@@ -221,7 +274,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
return UNW_EBADREG;
} else if (i == (int)cieInfo.returnAddressRegister) {
// Leaf function keeps the return address in register and there is no
- // explicit intructions how to restore it.
+ // explicit instructions how to restore it.
returnAddress = registers.getRegister(cieInfo.returnAddressRegister);
}
}
@@ -235,7 +288,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
// restored. autia1716 is used instead of autia as autia1716 assembles
// to a NOP on pre-v8.3a architectures.
if ((R::getArch() == REGISTERS_ARM64) &&
- prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value &&
+ getRA_SIGN_STATE(addressSpace, registers, cfa, prolog) &&
returnAddress != 0) {
#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
return UNW_ECROSSRASIGNING;
@@ -311,7 +364,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
#endif
// Return address is address after call site instruction, so setting IP to
- // that does simualates a return.
+ // that does simulates a return.
newRegisters.setIP(returnAddress);
// Simulate the step by replacing the register set with the new ones.
@@ -615,7 +668,7 @@ DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
svalue = (sint_t)*sp;
*sp = (pint_t)(svalue >> value);
if (log)
- fprintf(stderr, "shift left arithmetric\n");
+ fprintf(stderr, "shift left arithmetic\n");
break;
case DW_OP_xor:
diff --git a/contrib/libs/libunwind/src/DwarfParser.hpp b/contrib/libs/libunwind/src/DwarfParser.hpp
index b5a53166fc..0682942ce1 100644
--- a/contrib/libs/libunwind/src/DwarfParser.hpp
+++ b/contrib/libs/libunwind/src/DwarfParser.hpp
@@ -51,6 +51,7 @@ public:
uint8_t returnAddressRegister;
#if defined(_LIBUNWIND_TARGET_AARCH64)
bool addressesSignedWithBKey;
+ bool mteTaggedFrame;
#endif
};
@@ -325,6 +326,7 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
cieInfo->fdesHaveAugmentationData = false;
#if defined(_LIBUNWIND_TARGET_AARCH64)
cieInfo->addressesSignedWithBKey = false;
+ cieInfo->mteTaggedFrame = false;
#endif
cieInfo->cieStart = cie;
pint_t p = cie;
@@ -353,7 +355,7 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
while (addressSpace.get8(p) != 0)
++p;
++p;
- // parse code aligment factor
+ // parse code alignment factor
cieInfo->codeAlignFactor = (uint32_t)addressSpace.getULEB128(p, cieContentEnd);
// parse data alignment factor
cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd);
@@ -394,6 +396,9 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
case 'B':
cieInfo->addressesSignedWithBKey = true;
break;
+ case 'G':
+ cieInfo->mteTaggedFrame = true;
+ break;
#endif
default:
// ignore unknown letters
@@ -407,7 +412,7 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
}
-/// "run" the DWARF instructions and create the abstact PrologInfo for an FDE
+/// "run" the DWARF instructions and create the abstract PrologInfo for an FDE
template <typename A>
bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace,
const FDE_Info &fdeInfo,
diff --git a/contrib/libs/libunwind/src/EHHeaderParser.hpp b/contrib/libs/libunwind/src/EHHeaderParser.hpp
index 9a38070fab..0662a1321e 100644
--- a/contrib/libs/libunwind/src/EHHeaderParser.hpp
+++ b/contrib/libs/libunwind/src/EHHeaderParser.hpp
@@ -55,9 +55,23 @@ template <typename A>
bool EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo) {
pint_t p = ehHdrStart;
+
+ // Ensure that we don't read data beyond the end of .eh_frame_hdr
+ if (ehHdrEnd - ehHdrStart < 4) {
+ // Don't print a message for an empty .eh_frame_hdr (this can happen if
+ // the linker script defines symbols for it even in the empty case).
+ if (ehHdrEnd == ehHdrStart)
+ return false;
+ _LIBUNWIND_LOG("unsupported .eh_frame_hdr at %" PRIx64
+ ": need at least 4 bytes of data but only got %zd",
+ static_cast<uint64_t>(ehHdrStart),
+ static_cast<size_t>(ehHdrEnd - ehHdrStart));
+ return false;
+ }
uint8_t version = addressSpace.get8(p++);
if (version != 1) {
- _LIBUNWIND_LOG0("Unsupported .eh_frame_hdr version");
+ _LIBUNWIND_LOG("unsupported .eh_frame_hdr version: %" PRIu8 " at %" PRIx64,
+ version, static_cast<uint64_t>(ehHdrStart));
return false;
}
diff --git a/contrib/libs/libunwind/src/FrameHeaderCache.hpp b/contrib/libs/libunwind/src/FrameHeaderCache.hpp
index 54d5d33c3c..296064d8e2 100644
--- a/contrib/libs/libunwind/src/FrameHeaderCache.hpp
+++ b/contrib/libs/libunwind/src/FrameHeaderCache.hpp
@@ -31,8 +31,8 @@
class _LIBUNWIND_HIDDEN FrameHeaderCache {
struct CacheEntry {
- uintptr_t LowPC() { return Info.dso_base; };
- uintptr_t HighPC() { return Info.dso_base + Info.text_segment_length; };
+ uintptr_t LowPC() { return Info.dso_base; }
+ uintptr_t HighPC() { return Info.dso_base + Info.text_segment_length; }
UnwindInfoSections Info;
CacheEntry *Next;
};
@@ -41,7 +41,7 @@ class _LIBUNWIND_HIDDEN FrameHeaderCache {
// Can't depend on the C++ standard library in libunwind, so use an array to
// allocate the entries, and two linked lists for ordering unused and recently
- // used entries. FIXME: Would the the extra memory for a doubly-linked list
+ // used entries. FIXME: Would the extra memory for a doubly-linked list
// be better than the runtime cost of traversing a very short singly-linked
// list on a cache miss? The entries themselves are all small and consecutive,
// so unlikely to cause page faults when following the pointers. The memory
diff --git a/contrib/libs/libunwind/src/Registers.hpp b/contrib/libs/libunwind/src/Registers.hpp
index cbc3876d67..d11ddb3426 100644
--- a/contrib/libs/libunwind/src/Registers.hpp
+++ b/contrib/libs/libunwind/src/Registers.hpp
@@ -39,6 +39,8 @@ enum {
REGISTERS_HEXAGON,
REGISTERS_RISCV,
REGISTERS_VE,
+ REGISTERS_S390X,
+ REGISTERS_LOONGARCH,
};
#if defined(_LIBUNWIND_TARGET_I386)
@@ -69,7 +71,9 @@ public:
void setVectorRegister(int num, v128 value);
static const char *getRegisterName(int num);
void jumpto() { __libunwind_Registers_x86_jumpto(this); }
- static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; }
+ static constexpr int lastDwarfRegNum() {
+ return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86;
+ }
static int getArch() { return REGISTERS_X86; }
uint32_t getSP() const { return _registers.__esp; }
@@ -285,7 +289,9 @@ public:
void setVectorRegister(int num, v128 value);
static const char *getRegisterName(int num);
void jumpto() { __libunwind_Registers_x86_64_jumpto(this); }
- static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; }
+ static constexpr int lastDwarfRegNum() {
+ return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64;
+ }
static int getArch() { return REGISTERS_X86_64; }
uint64_t getSP() const { return _registers.__rsp; }
@@ -602,13 +608,19 @@ public:
void setVectorRegister(int num, v128 value);
static const char *getRegisterName(int num);
void jumpto();
- static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC; }
+ static constexpr int lastDwarfRegNum() {
+ return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC;
+ }
static int getArch() { return REGISTERS_PPC; }
uint64_t getSP() const { return _registers.__r1; }
void setSP(uint32_t value) { _registers.__r1 = value; }
uint64_t getIP() const { return _registers.__srr0; }
void setIP(uint32_t value) { _registers.__srr0 = value; }
+ uint64_t getCR() const { return _registers.__cr; }
+ void setCR(uint32_t value) { _registers.__cr = value; }
+ uint64_t getLR() const { return _registers.__lr; }
+ void setLR(uint32_t value) { _registers.__lr = value; }
private:
struct ppc_thread_state_t {
@@ -1168,13 +1180,19 @@ public:
void setVectorRegister(int num, v128 value);
static const char *getRegisterName(int num);
void jumpto();
- static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64; }
+ static constexpr int lastDwarfRegNum() {
+ return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64;
+ }
static int getArch() { return REGISTERS_PPC64; }
uint64_t getSP() const { return _registers.__r1; }
void setSP(uint64_t value) { _registers.__r1 = value; }
uint64_t getIP() const { return _registers.__srr0; }
void setIP(uint64_t value) { _registers.__srr0 = value; }
+ uint64_t getCR() const { return _registers.__cr; }
+ void setCR(uint64_t value) { _registers.__cr = value; }
+ uint64_t getLR() const { return _registers.__lr; }
+ void setLR(uint64_t value) { _registers.__lr = value; }
private:
struct ppc64_thread_state_t {
@@ -1813,7 +1831,9 @@ public:
void setVectorRegister(int num, v128 value);
static const char *getRegisterName(int num);
void jumpto() { __libunwind_Registers_arm64_jumpto(this); }
- static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; }
+ static constexpr int lastDwarfRegNum() {
+ return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64;
+ }
static int getArch() { return REGISTERS_ARM64; }
uint64_t getSP() const { return _registers.__sp; }
@@ -2103,7 +2123,9 @@ public:
restoreSavedFloatRegisters();
restoreCoreAndJumpTo();
}
- static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM; }
+ static constexpr int lastDwarfRegNum() {
+ return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM;
+ }
static int getArch() { return REGISTERS_ARM; }
uint32_t getSP() const { return _registers.__sp; }
@@ -2603,7 +2625,9 @@ public:
void setVectorRegister(int num, v128 value);
static const char *getRegisterName(int num);
void jumpto();
- static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K; }
+ static constexpr int lastDwarfRegNum() {
+ return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K;
+ }
static int getArch() { return REGISTERS_OR1K; }
uint64_t getSP() const { return _registers.__r[1]; }
@@ -2800,7 +2824,9 @@ public:
void setVectorRegister(int num, v128 value);
static const char *getRegisterName(int num);
void jumpto();
- static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }
+ static constexpr int lastDwarfRegNum() {
+ return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS;
+ }
static int getArch() { return REGISTERS_MIPS_O32; }
uint32_t getSP() const { return _registers.__r[29]; }
@@ -2847,7 +2873,7 @@ inline bool Registers_mips_o32::validRegister(int regNum) const {
return false;
if (regNum <= UNW_MIPS_R31)
return true;
-#if __mips_isa_rev != 6
+#if __mips_isa_rev < 6
if (regNum == UNW_MIPS_HI)
return true;
if (regNum == UNW_MIPS_LO)
@@ -2881,10 +2907,12 @@ inline uint32_t Registers_mips_o32::getRegister(int regNum) const {
return _registers.__pc;
case UNW_REG_SP:
return _registers.__r[29];
+#if __mips_isa_rev < 6
case UNW_MIPS_HI:
return _registers.__hi;
case UNW_MIPS_LO:
return _registers.__lo;
+#endif
}
_LIBUNWIND_ABORT("unsupported mips_o32 register");
}
@@ -2914,11 +2942,13 @@ inline void Registers_mips_o32::setRegister(int regNum, uint32_t value) {
case UNW_REG_SP:
_registers.__r[29] = value;
return;
+#if __mips_isa_rev < 6
case UNW_MIPS_HI:
_registers.__hi = value;
return;
case UNW_MIPS_LO:
_registers.__lo = value;
+#endif
return;
}
_LIBUNWIND_ABORT("unsupported mips_o32 register");
@@ -3098,10 +3128,12 @@ inline const char *Registers_mips_o32::getRegisterName(int regNum) {
return "$f30";
case UNW_MIPS_F31:
return "$f31";
+#if __mips_isa_rev < 6
case UNW_MIPS_HI:
return "$hi";
case UNW_MIPS_LO:
return "$lo";
+#endif
default:
return "unknown register";
}
@@ -3127,7 +3159,9 @@ public:
void setVectorRegister(int num, v128 value);
static const char *getRegisterName(int num);
void jumpto();
- static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }
+ static constexpr int lastDwarfRegNum() {
+ return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS;
+ }
static int getArch() { return REGISTERS_MIPS_NEWABI; }
uint64_t getSP() const { return _registers.__r[29]; }
@@ -3169,7 +3203,7 @@ inline bool Registers_mips_newabi::validRegister(int regNum) const {
return false;
if (regNum <= UNW_MIPS_R31)
return true;
-#if __mips_isa_rev != 6
+#if __mips_isa_rev < 6
if (regNum == UNW_MIPS_HI)
return true;
if (regNum == UNW_MIPS_LO)
@@ -3188,10 +3222,12 @@ inline uint64_t Registers_mips_newabi::getRegister(int regNum) const {
return _registers.__pc;
case UNW_REG_SP:
return _registers.__r[29];
+#if __mips_isa_rev < 6
case UNW_MIPS_HI:
return _registers.__hi;
case UNW_MIPS_LO:
return _registers.__lo;
+#endif
}
_LIBUNWIND_ABORT("unsupported mips_newabi register");
}
@@ -3209,12 +3245,14 @@ inline void Registers_mips_newabi::setRegister(int regNum, uint64_t value) {
case UNW_REG_SP:
_registers.__r[29] = value;
return;
+#if __mips_isa_rev < 6
case UNW_MIPS_HI:
_registers.__hi = value;
return;
case UNW_MIPS_LO:
_registers.__lo = value;
return;
+#endif
}
_LIBUNWIND_ABORT("unsupported mips_newabi register");
}
@@ -3393,10 +3431,12 @@ inline const char *Registers_mips_newabi::getRegisterName(int regNum) {
return "$f30";
case UNW_MIPS_F31:
return "$f31";
+#if __mips_isa_rev < 6
case UNW_MIPS_HI:
return "$hi";
case UNW_MIPS_LO:
return "$lo";
+#endif
default:
return "unknown register";
}
@@ -3422,7 +3462,9 @@ public:
void setVectorRegister(int num, v128 value);
static const char *getRegisterName(int num);
void jumpto();
- static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC; }
+ static constexpr int lastDwarfRegNum() {
+ return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC;
+ }
static int getArch() { return REGISTERS_SPARC; }
uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6]; }
@@ -3606,7 +3648,7 @@ public:
void setVectorRegister(int num, v128 value);
const char *getRegisterName(int num);
void jumpto();
- static int lastDwarfRegNum() {
+ static constexpr int lastDwarfRegNum() {
return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64;
}
static int getArch() { return REGISTERS_SPARC64; }
@@ -3791,7 +3833,9 @@ public:
void setVectorRegister(int num, v128 value);
const char *getRegisterName(int num);
void jumpto();
- static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON; }
+ static constexpr int lastDwarfRegNum() {
+ return _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON;
+ }
static int getArch() { return REGISTERS_HEXAGON; }
uint32_t getSP() const { return _registers.__r[UNW_HEXAGON_R29]; }
@@ -3976,7 +4020,7 @@ typedef float fp_t;
# error "Unsupported __riscv_flen"
# endif
# else
-// This is just for supressing undeclared error of fp_t.
+// This is just for suppressing undeclared error of fp_t.
typedef double fp_t;
# endif
# else
@@ -4004,7 +4048,9 @@ public:
void setVectorRegister(int num, v128 value);
static const char *getRegisterName(int num);
void jumpto();
- static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV; }
+ static constexpr int lastDwarfRegNum() {
+ return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV;
+ }
static int getArch() { return REGISTERS_RISCV; }
reg_t getSP() const { return _registers[2]; }
@@ -4055,6 +4101,8 @@ inline bool Registers_riscv::validRegister(int regNum) const {
return true;
if (regNum < 0)
return false;
+ if (regNum == UNW_RISCV_VLENB)
+ return true;
if (regNum > UNW_RISCV_F31)
return false;
return true;
@@ -4069,6 +4117,11 @@ inline reg_t Registers_riscv::getRegister(int regNum) const {
return 0;
if ((regNum > 0) && (regNum < 32))
return _registers[regNum];
+ if (regNum == UNW_RISCV_VLENB) {
+ reg_t vlenb;
+ __asm__("csrr %0, 0xC22" : "=r"(vlenb));
+ return vlenb;
+ }
_LIBUNWIND_ABORT("unsupported riscv register");
}
@@ -4220,6 +4273,8 @@ inline const char *Registers_riscv::getRegisterName(int regNum) {
return "ft10";
case UNW_RISCV_F31:
return "ft11";
+ case UNW_RISCV_VLENB:
+ return "vlenb";
default:
return "unknown register";
}
@@ -4290,7 +4345,9 @@ public:
void setVectorRegister(int num, v128 value);
static const char *getRegisterName(int num);
void jumpto();
- static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE; }
+ static constexpr int lastDwarfRegNum() {
+ return _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE;
+ }
static int getArch() { return REGISTERS_VE; }
uint64_t getSP() const { return _registers.__s[11]; }
@@ -4712,6 +4769,560 @@ inline const char *Registers_ve::getRegisterName(int regNum) {
}
#endif // _LIBUNWIND_TARGET_VE
+#if defined(_LIBUNWIND_TARGET_S390X)
+/// Registers_s390x holds the register state of a thread in a
+/// 64-bit Linux on IBM zSystems process.
+class _LIBUNWIND_HIDDEN Registers_s390x {
+public:
+ Registers_s390x();
+ Registers_s390x(const void *registers);
+
+ bool validRegister(int num) const;
+ uint64_t getRegister(int num) const;
+ void setRegister(int num, uint64_t value);
+ 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);
+ static const char *getRegisterName(int num);
+ void jumpto();
+ static constexpr int lastDwarfRegNum() {
+ return _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X;
+ }
+ static int getArch() { return REGISTERS_S390X; }
+
+ uint64_t getSP() const { return _registers.__gpr[15]; }
+ void setSP(uint64_t value) { _registers.__gpr[15] = value; }
+ uint64_t getIP() const { return _registers.__pswa; }
+ void setIP(uint64_t value) { _registers.__pswa = value; }
+
+private:
+ struct s390x_thread_state_t {
+ uint64_t __pswm; // Problem Status Word: Mask
+ uint64_t __pswa; // Problem Status Word: Address (PC)
+ uint64_t __gpr[16]; // General Purpose Registers
+ double __fpr[16]; // Floating-Point Registers
+ };
+
+ s390x_thread_state_t _registers;
+};
+
+inline Registers_s390x::Registers_s390x(const void *registers) {
+ static_assert((check_fit<Registers_s390x, unw_context_t>::does_fit),
+ "s390x registers do not fit into unw_context_t");
+ memcpy(&_registers, static_cast<const uint8_t *>(registers),
+ sizeof(_registers));
+}
+
+inline Registers_s390x::Registers_s390x() {
+ memset(&_registers, 0, sizeof(_registers));
+}
+
+inline bool Registers_s390x::validRegister(int regNum) const {
+ switch (regNum) {
+ case UNW_S390X_PSWM:
+ case UNW_S390X_PSWA:
+ case UNW_REG_IP:
+ case UNW_REG_SP:
+ return true;
+ }
+
+ if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15)
+ return true;
+
+ return false;
+}
+
+inline uint64_t Registers_s390x::getRegister(int regNum) const {
+ if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15)
+ return _registers.__gpr[regNum - UNW_S390X_R0];
+
+ switch (regNum) {
+ case UNW_S390X_PSWM:
+ return _registers.__pswm;
+ case UNW_S390X_PSWA:
+ case UNW_REG_IP:
+ return _registers.__pswa;
+ case UNW_REG_SP:
+ return _registers.__gpr[15];
+ }
+ _LIBUNWIND_ABORT("unsupported s390x register");
+}
+
+inline void Registers_s390x::setRegister(int regNum, uint64_t value) {
+ if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15) {
+ _registers.__gpr[regNum - UNW_S390X_R0] = value;
+ return;
+ }
+
+ switch (regNum) {
+ case UNW_S390X_PSWM:
+ _registers.__pswm = value;
+ return;
+ case UNW_S390X_PSWA:
+ case UNW_REG_IP:
+ _registers.__pswa = value;
+ return;
+ case UNW_REG_SP:
+ _registers.__gpr[15] = value;
+ return;
+ }
+ _LIBUNWIND_ABORT("unsupported s390x register");
+}
+
+inline bool Registers_s390x::validFloatRegister(int regNum) const {
+ return regNum >= UNW_S390X_F0 && regNum <= UNW_S390X_F15;
+}
+
+inline double Registers_s390x::getFloatRegister(int regNum) const {
+ // NOTE: FPR DWARF register numbers are not consecutive.
+ switch (regNum) {
+ case UNW_S390X_F0:
+ return _registers.__fpr[0];
+ case UNW_S390X_F1:
+ return _registers.__fpr[1];
+ case UNW_S390X_F2:
+ return _registers.__fpr[2];
+ case UNW_S390X_F3:
+ return _registers.__fpr[3];
+ case UNW_S390X_F4:
+ return _registers.__fpr[4];
+ case UNW_S390X_F5:
+ return _registers.__fpr[5];
+ case UNW_S390X_F6:
+ return _registers.__fpr[6];
+ case UNW_S390X_F7:
+ return _registers.__fpr[7];
+ case UNW_S390X_F8:
+ return _registers.__fpr[8];
+ case UNW_S390X_F9:
+ return _registers.__fpr[9];
+ case UNW_S390X_F10:
+ return _registers.__fpr[10];
+ case UNW_S390X_F11:
+ return _registers.__fpr[11];
+ case UNW_S390X_F12:
+ return _registers.__fpr[12];
+ case UNW_S390X_F13:
+ return _registers.__fpr[13];
+ case UNW_S390X_F14:
+ return _registers.__fpr[14];
+ case UNW_S390X_F15:
+ return _registers.__fpr[15];
+ }
+ _LIBUNWIND_ABORT("unsupported s390x register");
+}
+
+inline void Registers_s390x::setFloatRegister(int regNum, double value) {
+ // NOTE: FPR DWARF register numbers are not consecutive.
+ switch (regNum) {
+ case UNW_S390X_F0:
+ _registers.__fpr[0] = value;
+ return;
+ case UNW_S390X_F1:
+ _registers.__fpr[1] = value;
+ return;
+ case UNW_S390X_F2:
+ _registers.__fpr[2] = value;
+ return;
+ case UNW_S390X_F3:
+ _registers.__fpr[3] = value;
+ return;
+ case UNW_S390X_F4:
+ _registers.__fpr[4] = value;
+ return;
+ case UNW_S390X_F5:
+ _registers.__fpr[5] = value;
+ return;
+ case UNW_S390X_F6:
+ _registers.__fpr[6] = value;
+ return;
+ case UNW_S390X_F7:
+ _registers.__fpr[7] = value;
+ return;
+ case UNW_S390X_F8:
+ _registers.__fpr[8] = value;
+ return;
+ case UNW_S390X_F9:
+ _registers.__fpr[9] = value;
+ return;
+ case UNW_S390X_F10:
+ _registers.__fpr[10] = value;
+ return;
+ case UNW_S390X_F11:
+ _registers.__fpr[11] = value;
+ return;
+ case UNW_S390X_F12:
+ _registers.__fpr[12] = value;
+ return;
+ case UNW_S390X_F13:
+ _registers.__fpr[13] = value;
+ return;
+ case UNW_S390X_F14:
+ _registers.__fpr[14] = value;
+ return;
+ case UNW_S390X_F15:
+ _registers.__fpr[15] = value;
+ return;
+ }
+ _LIBUNWIND_ABORT("unsupported s390x register");
+}
+
+inline bool Registers_s390x::validVectorRegister(int /*regNum*/) const {
+ return false;
+}
+
+inline v128 Registers_s390x::getVectorRegister(int /*regNum*/) const {
+ _LIBUNWIND_ABORT("s390x vector support not implemented");
+}
+
+inline void Registers_s390x::setVectorRegister(int /*regNum*/, v128 /*value*/) {
+ _LIBUNWIND_ABORT("s390x vector support not implemented");
+}
+
+inline const char *Registers_s390x::getRegisterName(int regNum) {
+ switch (regNum) {
+ case UNW_REG_IP:
+ return "ip";
+ case UNW_REG_SP:
+ return "sp";
+ case UNW_S390X_R0:
+ return "r0";
+ case UNW_S390X_R1:
+ return "r1";
+ case UNW_S390X_R2:
+ return "r2";
+ case UNW_S390X_R3:
+ return "r3";
+ case UNW_S390X_R4:
+ return "r4";
+ case UNW_S390X_R5:
+ return "r5";
+ case UNW_S390X_R6:
+ return "r6";
+ case UNW_S390X_R7:
+ return "r7";
+ case UNW_S390X_R8:
+ return "r8";
+ case UNW_S390X_R9:
+ return "r9";
+ case UNW_S390X_R10:
+ return "r10";
+ case UNW_S390X_R11:
+ return "r11";
+ case UNW_S390X_R12:
+ return "r12";
+ case UNW_S390X_R13:
+ return "r13";
+ case UNW_S390X_R14:
+ return "r14";
+ case UNW_S390X_R15:
+ return "r15";
+ case UNW_S390X_F0:
+ return "f0";
+ case UNW_S390X_F1:
+ return "f1";
+ case UNW_S390X_F2:
+ return "f2";
+ case UNW_S390X_F3:
+ return "f3";
+ case UNW_S390X_F4:
+ return "f4";
+ case UNW_S390X_F5:
+ return "f5";
+ case UNW_S390X_F6:
+ return "f6";
+ case UNW_S390X_F7:
+ return "f7";
+ case UNW_S390X_F8:
+ return "f8";
+ case UNW_S390X_F9:
+ return "f9";
+ case UNW_S390X_F10:
+ return "f10";
+ case UNW_S390X_F11:
+ return "f11";
+ case UNW_S390X_F12:
+ return "f12";
+ case UNW_S390X_F13:
+ return "f13";
+ case UNW_S390X_F14:
+ return "f14";
+ case UNW_S390X_F15:
+ return "f15";
+ }
+ return "unknown register";
+}
+#endif // _LIBUNWIND_TARGET_S390X
+
+#if defined(_LIBUNWIND_TARGET_LOONGARCH)
+/// Registers_loongarch holds the register state of a thread in a 64-bit
+/// LoongArch process.
+class _LIBUNWIND_HIDDEN Registers_loongarch {
+public:
+ Registers_loongarch();
+ Registers_loongarch(const void *registers);
+
+ bool validRegister(int num) const;
+ uint64_t getRegister(int num) const;
+ void setRegister(int num, uint64_t value);
+ 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);
+ static const char *getRegisterName(int num);
+ void jumpto();
+ static constexpr int lastDwarfRegNum() {
+ return _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH;
+ }
+ static int getArch() { return REGISTERS_LOONGARCH; }
+
+ uint64_t getSP() const { return _registers.__r[3]; }
+ void setSP(uint64_t value) { _registers.__r[3] = value; }
+ uint64_t getIP() const { return _registers.__pc; }
+ void setIP(uint64_t value) { _registers.__pc = value; }
+
+private:
+ struct loongarch_thread_state_t {
+ uint64_t __r[32];
+ uint64_t __pc;
+ };
+
+ loongarch_thread_state_t _registers;
+#if __loongarch_frlen == 64
+ double _floats[32];
+#endif
+};
+
+inline Registers_loongarch::Registers_loongarch(const void *registers) {
+ static_assert((check_fit<Registers_loongarch, unw_context_t>::does_fit),
+ "loongarch registers do not fit into unw_context_t");
+ memcpy(&_registers, registers, sizeof(_registers));
+ static_assert(sizeof(_registers) == 0x108,
+ "expected float registers to be at offset 264");
+#if __loongarch_frlen == 64
+ memcpy(_floats, static_cast<const uint8_t *>(registers) + sizeof(_registers),
+ sizeof(_floats));
+#endif
+}
+
+inline Registers_loongarch::Registers_loongarch() {
+ memset(&_registers, 0, sizeof(_registers));
+#if __loongarch_frlen == 64
+ memset(&_floats, 0, sizeof(_floats));
+#endif
+}
+
+inline bool Registers_loongarch::validRegister(int regNum) const {
+ if (regNum == UNW_REG_IP || regNum == UNW_REG_SP)
+ return true;
+ if (regNum < 0 || regNum > UNW_LOONGARCH_F31)
+ return false;
+ return true;
+}
+
+inline uint64_t Registers_loongarch::getRegister(int regNum) const {
+ if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31)
+ return _registers.__r[regNum - UNW_LOONGARCH_R0];
+
+ if (regNum == UNW_REG_IP)
+ return _registers.__pc;
+ if (regNum == UNW_REG_SP)
+ return _registers.__r[3];
+ _LIBUNWIND_ABORT("unsupported loongarch register");
+}
+
+inline void Registers_loongarch::setRegister(int regNum, uint64_t value) {
+ if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31)
+ _registers.__r[regNum - UNW_LOONGARCH_R0] = value;
+ else if (regNum == UNW_REG_IP)
+ _registers.__pc = value;
+ else if (regNum == UNW_REG_SP)
+ _registers.__r[3] = value;
+ else
+ _LIBUNWIND_ABORT("unsupported loongarch register");
+}
+
+inline const char *Registers_loongarch::getRegisterName(int regNum) {
+ switch (regNum) {
+ case UNW_REG_IP:
+ return "$pc";
+ case UNW_REG_SP:
+ return "$sp";
+ case UNW_LOONGARCH_R0:
+ return "$r0";
+ case UNW_LOONGARCH_R1:
+ return "$r1";
+ case UNW_LOONGARCH_R2:
+ return "$r2";
+ case UNW_LOONGARCH_R3:
+ return "$r3";
+ case UNW_LOONGARCH_R4:
+ return "$r4";
+ case UNW_LOONGARCH_R5:
+ return "$r5";
+ case UNW_LOONGARCH_R6:
+ return "$r6";
+ case UNW_LOONGARCH_R7:
+ return "$r7";
+ case UNW_LOONGARCH_R8:
+ return "$r8";
+ case UNW_LOONGARCH_R9:
+ return "$r9";
+ case UNW_LOONGARCH_R10:
+ return "$r10";
+ case UNW_LOONGARCH_R11:
+ return "$r11";
+ case UNW_LOONGARCH_R12:
+ return "$r12";
+ case UNW_LOONGARCH_R13:
+ return "$r13";
+ case UNW_LOONGARCH_R14:
+ return "$r14";
+ case UNW_LOONGARCH_R15:
+ return "$r15";
+ case UNW_LOONGARCH_R16:
+ return "$r16";
+ case UNW_LOONGARCH_R17:
+ return "$r17";
+ case UNW_LOONGARCH_R18:
+ return "$r18";
+ case UNW_LOONGARCH_R19:
+ return "$r19";
+ case UNW_LOONGARCH_R20:
+ return "$r20";
+ case UNW_LOONGARCH_R21:
+ return "$r21";
+ case UNW_LOONGARCH_R22:
+ return "$r22";
+ case UNW_LOONGARCH_R23:
+ return "$r23";
+ case UNW_LOONGARCH_R24:
+ return "$r24";
+ case UNW_LOONGARCH_R25:
+ return "$r25";
+ case UNW_LOONGARCH_R26:
+ return "$r26";
+ case UNW_LOONGARCH_R27:
+ return "$r27";
+ case UNW_LOONGARCH_R28:
+ return "$r28";
+ case UNW_LOONGARCH_R29:
+ return "$r29";
+ case UNW_LOONGARCH_R30:
+ return "$r30";
+ case UNW_LOONGARCH_R31:
+ return "$r31";
+ case UNW_LOONGARCH_F0:
+ return "$f0";
+ case UNW_LOONGARCH_F1:
+ return "$f1";
+ case UNW_LOONGARCH_F2:
+ return "$f2";
+ case UNW_LOONGARCH_F3:
+ return "$f3";
+ case UNW_LOONGARCH_F4:
+ return "$f4";
+ case UNW_LOONGARCH_F5:
+ return "$f5";
+ case UNW_LOONGARCH_F6:
+ return "$f6";
+ case UNW_LOONGARCH_F7:
+ return "$f7";
+ case UNW_LOONGARCH_F8:
+ return "$f8";
+ case UNW_LOONGARCH_F9:
+ return "$f9";
+ case UNW_LOONGARCH_F10:
+ return "$f10";
+ case UNW_LOONGARCH_F11:
+ return "$f11";
+ case UNW_LOONGARCH_F12:
+ return "$f12";
+ case UNW_LOONGARCH_F13:
+ return "$f13";
+ case UNW_LOONGARCH_F14:
+ return "$f14";
+ case UNW_LOONGARCH_F15:
+ return "$f15";
+ case UNW_LOONGARCH_F16:
+ return "$f16";
+ case UNW_LOONGARCH_F17:
+ return "$f17";
+ case UNW_LOONGARCH_F18:
+ return "$f18";
+ case UNW_LOONGARCH_F19:
+ return "$f19";
+ case UNW_LOONGARCH_F20:
+ return "$f20";
+ case UNW_LOONGARCH_F21:
+ return "$f21";
+ case UNW_LOONGARCH_F22:
+ return "$f22";
+ case UNW_LOONGARCH_F23:
+ return "$f23";
+ case UNW_LOONGARCH_F24:
+ return "$f24";
+ case UNW_LOONGARCH_F25:
+ return "$f25";
+ case UNW_LOONGARCH_F26:
+ return "$f26";
+ case UNW_LOONGARCH_F27:
+ return "$f27";
+ case UNW_LOONGARCH_F28:
+ return "$f28";
+ case UNW_LOONGARCH_F29:
+ return "$f29";
+ case UNW_LOONGARCH_F30:
+ return "$f30";
+ case UNW_LOONGARCH_F31:
+ return "$f31";
+ default:
+ return "unknown register";
+ }
+}
+
+inline bool Registers_loongarch::validFloatRegister(int regNum) const {
+ if (regNum < UNW_LOONGARCH_F0 || regNum > UNW_LOONGARCH_F31)
+ return false;
+ return true;
+}
+
+inline double Registers_loongarch::getFloatRegister(int regNum) const {
+#if __loongarch_frlen == 64
+ assert(validFloatRegister(regNum));
+ return _floats[regNum - UNW_LOONGARCH_F0];
+#else
+ _LIBUNWIND_ABORT("libunwind not built with float support");
+#endif
+}
+
+inline void Registers_loongarch::setFloatRegister(int regNum, double value) {
+#if __loongarch_frlen == 64
+ assert(validFloatRegister(regNum));
+ _floats[regNum - UNW_LOONGARCH_F0] = value;
+#else
+ _LIBUNWIND_ABORT("libunwind not built with float support");
+#endif
+}
+
+inline bool Registers_loongarch::validVectorRegister(int) const {
+ return false;
+}
+
+inline v128 Registers_loongarch::getVectorRegister(int) const {
+ _LIBUNWIND_ABORT("loongarch vector support not implemented");
+}
+
+inline void Registers_loongarch::setVectorRegister(int, v128) {
+ _LIBUNWIND_ABORT("loongarch vector support not implemented");
+}
+#endif //_LIBUNWIND_TARGET_LOONGARCH
+
} // namespace libunwind
#endif // __REGISTERS_HPP__
diff --git a/contrib/libs/libunwind/src/Unwind-EHABI.cpp b/contrib/libs/libunwind/src/Unwind-EHABI.cpp
index 2b21f0a3dd..af5daa9f6a 100644
--- a/contrib/libs/libunwind/src/Unwind-EHABI.cpp
+++ b/contrib/libs/libunwind/src/Unwind-EHABI.cpp
@@ -235,7 +235,7 @@ decode_eht_entry(const uint32_t* data, size_t* off, size_t* len) {
} else {
// 6.3: ARM Compact Model
//
- // EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeded
+ // EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeed
// by format:
Descriptor::Format format =
static_cast<Descriptor::Format>((*data & 0x0f000000) >> 24);
@@ -432,10 +432,11 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data,
uint32_t sp;
uint32_t pac;
_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);
- _Unwind_VRS_Get(context, _UVRSC_PSEUDO, UNW_ARM_RA_AUTH_CODE,
- _UVRSD_UINT32, &pac);
+ _Unwind_VRS_Get(context, _UVRSC_PSEUDO, 0, _UVRSD_UINT32, &pac);
__asm__ __volatile__("autg %0, %1, %2" : : "r"(pac), "r"(lr), "r"(sp) :);
}
+#else
+ (void)hasReturnAddrAuthCode;
#endif
_Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr);
}
@@ -708,7 +709,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
// Update info about this frame.
unw_proc_info_t frameInfo;
if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_step "
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_get_proc_info "
"failed => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
@@ -844,7 +845,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)
@@ -884,8 +885,11 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
return result;
}
-[[maybe_unused]] static uint64_t ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation,
- void* valuep) {
+// Only used in _LIBUNWIND_TRACE_API, which is a no-op when assertions are
+// disabled.
+[[gnu::unused]] static uint64_t
+ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation,
+ const void *valuep) {
uint64_t value = 0;
switch (representation) {
case _UVRSD_UINT32:
@@ -1136,8 +1140,7 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
}
uint32_t pac = *sp++;
_Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);
- return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_RA_AUTH_CODE,
- _UVRSD_UINT32, &pac);
+ return _Unwind_VRS_Set(context, _UVRSC_PSEUDO, 0, _UVRSD_UINT32, &pac);
}
}
_LIBUNWIND_ABORT("unsupported register class");
@@ -1191,8 +1194,9 @@ _Unwind_DeleteException(_Unwind_Exception *exception_object) {
}
extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code
-__gnu_unwind_frame(_Unwind_Exception * /* exception_object */,
+__gnu_unwind_frame(_Unwind_Exception *exception_object,
struct _Unwind_Context *context) {
+ (void)exception_object;
unw_cursor_t *cursor = (unw_cursor_t *)context;
switch (__unw_step(cursor)) {
case UNW_STEP_SUCCESS:
diff --git a/contrib/libs/libunwind/src/Unwind-seh.cpp b/contrib/libs/libunwind/src/Unwind-seh.cpp
index f00bc4721b..b2bb119ed6 100644
--- a/contrib/libs/libunwind/src/Unwind-seh.cpp
+++ b/contrib/libs/libunwind/src/Unwind-seh.cpp
@@ -104,7 +104,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,
if (!ctx) {
__unw_init_seh(&cursor, disp->ContextRecord);
__unw_seh_set_disp_ctx(&cursor, disp);
- __unw_set_reg(&cursor, UNW_REG_IP, disp->ControlPc - 1);
+ __unw_set_reg(&cursor, UNW_REG_IP, disp->ControlPc);
ctx = (struct _Unwind_Context *)&cursor;
if (!IS_UNWINDING(ms_exc->ExceptionFlags)) {
@@ -137,7 +137,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,
// If we were called by __libunwind_seh_personality(), indicate that
// a handler was found; otherwise, initiate phase 2 by unwinding.
if (ours && ms_exc->NumberParameters > 1)
- return 4 /* ExecptionExecuteHandler in mingw */;
+ return 4 /* ExceptionExecuteHandler in mingw */;
// This should never happen in phase 2.
if (IS_UNWINDING(ms_exc->ExceptionFlags))
_LIBUNWIND_ABORT("Personality indicated exception handler in phase 2!");
@@ -155,7 +155,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,
// a handler was found; otherwise, it's time to initiate a collided
// unwind to the target.
if (ours && !IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1)
- return 4 /* ExecptionExecuteHandler in mingw */;
+ return 4 /* ExceptionExecuteHandler in mingw */;
// This should never happen in phase 1.
if (!IS_UNWINDING(ms_exc->ExceptionFlags))
_LIBUNWIND_ABORT("Personality installed context during phase 1!");
@@ -212,11 +212,20 @@ __libunwind_seh_personality(int version, _Unwind_Action state,
ms_exc.ExceptionInformation[2] = state;
DISPATCHER_CONTEXT *disp_ctx =
__unw_seh_get_disp_ctx((unw_cursor_t *)context);
+ _LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() calling "
+ "LanguageHandler %p(%p, %p, %p, %p)",
+ (void *)disp_ctx->LanguageHandler, (void *)&ms_exc,
+ (void *)disp_ctx->EstablisherFrame,
+ (void *)disp_ctx->ContextRecord, (void *)disp_ctx);
EXCEPTION_DISPOSITION ms_act = disp_ctx->LanguageHandler(&ms_exc,
(PVOID)disp_ctx->EstablisherFrame,
disp_ctx->ContextRecord,
disp_ctx);
+ _LIBUNWIND_TRACE_UNWINDING("__libunwind_seh_personality() LanguageHandler "
+ "returned %d",
+ (int)ms_act);
switch (ms_act) {
+ case ExceptionContinueExecution: return _URC_END_OF_STACK;
case ExceptionContinueSearch: return _URC_CONTINUE_UNWIND;
case 4 /*ExceptionExecuteHandler*/:
return phase2 ? _URC_INSTALL_CONTEXT : _URC_HANDLER_FOUND;
@@ -238,7 +247,7 @@ unwind_phase2_forced(unw_context_t *uc,
// Update info about this frame.
unw_proc_info_t frameInfo;
if (__unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_step "
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_get_proc_info "
"failed => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
@@ -255,8 +264,8 @@ unwind_phase2_forced(unw_context_t *uc,
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIx64
- ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64,
+ "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIxPTR
+ ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,
(void *)exception_object, frameInfo.start_ip, functionName,
frameInfo.lsda, frameInfo.handler);
}
@@ -304,6 +313,12 @@ unwind_phase2_forced(unw_context_t *uc,
// We may get control back if landing pad calls _Unwind_Resume().
__unw_resume(&cursor2);
break;
+ case _URC_END_OF_STACK:
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
+ "personality returned "
+ "_URC_END_OF_STACK",
+ (void *)exception_object);
+ break;
default:
// Personality routine returned an unknown result code.
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
@@ -312,6 +327,8 @@ unwind_phase2_forced(unw_context_t *uc,
(void *)exception_object, personalityResult);
return _URC_FATAL_PHASE2_ERROR;
}
+ if (personalityResult == _URC_END_OF_STACK)
+ break;
}
}
@@ -354,7 +371,7 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) {
/// may force a jump to a landing pad in that function; the landing
/// pad code may then call \c _Unwind_Resume() to continue with the
/// unwinding. Note: the call to \c _Unwind_Resume() is from compiler
-/// geneated user code. All other \c _Unwind_* routines are called
+/// generated user code. All other \c _Unwind_* routines are called
/// by the C++ runtime \c __cxa_* routines.
///
/// Note: re-throwing an exception (as opposed to continuing the unwind)
diff --git a/contrib/libs/libunwind/src/Unwind-sjlj.c b/contrib/libs/libunwind/src/Unwind-sjlj.c
index d487995bb7..7e8faf098f 100644
--- a/contrib/libs/libunwind/src/Unwind-sjlj.c
+++ b/contrib/libs/libunwind/src/Unwind-sjlj.c
@@ -33,7 +33,7 @@ struct _Unwind_FunctionContext {
struct _Unwind_FunctionContext *prev;
#if defined(__ve__)
- // VE requires to store 64 bit pointers in the buffer for SjLj execption.
+ // VE requires to store 64 bit pointers in the buffer for SjLj exception.
// We expand the size of values defined here. This size must be matched
// to the size returned by TargetMachine::getSjLjDataSize().
@@ -82,7 +82,8 @@ struct _Unwind_FunctionContext {
static _LIBUNWIND_THREAD_LOCAL struct _Unwind_FunctionContext *stack = NULL;
#endif
-static struct _Unwind_FunctionContext *__Unwind_SjLj_GetTopOfFunctionStack() {
+static struct _Unwind_FunctionContext *
+__Unwind_SjLj_GetTopOfFunctionStack(void) {
#if defined(__APPLE__)
return _pthread_getspecific_direct(__PTK_LIBC_DYLD_Unwind_SjLj_Key);
#else
@@ -357,7 +358,7 @@ _Unwind_SjLj_RaiseException(struct _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.
///
/// Re-throwing an exception is implemented by having the code call
@@ -394,7 +395,7 @@ _Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *exception_object) {
// std::terminate()
}
- // Call through to _Unwind_Resume() which distiguishes between forced and
+ // Call through to _Unwind_Resume() which distinguishes between forced and
// regular exceptions.
_Unwind_SjLj_Resume(exception_object);
_LIBUNWIND_ABORT("__Unwind_SjLj_Resume_or_Rethrow() called "
@@ -426,7 +427,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetGR(struct _Unwind_Context *context,
/// Called by personality handler during phase 2 to alter register values.
_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
uintptr_t new_value) {
- _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%" PRIuPTR
+ _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, reg=%d, value=0x%" PRIxPTR
")",
(void *)context, index, new_value);
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
@@ -437,7 +438,7 @@ _LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
/// Called by personality handler during phase 2 to get instruction pointer.
_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
- _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIu32,
+ _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => 0x%" PRIxPTR,
(void *)context, ufc->resumeLocation + 1);
return ufc->resumeLocation + 1;
}
@@ -450,7 +451,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
int *ipBefore) {
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
*ipBefore = 0;
- _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%" PRIu32,
+ _LIBUNWIND_TRACE_API("_Unwind_GetIPInfo(context=%p, %p) => 0x%" PRIxPTR,
(void *)context, (void *)ipBefore,
ufc->resumeLocation + 1);
return ufc->resumeLocation + 1;
@@ -460,7 +461,7 @@ _LIBUNWIND_EXPORT uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context,
/// Called by personality handler during phase 2 to alter instruction pointer.
_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
uintptr_t new_value) {
- _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%" PRIuPTR ")",
+ _LIBUNWIND_TRACE_API("_Unwind_SetIP(context=%p, value=0x%" PRIxPTR ")",
(void *)context, new_value);
_Unwind_FunctionContext_t ufc = (_Unwind_FunctionContext_t) context;
ufc->resumeLocation = new_value - 1;
diff --git a/contrib/libs/libunwind/src/Unwind-wasm.c b/contrib/libs/libunwind/src/Unwind-wasm.c
new file mode 100644
index 0000000000..f7f39d38b5
--- /dev/null
+++ b/contrib/libs/libunwind/src/Unwind-wasm.c
@@ -0,0 +1,123 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//
+// Implements Wasm exception handling proposal
+// (https://github.com/WebAssembly/exception-handling) based C++ exceptions
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdbool.h>
+
+#include "config.h"
+
+#ifdef __USING_WASM_EXCEPTIONS__
+
+#include "unwind.h"
+#include <threads.h>
+
+_Unwind_Reason_Code __gxx_personality_wasm0(int version, _Unwind_Action actions,
+ uint64_t exceptionClass,
+ _Unwind_Exception *unwind_exception,
+ _Unwind_Context *context);
+
+struct _Unwind_LandingPadContext {
+ // Input information to personality function
+ uintptr_t lpad_index; // landing pad index
+ uintptr_t lsda; // LSDA address
+
+ // Output information computed by personality function
+ uintptr_t selector; // selector value
+};
+
+// Communication channel between compiler-generated user code and personality
+// function
+thread_local struct _Unwind_LandingPadContext __wasm_lpad_context;
+
+/// Calls to this function is in landing pads in compiler-generated user code.
+/// In other EH schemes, stack unwinding is done by libunwind library, which
+/// calls the personality function for each each frame it lands. On the other
+/// hand, WebAssembly stack unwinding process is performed by a VM, and the
+/// personality function cannot be called from there. So the compiler inserts
+/// a call to this function in landing pads in the user code, which in turn
+/// calls the personality function.
+_Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) {
+ struct _Unwind_Exception *exception_object =
+ (struct _Unwind_Exception *)exception_ptr;
+ _LIBUNWIND_TRACE_API("_Unwind_CallPersonality(exception_object=%p)",
+ (void *)exception_object);
+
+ // Reset the selector.
+ __wasm_lpad_context.selector = 0;
+
+ // Call personality function. Wasm does not have two-phase unwinding, so we
+ // only do the cleanup phase.
+ return __gxx_personality_wasm0(
+ 1, _UA_SEARCH_PHASE, exception_object->exception_class, exception_object,
+ (struct _Unwind_Context *)&__wasm_lpad_context);
+}
+
+/// Called by __cxa_throw.
+_LIBUNWIND_EXPORT _Unwind_Reason_Code
+_Unwind_RaiseException(_Unwind_Exception *exception_object) {
+ _LIBUNWIND_TRACE_API("_Unwind_RaiseException(exception_object=%p)",
+ (void *)exception_object);
+ // Use Wasm EH's 'throw' instruction.
+ __builtin_wasm_throw(0, exception_object);
+}
+
+/// Called by __cxa_end_catch.
+_LIBUNWIND_EXPORT void
+_Unwind_DeleteException(_Unwind_Exception *exception_object) {
+ _LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
+ (void *)(exception_object));
+ if (exception_object->exception_cleanup != NULL)
+ (*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
+ exception_object);
+}
+
+/// Called by personality handler to alter register values.
+_LIBUNWIND_EXPORT void _Unwind_SetGR(struct _Unwind_Context *context, int index,
+ uintptr_t value) {
+ _LIBUNWIND_TRACE_API("_Unwind_SetGR(context=%p, index=%d, value=%lu)",
+ (void *)context, index, value);
+ // We only use this function to set __wasm_lpad_context.selector field, which
+ // is index 1 in the personality function.
+ if (index == 1)
+ ((struct _Unwind_LandingPadContext *)context)->selector = value;
+}
+
+/// Called by personality handler to get instruction pointer.
+_LIBUNWIND_EXPORT uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
+ // The result will be used as an 1-based index after decrementing 1, so we
+ // increment 2 here
+ uintptr_t result =
+ ((struct _Unwind_LandingPadContext *)context)->lpad_index + 2;
+ _LIBUNWIND_TRACE_API("_Unwind_GetIP(context=%p) => %lu", (void *)context,
+ result);
+ return result;
+}
+
+/// Not used in Wasm.
+_LIBUNWIND_EXPORT void _Unwind_SetIP(struct _Unwind_Context *context,
+ uintptr_t value) {}
+
+/// Called by personality handler to get LSDA for current frame.
+_LIBUNWIND_EXPORT uintptr_t
+_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
+ uintptr_t result = ((struct _Unwind_LandingPadContext *)context)->lsda;
+ _LIBUNWIND_TRACE_API("_Unwind_GetLanguageSpecificData(context=%p) => 0x%lx",
+ (void *)context, result);
+ return result;
+}
+
+/// Not used in Wasm.
+_LIBUNWIND_EXPORT uintptr_t
+_Unwind_GetRegionStart(struct _Unwind_Context *context) {
+ return 0;
+}
+
+#endif // defined(__USING_WASM_EXCEPTIONS__)
diff --git a/contrib/libs/libunwind/src/UnwindCursor.hpp b/contrib/libs/libunwind/src/UnwindCursor.hpp
index 1ca842f33a..e251e13520 100644
--- a/contrib/libs/libunwind/src/UnwindCursor.hpp
+++ b/contrib/libs/libunwind/src/UnwindCursor.hpp
@@ -24,6 +24,33 @@
#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif
+#ifdef _AIX
+#include <dlfcn.h>
+#error #include <sys/debug.h>
+#error #include <sys/pseg.h>
+#endif
+
+#if defined(_LIBUNWIND_TARGET_LINUX) && \
+ (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_RISCV) || \
+ defined(_LIBUNWIND_TARGET_S390X))
+#include <errno.h>
+#include <signal.h>
+#include <sys/syscall.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1
+#endif
+
+#include "AddressSpace.hpp"
+#include "CompactUnwinder.hpp"
+#include "config.h"
+#include "DwarfInstructions.hpp"
+#include "EHHeaderParser.hpp"
+#include "libunwind.h"
+#include "libunwind_ext.h"
+#include "Registers.hpp"
+#include "RWMutex.hpp"
+#include "Unwind-EHABI.h"
#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
// Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and
@@ -62,18 +89,6 @@ extern "C" _Unwind_Reason_Code __libunwind_seh_personality(
#endif
-#include "config.h"
-
-#include "AddressSpace.hpp"
-#include "CompactUnwinder.hpp"
-#include "config.h"
-#include "DwarfInstructions.hpp"
-#include "EHHeaderParser.hpp"
-#include "libunwind.h"
-#include "Registers.hpp"
-#include "RWMutex.hpp"
-#include "Unwind-EHABI.h"
-
namespace libunwind {
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
@@ -430,7 +445,7 @@ public:
virtual void setFloatReg(int, unw_fpreg_t) {
_LIBUNWIND_ABORT("setFloatReg not implemented");
}
- virtual int step() { _LIBUNWIND_ABORT("step not implemented"); }
+ virtual int step(bool = false) { _LIBUNWIND_ABORT("step not implemented"); }
virtual void getInfo(unw_proc_info_t *) {
_LIBUNWIND_ABORT("getInfo not implemented");
}
@@ -451,6 +466,12 @@ public:
virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); }
#endif
+#ifdef _AIX
+ virtual uintptr_t getDataRelBase() {
+ _LIBUNWIND_ABORT("getDataRelBase not implemented");
+ }
+#endif
+
#if defined(_LIBUNWIND_USE_CET)
virtual void *get_registers() {
_LIBUNWIND_ABORT("get_registers not implemented");
@@ -476,7 +497,7 @@ public:
virtual bool validFloatReg(int);
virtual unw_fpreg_t getFloatReg(int);
virtual void setFloatReg(int, unw_fpreg_t);
- virtual int step();
+ virtual int step(bool = false);
virtual void getInfo(unw_proc_info_t *);
virtual void jumpto();
virtual bool isSignalFrame();
@@ -488,10 +509,17 @@ public:
#endif
DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; }
- void setDispatcherContext(DISPATCHER_CONTEXT *disp) { _dispContext = *disp; }
+ void setDispatcherContext(DISPATCHER_CONTEXT *disp) {
+ _dispContext = *disp;
+ _info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);
+ if (_dispContext.LanguageHandler) {
+ _info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
+ } else
+ _info.handler = 0;
+ }
// libunwind does not and should not depend on C++ library which means that we
- // need our own defition of inline placement new.
+ // need our own definition of inline placement new.
static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }
private:
@@ -499,6 +527,14 @@ private:
pint_t getLastPC() const { return _dispContext.ControlPc; }
void setLastPC(pint_t pc) { _dispContext.ControlPc = pc; }
RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {
+#ifdef __arm__
+ // Remove the thumb bit; FunctionEntry ranges don't include the thumb bit.
+ pc &= ~1U;
+#endif
+ // If pc points exactly at the end of the range, we might resolve the
+ // next function instead. Decrement pc by 1 to fit inside the current
+ // function.
+ pc -= 1;
_dispContext.FunctionEntry = RtlLookupFunctionEntry(pc,
&_dispContext.ImageBase,
_dispContext.HistoryTable);
@@ -542,10 +578,12 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
"UnwindCursor<> requires more alignment than unw_cursor_t");
memset(&_info, 0, sizeof(_info));
memset(&_histTable, 0, sizeof(_histTable));
+ memset(&_dispContext, 0, sizeof(_dispContext));
_dispContext.ContextRecord = &_msContext;
_dispContext.HistoryTable = &_histTable;
// Initialize MS context from ours.
R r(context);
+ RtlCaptureContext(&_msContext);
_msContext.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_FLOATING_POINT;
#if defined(_LIBUNWIND_TARGET_X86_64)
_msContext.Rax = r.getRegister(UNW_X86_64_RAX);
@@ -643,6 +681,7 @@ UnwindCursor<A, R>::UnwindCursor(CONTEXT *context, A &as)
"UnwindCursor<> does not fit in unw_cursor_t");
memset(&_info, 0, sizeof(_info));
memset(&_histTable, 0, sizeof(_histTable));
+ memset(&_dispContext, 0, sizeof(_dispContext));
_dispContext.ContextRecord = &_msContext;
_dispContext.HistoryTable = &_histTable;
_msContext = *context;
@@ -653,7 +692,7 @@ template <typename A, typename R>
bool UnwindCursor<A, R>::validReg(int regNum) {
if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) return true;
#if defined(_LIBUNWIND_TARGET_X86_64)
- if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_R15) return true;
+ if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_RIP) return true;
#elif defined(_LIBUNWIND_TARGET_ARM)
if ((regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) ||
regNum == UNW_ARM_RA_AUTH_CODE)
@@ -668,6 +707,7 @@ template <typename A, typename R>
unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
switch (regNum) {
#if defined(_LIBUNWIND_TARGET_X86_64)
+ case UNW_X86_64_RIP:
case UNW_REG_IP: return _msContext.Rip;
case UNW_X86_64_RAX: return _msContext.Rax;
case UNW_X86_64_RDX: return _msContext.Rdx;
@@ -718,6 +758,7 @@ template <typename A, typename R>
void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
switch (regNum) {
#if defined(_LIBUNWIND_TARGET_X86_64)
+ case UNW_X86_64_RIP:
case UNW_REG_IP: _msContext.Rip = value; break;
case UNW_X86_64_RAX: _msContext.Rax = value; break;
case UNW_X86_64_RDX: _msContext.Rdx = value; break;
@@ -844,7 +885,7 @@ void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
uint32_t w;
float f;
} d;
- d.f = value;
+ d.f = (float)value;
_msContext.S[regNum - UNW_ARM_S0] = d.w;
}
if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {
@@ -899,7 +940,7 @@ public:
virtual bool validFloatReg(int);
virtual unw_fpreg_t getFloatReg(int);
virtual void setFloatReg(int, unw_fpreg_t);
- virtual int step();
+ virtual int step(bool stage2 = false);
virtual void getInfo(unw_proc_info_t *);
virtual void jumpto();
virtual bool isSignalFrame();
@@ -910,11 +951,16 @@ public:
virtual void saveVFPAsX();
#endif
+#ifdef _AIX
+ virtual uintptr_t getDataRelBase();
+#endif
+
#if defined(_LIBUNWIND_USE_CET)
virtual void *get_registers() { return &_registers; }
#endif
+
// libunwind does not and should not depend on C++ library which means that we
- // need our own defition of inline placement new.
+ // need our own definition of inline placement new.
static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }
private:
@@ -937,7 +983,7 @@ private:
}
#endif
-#if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64)
+#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
bool setInfoForSigReturn() {
R dummy;
return setInfoForSigReturn(dummy);
@@ -946,8 +992,19 @@ private:
R dummy;
return stepThroughSigReturn(dummy);
}
+ bool isReadableAddr(const pint_t addr) const;
+#if defined(_LIBUNWIND_TARGET_AARCH64)
bool setInfoForSigReturn(Registers_arm64 &);
int stepThroughSigReturn(Registers_arm64 &);
+#endif
+#if defined(_LIBUNWIND_TARGET_RISCV)
+ bool setInfoForSigReturn(Registers_riscv &);
+ int stepThroughSigReturn(Registers_riscv &);
+#endif
+#if defined(_LIBUNWIND_TARGET_S390X)
+ bool setInfoForSigReturn(Registers_s390x &);
+ int stepThroughSigReturn(Registers_s390x &);
+#endif
template <typename Registers> bool setInfoForSigReturn(Registers &) {
return false;
}
@@ -962,22 +1019,21 @@ private:
pint_t pc, uintptr_t dso_base);
bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections &sects,
uint32_t fdeSectionOffsetHint=0);
- int stepWithDwarfFDE() {
- return DwarfInstructions<A, R>::stepWithDwarf(_addressSpace,
- (pint_t)this->getReg(UNW_REG_IP),
- (pint_t)_info.unwind_info,
- _registers, _isSignalFrame);
+ int stepWithDwarfFDE(bool stage2) {
+ return DwarfInstructions<A, R>::stepWithDwarf(
+ _addressSpace, (pint_t)this->getReg(UNW_REG_IP),
+ (pint_t)_info.unwind_info, _registers, _isSignalFrame, stage2);
}
#endif
#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
bool getInfoFromCompactEncodingSection(pint_t pc,
const UnwindInfoSections &sects);
- int stepWithCompactEncoding() {
- #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
+ int stepWithCompactEncoding(bool stage2 = false) {
+#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
if ( compactSaysUseDwarf() )
- return stepWithDwarfFDE();
- #endif
+ return stepWithDwarfFDE(stage2);
+#endif
R dummy;
return stepWithCompactEncoding(dummy);
}
@@ -1028,6 +1084,10 @@ private:
}
#endif
+#if defined(_LIBUNWIND_TARGET_LOONGARCH)
+ int stepWithCompactEncoding(Registers_loongarch &) { return UNW_EINVAL; }
+#endif
+
#if defined(_LIBUNWIND_TARGET_SPARC)
int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; }
#endif
@@ -1104,6 +1164,12 @@ private:
}
#endif
+#if defined(_LIBUNWIND_TARGET_LOONGARCH)
+ bool compactSaysUseDwarf(Registers_loongarch &, uint32_t *) const {
+ return true;
+ }
+#endif
+
#if defined(_LIBUNWIND_TARGET_SPARC)
bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; }
#endif
@@ -1188,6 +1254,12 @@ private:
}
#endif
+#if defined(_LIBUNWIND_TARGET_LOONGARCH)
+ compact_unwind_encoding_t dwarfEncoding(Registers_loongarch &) const {
+ return 0;
+ }
+#endif
+
#if defined(_LIBUNWIND_TARGET_SPARC)
compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; }
#endif
@@ -1204,6 +1276,12 @@ private:
}
#endif
+#if defined (_LIBUNWIND_TARGET_S390X)
+ compact_unwind_encoding_t dwarfEncoding(Registers_s390x &) const {
+ return 0;
+ }
+#endif
+
#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
@@ -1220,13 +1298,23 @@ private:
int stepWithSEHData() { /* FIXME: Implement */ return 0; }
#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
+#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
+ bool getInfoFromTBTable(pint_t pc, R &registers);
+ int stepWithTBTable(pint_t pc, tbtable *TBTable, R &registers,
+ bool &isSignalFrame);
+ int stepWithTBTableData() {
+ return stepWithTBTable(reinterpret_cast<pint_t>(this->getReg(UNW_REG_IP)),
+ reinterpret_cast<tbtable *>(_info.unwind_info),
+ _registers, _isSignalFrame);
+ }
+#endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
A &_addressSpace;
R _registers;
unw_proc_info_t _info;
bool _unwindInfoMissing;
bool _isSignalFrame;
-#if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64)
+#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
bool _isSigReturn = false;
#endif
};
@@ -1292,6 +1380,13 @@ template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {
}
#endif
+#ifdef _AIX
+template <typename A, typename R>
+uintptr_t UnwindCursor<A, R>::getDataRelBase() {
+ return reinterpret_cast<uintptr_t>(_info.extra);
+}
+#endif
+
template <typename A, typename R>
const char *UnwindCursor<A, R>::getRegisterName(int regNum) {
return _registers.getRegisterName(regNum);
@@ -1903,6 +1998,9 @@ bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {
uint32_t lastcode = (xdata->CountOfCodes + 1) & ~1;
const uint32_t *handler = reinterpret_cast<uint32_t *>(&xdata->UnwindCodes[lastcode]);
_info.lsda = reinterpret_cast<unw_word_t>(handler+1);
+ _dispContext.HandlerData = reinterpret_cast<void *>(_info.lsda);
+ _dispContext.LanguageHandler =
+ reinterpret_cast<EXCEPTION_ROUTINE *>(base + *handler);
if (*handler) {
_info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
} else
@@ -1912,20 +2010,555 @@ bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {
_info.handler = 0;
}
}
-#elif defined(_LIBUNWIND_TARGET_ARM)
- _info.end_ip = _info.start_ip + unwindEntry->FunctionLength;
- _info.lsda = 0; // FIXME
- _info.handler = 0; // FIXME
#endif
setLastPC(pc);
return true;
}
#endif
+#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
+// Masks for traceback table field xtbtable.
+enum xTBTableMask : uint8_t {
+ reservedBit = 0x02, // The traceback table was incorrectly generated if set
+ // (see comments in function getInfoFromTBTable().
+ ehInfoBit = 0x08 // Exception handling info is present if set
+};
+
+enum frameType : unw_word_t {
+ frameWithXLEHStateTable = 0,
+ frameWithEHInfo = 1
+};
+
+extern "C" {
+typedef _Unwind_Reason_Code __xlcxx_personality_v0_t(int, _Unwind_Action,
+ uint64_t,
+ _Unwind_Exception *,
+ struct _Unwind_Context *);
+__attribute__((__weak__)) __xlcxx_personality_v0_t __xlcxx_personality_v0;
+}
+
+static __xlcxx_personality_v0_t *xlcPersonalityV0;
+static RWMutex xlcPersonalityV0InitLock;
+
+template <typename A, typename R>
+bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R &registers) {
+ uint32_t *p = reinterpret_cast<uint32_t *>(pc);
+
+ // Keep looking forward until a word of 0 is found. The traceback
+ // table starts at the following word.
+ while (*p)
+ ++p;
+ tbtable *TBTable = reinterpret_cast<tbtable *>(p + 1);
+
+ if (_LIBUNWIND_TRACING_UNWINDING) {
+ char functionBuf[512];
+ const char *functionName = functionBuf;
+ unw_word_t offset;
+ if (!getFunctionName(functionBuf, sizeof(functionBuf), &offset)) {
+ functionName = ".anonymous.";
+ }
+ _LIBUNWIND_TRACE_UNWINDING("%s: Look up traceback table of func=%s at %p",
+ __func__, functionName,
+ reinterpret_cast<void *>(TBTable));
+ }
+
+ // If the traceback table does not contain necessary info, bypass this frame.
+ if (!TBTable->tb.has_tboff)
+ return false;
+
+ // Structure tbtable_ext contains important data we are looking for.
+ p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext);
+
+ // Skip field parminfo if it exists.
+ if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
+ ++p;
+
+ // p now points to tb_offset, the offset from start of function to TB table.
+ unw_word_t start_ip =
+ reinterpret_cast<unw_word_t>(TBTable) - *p - sizeof(uint32_t);
+ unw_word_t end_ip = reinterpret_cast<unw_word_t>(TBTable);
+ ++p;
+
+ _LIBUNWIND_TRACE_UNWINDING("start_ip=%p, end_ip=%p\n",
+ reinterpret_cast<void *>(start_ip),
+ reinterpret_cast<void *>(end_ip));
+
+ // Skip field hand_mask if it exists.
+ if (TBTable->tb.int_hndl)
+ ++p;
+
+ unw_word_t lsda = 0;
+ unw_word_t handler = 0;
+ unw_word_t flags = frameType::frameWithXLEHStateTable;
+
+ if (TBTable->tb.lang == TB_CPLUSPLUS && TBTable->tb.has_ctl) {
+ // State table info is available. The ctl_info field indicates the
+ // number of CTL anchors. There should be only one entry for the C++
+ // state table.
+ assert(*p == 1 && "libunwind: there must be only one ctl_info entry");
+ ++p;
+ // p points to the offset of the state table into the stack.
+ pint_t stateTableOffset = *p++;
+
+ int framePointerReg;
+
+ // Skip fields name_len and name if exist.
+ if (TBTable->tb.name_present) {
+ const uint16_t name_len = *(reinterpret_cast<uint16_t *>(p));
+ p = reinterpret_cast<uint32_t *>(reinterpret_cast<char *>(p) + name_len +
+ sizeof(uint16_t));
+ }
+
+ if (TBTable->tb.uses_alloca)
+ framePointerReg = *(reinterpret_cast<char *>(p));
+ else
+ framePointerReg = 1; // default frame pointer == SP
+
+ _LIBUNWIND_TRACE_UNWINDING(
+ "framePointerReg=%d, framePointer=%p, "
+ "stateTableOffset=%#lx\n",
+ framePointerReg,
+ reinterpret_cast<void *>(_registers.getRegister(framePointerReg)),
+ stateTableOffset);
+ lsda = _registers.getRegister(framePointerReg) + stateTableOffset;
+
+ // Since the traceback table generated by the legacy XLC++ does not
+ // provide the location of the personality for the state table,
+ // function __xlcxx_personality_v0(), which is the personality for the state
+ // table and is exported from libc++abi, is directly assigned as the
+ // handler here. When a legacy XLC++ frame is encountered, the symbol
+ // is resolved dynamically using dlopen() to avoid hard dependency from
+ // libunwind on libc++abi.
+
+ // Resolve the function pointer to the state table personality if it has
+ // not already.
+ if (xlcPersonalityV0 == NULL) {
+ xlcPersonalityV0InitLock.lock();
+ if (xlcPersonalityV0 == NULL) {
+ // If libc++abi is statically linked in, symbol __xlcxx_personality_v0
+ // has been resolved at the link time.
+ xlcPersonalityV0 = &__xlcxx_personality_v0;
+ if (xlcPersonalityV0 == NULL) {
+ // libc++abi is dynamically linked. Resolve __xlcxx_personality_v0
+ // using dlopen().
+ const char libcxxabi[] = "libc++abi.a(libc++abi.so.1)";
+ void *libHandle;
+ // The AIX dlopen() sets errno to 0 when it is successful, which
+ // clobbers the value of errno from the user code. This is an AIX
+ // bug because according to POSIX it should not set errno to 0. To
+ // workaround before AIX fixes the bug, errno is saved and restored.
+ int saveErrno = errno;
+ libHandle = dlopen(libcxxabi, RTLD_MEMBER | RTLD_NOW);
+ if (libHandle == NULL) {
+ _LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n",
+ errno);
+ assert(0 && "dlopen() failed");
+ }
+ xlcPersonalityV0 = reinterpret_cast<__xlcxx_personality_v0_t *>(
+ dlsym(libHandle, "__xlcxx_personality_v0"));
+ if (xlcPersonalityV0 == NULL) {
+ _LIBUNWIND_TRACE_UNWINDING("dlsym() failed with errno=%d\n", errno);
+ assert(0 && "dlsym() failed");
+ }
+ dlclose(libHandle);
+ errno = saveErrno;
+ }
+ }
+ xlcPersonalityV0InitLock.unlock();
+ }
+ handler = reinterpret_cast<unw_word_t>(xlcPersonalityV0);
+ _LIBUNWIND_TRACE_UNWINDING("State table: LSDA=%p, Personality=%p\n",
+ reinterpret_cast<void *>(lsda),
+ reinterpret_cast<void *>(handler));
+ } else if (TBTable->tb.longtbtable) {
+ // This frame has the traceback table extension. Possible cases are
+ // 1) a C++ frame that has the 'eh_info' structure; 2) a C++ frame that
+ // is not EH aware; or, 3) a frame of other languages. We need to figure out
+ // if the traceback table extension contains the 'eh_info' structure.
+ //
+ // We also need to deal with the complexity arising from some XL compiler
+ // versions use the wrong ordering of 'longtbtable' and 'has_vec' bits
+ // where the 'longtbtable' bit is meant to be the 'has_vec' bit and vice
+ // versa. For frames of code generated by those compilers, the 'longtbtable'
+ // bit may be set but there isn't really a traceback table extension.
+ //
+ // In </usr/include/sys/debug.h>, there is the following definition of
+ // 'struct tbtable_ext'. It is not really a structure but a dummy to
+ // collect the description of optional parts of the traceback table.
+ //
+ // struct tbtable_ext {
+ // ...
+ // char alloca_reg; /* Register for alloca automatic storage */
+ // struct vec_ext vec_ext; /* Vector extension (if has_vec is set) */
+ // unsigned char xtbtable; /* More tbtable fields, if longtbtable is set*/
+ // };
+ //
+ // Depending on how the 'has_vec'/'longtbtable' bit is interpreted, the data
+ // following 'alloca_reg' can be treated either as 'struct vec_ext' or
+ // 'unsigned char xtbtable'. 'xtbtable' bits are defined in
+ // </usr/include/sys/debug.h> as flags. The 7th bit '0x02' is currently
+ // unused and should not be set. 'struct vec_ext' is defined in
+ // </usr/include/sys/debug.h> as follows:
+ //
+ // struct vec_ext {
+ // unsigned vr_saved:6; /* Number of non-volatile vector regs saved
+ // */
+ // /* first register saved is assumed to be */
+ // /* 32 - vr_saved */
+ // unsigned saves_vrsave:1; /* Set if vrsave is saved on the stack */
+ // unsigned has_varargs:1;
+ // ...
+ // };
+ //
+ // Here, the 7th bit is used as 'saves_vrsave'. To determine whether it
+ // is 'struct vec_ext' or 'xtbtable' that follows 'alloca_reg',
+ // we checks if the 7th bit is set or not because 'xtbtable' should
+ // never have the 7th bit set. The 7th bit of 'xtbtable' will be reserved
+ // in the future to make sure the mitigation works. This mitigation
+ // is not 100% bullet proof because 'struct vec_ext' may not always have
+ // 'saves_vrsave' bit set.
+ //
+ // 'reservedBit' is defined in enum 'xTBTableMask' above as the mask for
+ // checking the 7th bit.
+
+ // p points to field name len.
+ uint8_t *charPtr = reinterpret_cast<uint8_t *>(p);
+
+ // Skip fields name_len and name if they exist.
+ if (TBTable->tb.name_present) {
+ const uint16_t name_len = *(reinterpret_cast<uint16_t *>(charPtr));
+ charPtr = charPtr + name_len + sizeof(uint16_t);
+ }
+
+ // Skip field alloc_reg if it exists.
+ if (TBTable->tb.uses_alloca)
+ ++charPtr;
+
+ // Check traceback table bit has_vec. Skip struct vec_ext if it exists.
+ if (TBTable->tb.has_vec)
+ // Note struct vec_ext does exist at this point because whether the
+ // ordering of longtbtable and has_vec bits is correct or not, both
+ // are set.
+ charPtr += sizeof(struct vec_ext);
+
+ // charPtr points to field 'xtbtable'. Check if the EH info is available.
+ // Also check if the reserved bit of the extended traceback table field
+ // 'xtbtable' is set. If it is, the traceback table was incorrectly
+ // generated by an XL compiler that uses the wrong ordering of 'longtbtable'
+ // and 'has_vec' bits and this is in fact 'struct vec_ext'. So skip the
+ // frame.
+ if ((*charPtr & xTBTableMask::ehInfoBit) &&
+ !(*charPtr & xTBTableMask::reservedBit)) {
+ // Mark this frame has the new EH info.
+ flags = frameType::frameWithEHInfo;
+
+ // eh_info is available.
+ charPtr++;
+ // The pointer is 4-byte aligned.
+ if (reinterpret_cast<uintptr_t>(charPtr) % 4)
+ charPtr += 4 - reinterpret_cast<uintptr_t>(charPtr) % 4;
+ uintptr_t *ehInfo =
+ reinterpret_cast<uintptr_t *>(*(reinterpret_cast<uintptr_t *>(
+ registers.getRegister(2) +
+ *(reinterpret_cast<uintptr_t *>(charPtr)))));
+
+ // ehInfo points to structure en_info. The first member is version.
+ // Only version 0 is currently supported.
+ assert(*(reinterpret_cast<uint32_t *>(ehInfo)) == 0 &&
+ "libunwind: ehInfo version other than 0 is not supported");
+
+ // Increment ehInfo to point to member lsda.
+ ++ehInfo;
+ lsda = *ehInfo++;
+
+ // enInfo now points to member personality.
+ handler = *ehInfo;
+
+ _LIBUNWIND_TRACE_UNWINDING("Range table: LSDA=%#lx, Personality=%#lx\n",
+ lsda, handler);
+ }
+ }
+
+ _info.start_ip = start_ip;
+ _info.end_ip = end_ip;
+ _info.lsda = lsda;
+ _info.handler = handler;
+ _info.gp = 0;
+ _info.flags = flags;
+ _info.format = 0;
+ _info.unwind_info = reinterpret_cast<unw_word_t>(TBTable);
+ _info.unwind_info_size = 0;
+ _info.extra = registers.getRegister(2);
+
+ return true;
+}
+
+// Step back up the stack following the frame back link.
+template <typename A, typename R>
+int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
+ R &registers, bool &isSignalFrame) {
+ if (_LIBUNWIND_TRACING_UNWINDING) {
+ char functionBuf[512];
+ const char *functionName = functionBuf;
+ unw_word_t offset;
+ if (!getFunctionName(functionBuf, sizeof(functionBuf), &offset)) {
+ functionName = ".anonymous.";
+ }
+ _LIBUNWIND_TRACE_UNWINDING(
+ "%s: Look up traceback table of func=%s at %p, pc=%p, "
+ "SP=%p, saves_lr=%d, stores_bc=%d",
+ __func__, functionName, reinterpret_cast<void *>(TBTable),
+ reinterpret_cast<void *>(pc),
+ reinterpret_cast<void *>(registers.getSP()), TBTable->tb.saves_lr,
+ TBTable->tb.stores_bc);
+ }
+
+#if defined(__powerpc64__)
+ // Instruction to reload TOC register "ld r2,40(r1)"
+ const uint32_t loadTOCRegInst = 0xe8410028;
+ const int32_t unwPPCF0Index = UNW_PPC64_F0;
+ const int32_t unwPPCV0Index = UNW_PPC64_V0;
+#else
+ // Instruction to reload TOC register "lwz r2,20(r1)"
+ const uint32_t loadTOCRegInst = 0x80410014;
+ const int32_t unwPPCF0Index = UNW_PPC_F0;
+ const int32_t unwPPCV0Index = UNW_PPC_V0;
+#endif
+
+ // lastStack points to the stack frame of the next routine up.
+ pint_t curStack = static_cast<pint_t>(registers.getSP());
+ pint_t lastStack = *reinterpret_cast<pint_t *>(curStack);
+
+ if (lastStack == 0)
+ return UNW_STEP_END;
+
+ R newRegisters = registers;
+
+ // If backchain is not stored, use the current stack frame.
+ if (!TBTable->tb.stores_bc)
+ lastStack = curStack;
+
+ // Return address is the address after call site instruction.
+ pint_t returnAddress;
+
+ if (isSignalFrame) {
+ _LIBUNWIND_TRACE_UNWINDING("Possible signal handler frame: lastStack=%p",
+ reinterpret_cast<void *>(lastStack));
+
+ sigcontext *sigContext = reinterpret_cast<sigcontext *>(
+ reinterpret_cast<char *>(lastStack) + STKMINALIGN);
+ returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;
+
+ bool useSTKMIN = false;
+ if (returnAddress < 0x10000000) {
+ // Try again using STKMIN.
+ sigContext = reinterpret_cast<sigcontext *>(
+ reinterpret_cast<char *>(lastStack) + STKMIN);
+ returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;
+ if (returnAddress < 0x10000000) {
+ _LIBUNWIND_TRACE_UNWINDING("Bad returnAddress=%p from sigcontext=%p",
+ reinterpret_cast<void *>(returnAddress),
+ reinterpret_cast<void *>(sigContext));
+ return UNW_EBADFRAME;
+ }
+ useSTKMIN = true;
+ }
+ _LIBUNWIND_TRACE_UNWINDING("Returning from a signal handler %s: "
+ "sigContext=%p, returnAddress=%p. "
+ "Seems to be a valid address",
+ useSTKMIN ? "STKMIN" : "STKMINALIGN",
+ reinterpret_cast<void *>(sigContext),
+ reinterpret_cast<void *>(returnAddress));
+
+ // Restore the condition register from sigcontext.
+ newRegisters.setCR(sigContext->sc_jmpbuf.jmp_context.cr);
+
+ // Save the LR in sigcontext for stepping up when the function that
+ // raised the signal is a leaf function. This LR has the return address
+ // to the caller of the leaf function.
+ newRegisters.setLR(sigContext->sc_jmpbuf.jmp_context.lr);
+ _LIBUNWIND_TRACE_UNWINDING(
+ "Save LR=%p from sigcontext",
+ reinterpret_cast<void *>(sigContext->sc_jmpbuf.jmp_context.lr));
+
+ // Restore GPRs from sigcontext.
+ for (int i = 0; i < 32; ++i)
+ newRegisters.setRegister(i, sigContext->sc_jmpbuf.jmp_context.gpr[i]);
+
+ // Restore FPRs from sigcontext.
+ for (int i = 0; i < 32; ++i)
+ newRegisters.setFloatRegister(i + unwPPCF0Index,
+ sigContext->sc_jmpbuf.jmp_context.fpr[i]);
+
+ // Restore vector registers if there is an associated extended context
+ // structure.
+ if (sigContext->sc_jmpbuf.jmp_context.msr & __EXTCTX) {
+ ucontext_t *uContext = reinterpret_cast<ucontext_t *>(sigContext);
+ if (uContext->__extctx->__extctx_magic == __EXTCTX_MAGIC) {
+ for (int i = 0; i < 32; ++i)
+ newRegisters.setVectorRegister(
+ i + unwPPCV0Index, *(reinterpret_cast<v128 *>(
+ &(uContext->__extctx->__vmx.__vr[i]))));
+ }
+ }
+ } else {
+ // Step up a normal frame.
+
+ if (!TBTable->tb.saves_lr && registers.getLR()) {
+ // This case should only occur if we were called from a signal handler
+ // and the signal occurred in a function that doesn't save the LR.
+ returnAddress = static_cast<pint_t>(registers.getLR());
+ _LIBUNWIND_TRACE_UNWINDING("Use saved LR=%p",
+ reinterpret_cast<void *>(returnAddress));
+ } else {
+ // Otherwise, use the LR value in the stack link area.
+ returnAddress = reinterpret_cast<pint_t *>(lastStack)[2];
+ }
+
+ // Reset LR in the current context.
+ newRegisters.setLR(NULL);
+
+ _LIBUNWIND_TRACE_UNWINDING(
+ "Extract info from lastStack=%p, returnAddress=%p",
+ reinterpret_cast<void *>(lastStack),
+ reinterpret_cast<void *>(returnAddress));
+ _LIBUNWIND_TRACE_UNWINDING("fpr_regs=%d, gpr_regs=%d, saves_cr=%d",
+ TBTable->tb.fpr_saved, TBTable->tb.gpr_saved,
+ TBTable->tb.saves_cr);
+
+ // Restore FP registers.
+ char *ptrToRegs = reinterpret_cast<char *>(lastStack);
+ double *FPRegs = reinterpret_cast<double *>(
+ ptrToRegs - (TBTable->tb.fpr_saved * sizeof(double)));
+ for (int i = 0; i < TBTable->tb.fpr_saved; ++i)
+ newRegisters.setFloatRegister(
+ 32 - TBTable->tb.fpr_saved + i + unwPPCF0Index, FPRegs[i]);
+
+ // Restore GP registers.
+ ptrToRegs = reinterpret_cast<char *>(FPRegs);
+ uintptr_t *GPRegs = reinterpret_cast<uintptr_t *>(
+ ptrToRegs - (TBTable->tb.gpr_saved * sizeof(uintptr_t)));
+ for (int i = 0; i < TBTable->tb.gpr_saved; ++i)
+ newRegisters.setRegister(32 - TBTable->tb.gpr_saved + i, GPRegs[i]);
+
+ // Restore Vector registers.
+ ptrToRegs = reinterpret_cast<char *>(GPRegs);
+
+ // Restore vector registers only if this is a Clang frame. Also
+ // check if traceback table bit has_vec is set. If it is, structure
+ // vec_ext is available.
+ if (_info.flags == frameType::frameWithEHInfo && TBTable->tb.has_vec) {
+
+ // Get to the vec_ext structure to check if vector registers are saved.
+ uint32_t *p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext);
+
+ // Skip field parminfo if exists.
+ if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
+ ++p;
+
+ // Skip field tb_offset if exists.
+ if (TBTable->tb.has_tboff)
+ ++p;
+
+ // Skip field hand_mask if exists.
+ if (TBTable->tb.int_hndl)
+ ++p;
+
+ // Skip fields ctl_info and ctl_info_disp if exist.
+ if (TBTable->tb.has_ctl) {
+ // Skip field ctl_info.
+ ++p;
+ // Skip field ctl_info_disp.
+ ++p;
+ }
+
+ // Skip fields name_len and name if exist.
+ // p is supposed to point to field name_len now.
+ uint8_t *charPtr = reinterpret_cast<uint8_t *>(p);
+ if (TBTable->tb.name_present) {
+ const uint16_t name_len = *(reinterpret_cast<uint16_t *>(charPtr));
+ charPtr = charPtr + name_len + sizeof(uint16_t);
+ }
+
+ // Skip field alloc_reg if it exists.
+ if (TBTable->tb.uses_alloca)
+ ++charPtr;
+
+ struct vec_ext *vec_ext = reinterpret_cast<struct vec_ext *>(charPtr);
+
+ _LIBUNWIND_TRACE_UNWINDING("vr_saved=%d", vec_ext->vr_saved);
+
+ // Restore vector register(s) if saved on the stack.
+ if (vec_ext->vr_saved) {
+ // Saved vector registers are 16-byte aligned.
+ if (reinterpret_cast<uintptr_t>(ptrToRegs) % 16)
+ ptrToRegs -= reinterpret_cast<uintptr_t>(ptrToRegs) % 16;
+ v128 *VecRegs = reinterpret_cast<v128 *>(ptrToRegs - vec_ext->vr_saved *
+ sizeof(v128));
+ for (int i = 0; i < vec_ext->vr_saved; ++i) {
+ newRegisters.setVectorRegister(
+ 32 - vec_ext->vr_saved + i + unwPPCV0Index, VecRegs[i]);
+ }
+ }
+ }
+ if (TBTable->tb.saves_cr) {
+ // Get the saved condition register. The condition register is only
+ // a single word.
+ newRegisters.setCR(
+ *(reinterpret_cast<uint32_t *>(lastStack + sizeof(uintptr_t))));
+ }
+
+ // Restore the SP.
+ newRegisters.setSP(lastStack);
+
+ // The first instruction after return.
+ uint32_t firstInstruction = *(reinterpret_cast<uint32_t *>(returnAddress));
+
+ // Do we need to set the TOC register?
+ _LIBUNWIND_TRACE_UNWINDING(
+ "Current gpr2=%p",
+ reinterpret_cast<void *>(newRegisters.getRegister(2)));
+ if (firstInstruction == loadTOCRegInst) {
+ _LIBUNWIND_TRACE_UNWINDING(
+ "Set gpr2=%p from frame",
+ reinterpret_cast<void *>(reinterpret_cast<pint_t *>(lastStack)[5]));
+ newRegisters.setRegister(2, reinterpret_cast<pint_t *>(lastStack)[5]);
+ }
+ }
+ _LIBUNWIND_TRACE_UNWINDING("lastStack=%p, returnAddress=%p, pc=%p\n",
+ reinterpret_cast<void *>(lastStack),
+ reinterpret_cast<void *>(returnAddress),
+ reinterpret_cast<void *>(pc));
+
+ // The return address is the address after call site instruction, so
+ // setting IP to that simulates a return.
+ newRegisters.setIP(reinterpret_cast<uintptr_t>(returnAddress));
+
+ // Simulate the step by replacing the register set with the new ones.
+ registers = newRegisters;
+
+ // Check if the next frame is a signal frame.
+ pint_t nextStack = *(reinterpret_cast<pint_t *>(registers.getSP()));
+
+ // Return address is the address after call site instruction.
+ pint_t nextReturnAddress = reinterpret_cast<pint_t *>(nextStack)[2];
+
+ if (nextReturnAddress > 0x01 && nextReturnAddress < 0x10000) {
+ _LIBUNWIND_TRACE_UNWINDING("The next is a signal handler frame: "
+ "nextStack=%p, next return address=%p\n",
+ reinterpret_cast<void *>(nextStack),
+ reinterpret_cast<void *>(nextReturnAddress));
+ isSignalFrame = true;
+ } else {
+ isSignalFrame = false;
+ }
+ return UNW_STEP_SUCCESS;
+}
+#endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
template <typename A, typename R>
void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
-#if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64)
+#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
_isSigReturn = false;
#endif
@@ -1948,7 +2581,14 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
// To disambiguate this, back up the pc when we know it is a return
// address.
if (isReturnAddress)
+#if defined(_AIX)
+ // PC needs to be a 4-byte aligned address to be able to look for a
+ // word of 0 that indicates the start of the traceback table at the end
+ // of a function on AIX.
+ pc -= 4;
+#else
--pc;
+#endif
// Ask address space object to find unwind sections for this pc.
UnwindInfoSections sects;
@@ -1982,6 +2622,12 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
return;
#endif
+#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
+ // If there is unwind info in the traceback table, look there next.
+ if (this->getInfoFromTBTable(pc, _registers))
+ return;
+#endif
+
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
// If there is dwarf unwind info, look there next.
if (sects.dwarf_section != 0) {
@@ -2027,7 +2673,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
}
#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
-#if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64)
+#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
if (setInfoForSigReturn())
return;
#endif
@@ -2036,7 +2682,8 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
_unwindInfoMissing = true;
}
-#if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64)
+#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
+ defined(_LIBUNWIND_TARGET_AARCH64)
template <typename A, typename R>
bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {
// Look for the sigreturn trampoline. The trampoline's body is two
@@ -2055,14 +2702,20 @@ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {
//
// [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/vdso/sigreturn.S
const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
+ // The PC might contain an invalid address if the unwind info is bad, so
+ // directly accessing it could cause a SIGSEGV.
+ if (!isReadableAddr(pc))
+ return false;
+ auto *instructions = reinterpret_cast<const uint32_t *>(pc);
// Look for instructions: mov x8, #0x8b; svc #0x0
- if (_addressSpace.get32(pc) == 0xd2801168 &&
- _addressSpace.get32(pc + 4) == 0xd4000001) {
- _info = {};
- _isSigReturn = true;
- return true;
- }
- return false;
+ if (instructions[0] != 0xd2801168 || instructions[1] != 0xd4000001)
+ return false;
+
+ _info = {};
+ _info.start_ip = pc;
+ _info.end_ip = pc + 4;
+ _isSigReturn = true;
+ return true;
}
template <typename A, typename R>
@@ -2096,28 +2749,188 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {
_isSignalFrame = true;
return UNW_STEP_SUCCESS;
}
-#endif // defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64)
+#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
+ // defined(_LIBUNWIND_TARGET_AARCH64)
+
+#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
+ defined(_LIBUNWIND_TARGET_RISCV)
+template <typename A, typename R>
+bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_riscv &) {
+ const pint_t pc = static_cast<pint_t>(getReg(UNW_REG_IP));
+ // The PC might contain an invalid address if the unwind info is bad, so
+ // directly accessing it could cause a SIGSEGV.
+ if (!isReadableAddr(pc))
+ return false;
+ const auto *instructions = reinterpret_cast<const uint32_t *>(pc);
+ // Look for the two instructions used in the sigreturn trampoline
+ // __vdso_rt_sigreturn:
+ //
+ // 0x08b00893 li a7,0x8b
+ // 0x00000073 ecall
+ if (instructions[0] != 0x08b00893 || instructions[1] != 0x00000073)
+ return false;
+
+ _info = {};
+ _info.start_ip = pc;
+ _info.end_ip = pc + 4;
+ _isSigReturn = true;
+ return true;
+}
+
+template <typename A, typename R>
+int UnwindCursor<A, R>::stepThroughSigReturn(Registers_riscv &) {
+ // In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
+ // - 128-byte siginfo struct
+ // - ucontext_t struct:
+ // - 8-byte long (__uc_flags)
+ // - 8-byte pointer (*uc_link)
+ // - 24-byte uc_stack
+ // - 8-byte uc_sigmask
+ // - 120-byte of padding to allow sigset_t to be expanded in the future
+ // - 8 bytes of padding because sigcontext has 16-byte alignment
+ // - struct sigcontext uc_mcontext
+ // [1]
+ // https://github.com/torvalds/linux/blob/master/arch/riscv/kernel/signal.c
+ const pint_t kOffsetSpToSigcontext = 128 + 8 + 8 + 24 + 8 + 128;
+
+ const pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext;
+ _registers.setIP(_addressSpace.get64(sigctx));
+ for (int i = UNW_RISCV_X1; i <= UNW_RISCV_X31; ++i) {
+ uint64_t value = _addressSpace.get64(sigctx + static_cast<pint_t>(i * 8));
+ _registers.setRegister(i, value);
+ }
+ _isSignalFrame = true;
+ return UNW_STEP_SUCCESS;
+}
+#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
+ // defined(_LIBUNWIND_TARGET_RISCV)
+
+#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
+ defined(_LIBUNWIND_TARGET_S390X)
+template <typename A, typename R>
+bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_s390x &) {
+ // Look for the sigreturn trampoline. The trampoline's body is a
+ // specific instruction (see below). Typically the trampoline comes from the
+ // vDSO (i.e. the __kernel_[rt_]sigreturn function). A libc might provide its
+ // own restorer function, though, or user-mode QEMU might write a trampoline
+ // onto the stack.
+ const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
+ // The PC might contain an invalid address if the unwind info is bad, so
+ // directly accessing it could cause a SIGSEGV.
+ if (!isReadableAddr(pc))
+ return false;
+ const auto inst = *reinterpret_cast<const uint16_t *>(pc);
+ if (inst == 0x0a77 || inst == 0x0aad) {
+ _info = {};
+ _info.start_ip = pc;
+ _info.end_ip = pc + 2;
+ _isSigReturn = true;
+ return true;
+ }
+ return false;
+}
template <typename A, typename R>
-int UnwindCursor<A, R>::step() {
+int UnwindCursor<A, R>::stepThroughSigReturn(Registers_s390x &) {
+ // Determine current SP.
+ const pint_t sp = static_cast<pint_t>(this->getReg(UNW_REG_SP));
+ // According to the s390x ABI, the CFA is at (incoming) SP + 160.
+ const pint_t cfa = sp + 160;
+
+ // Determine current PC and instruction there (this must be either
+ // a "svc __NR_sigreturn" or "svc __NR_rt_sigreturn").
+ const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
+ const uint16_t inst = _addressSpace.get16(pc);
+
+ // Find the addresses of the signo and sigcontext in the frame.
+ pint_t pSigctx = 0;
+ pint_t pSigno = 0;
+
+ // "svc __NR_sigreturn" uses a non-RT signal trampoline frame.
+ if (inst == 0x0a77) {
+ // Layout of a non-RT signal trampoline frame, starting at the CFA:
+ // - 8-byte signal mask
+ // - 8-byte pointer to sigcontext, followed by signo
+ // - 4-byte signo
+ pSigctx = _addressSpace.get64(cfa + 8);
+ pSigno = pSigctx + 344;
+ }
+
+ // "svc __NR_rt_sigreturn" uses a RT signal trampoline frame.
+ if (inst == 0x0aad) {
+ // Layout of a RT signal trampoline frame, starting at the CFA:
+ // - 8-byte retcode (+ alignment)
+ // - 128-byte siginfo struct (starts with signo)
+ // - ucontext struct:
+ // - 8-byte long (uc_flags)
+ // - 8-byte pointer (uc_link)
+ // - 24-byte stack_t
+ // - 8 bytes of padding because sigcontext has 16-byte alignment
+ // - sigcontext/mcontext_t
+ pSigctx = cfa + 8 + 128 + 8 + 8 + 24 + 8;
+ pSigno = cfa + 8;
+ }
+
+ assert(pSigctx != 0);
+ assert(pSigno != 0);
+
+ // Offsets from sigcontext to each register.
+ const pint_t kOffsetPc = 8;
+ const pint_t kOffsetGprs = 16;
+ const pint_t kOffsetFprs = 216;
+
+ // Restore all registers.
+ for (int i = 0; i < 16; ++i) {
+ uint64_t value = _addressSpace.get64(pSigctx + kOffsetGprs +
+ static_cast<pint_t>(i * 8));
+ _registers.setRegister(UNW_S390X_R0 + i, value);
+ }
+ for (int i = 0; i < 16; ++i) {
+ static const int fpr[16] = {
+ UNW_S390X_F0, UNW_S390X_F1, UNW_S390X_F2, UNW_S390X_F3,
+ UNW_S390X_F4, UNW_S390X_F5, UNW_S390X_F6, UNW_S390X_F7,
+ UNW_S390X_F8, UNW_S390X_F9, UNW_S390X_F10, UNW_S390X_F11,
+ UNW_S390X_F12, UNW_S390X_F13, UNW_S390X_F14, UNW_S390X_F15
+ };
+ double value = _addressSpace.getDouble(pSigctx + kOffsetFprs +
+ static_cast<pint_t>(i * 8));
+ _registers.setFloatRegister(fpr[i], value);
+ }
+ _registers.setIP(_addressSpace.get64(pSigctx + kOffsetPc));
+
+ // SIGILL, SIGFPE and SIGTRAP are delivered with psw_addr
+ // after the faulting instruction rather than before it.
+ // Do not set _isSignalFrame in that case.
+ uint32_t signo = _addressSpace.get32(pSigno);
+ _isSignalFrame = (signo != 4 && signo != 5 && signo != 8);
+
+ return UNW_STEP_SUCCESS;
+}
+#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
+ // defined(_LIBUNWIND_TARGET_S390X)
+
+template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
+ (void)stage2;
// Bottom of stack is defined is when unwind info cannot be found.
if (_unwindInfoMissing)
return UNW_STEP_END;
// Use unwinding info to modify register set as if function returned.
int result;
-#if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64)
+#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
if (_isSigReturn) {
result = this->stepThroughSigReturn();
} else
#endif
{
#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
- result = this->stepWithCompactEncoding();
+ result = this->stepWithCompactEncoding(stage2);
#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
result = this->stepWithSEHData();
+#elif defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
+ result = this->stepWithTBTableData();
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
- result = this->stepWithDwarfFDE();
+ result = this->stepWithDwarfFDE(stage2);
#elif defined(_LIBUNWIND_ARM_EHABI)
result = this->stepWithEHABI();
#else
@@ -2153,6 +2966,37 @@ bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen,
buf, bufLen, offset);
}
+#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
+template <typename A, typename R>
+bool UnwindCursor<A, R>::isReadableAddr(const pint_t addr) const {
+ // We use SYS_rt_sigprocmask, inspired by Abseil's AddressIsReadable.
+
+ const auto sigsetAddr = reinterpret_cast<sigset_t *>(addr);
+ // We have to check that addr is nullptr because sigprocmask allows that
+ // as an argument without failure.
+ if (!sigsetAddr)
+ return false;
+ const auto saveErrno = errno;
+ // We MUST use a raw syscall here, as wrappers may try to access
+ // sigsetAddr which may cause a SIGSEGV. A raw syscall however is
+ // safe. Additionally, we need to pass the kernel_sigset_size, which is
+ // different from libc sizeof(sigset_t). For the majority of architectures,
+ // it's 64 bits (_NSIG), and libc NSIG is _NSIG + 1.
+ const auto kernelSigsetSize = NSIG / 8;
+ [[maybe_unused]] const int Result = syscall(
+ SYS_rt_sigprocmask, /*how=*/~0, sigsetAddr, nullptr, kernelSigsetSize);
+ // Because our "how" is invalid, this syscall should always fail, and our
+ // errno should always be EINVAL or an EFAULT. This relies on the Linux
+ // kernel to check copy_from_user before checking if the "how" argument is
+ // invalid.
+ assert(Result == -1);
+ assert(errno == EFAULT || errno == EINVAL);
+ const auto readable = errno != EFAULT;
+ errno = saveErrno;
+ return readable;
+}
+#endif
+
#if defined(_LIBUNWIND_USE_CET)
extern "C" void *__libunwind_cet_get_registers(unw_cursor_t *cursor) {
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
diff --git a/contrib/libs/libunwind/src/UnwindLevel1-gcc-ext.c b/contrib/libs/libunwind/src/UnwindLevel1-gcc-ext.c
index 951d5d219a..7deeb2cc07 100644
--- a/contrib/libs/libunwind/src/UnwindLevel1-gcc-ext.c
+++ b/contrib/libs/libunwind/src/UnwindLevel1-gcc-ext.c
@@ -22,6 +22,10 @@
#include "Unwind-EHABI.h"
#include "unwind.h"
+#if defined(_AIX)
+#error #include <sys/debug.h>
+#endif
+
#if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
@@ -48,7 +52,7 @@ _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) {
// std::terminate().
}
- // Call through to _Unwind_Resume() which distiguishes between forced and
+ // Call through to _Unwind_Resume() which distinguishes between forced and
// regular exceptions.
_Unwind_Resume(exception_object);
_LIBUNWIND_ABORT("_Unwind_Resume_or_Rethrow() called _Unwind_RaiseException()"
@@ -59,12 +63,15 @@ _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) {
/// relative encodings.
_LIBUNWIND_EXPORT uintptr_t
_Unwind_GetDataRelBase(struct _Unwind_Context *context) {
- (void)context;
_LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", (void *)context);
+#if defined(_AIX)
+ return unw_get_data_rel_base((unw_cursor_t *)context);
+#else
+ (void)context;
_LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented");
+#endif
}
-
/// Called by personality handler during phase 2 to get base address for text
/// relative encodings.
_LIBUNWIND_EXPORT uintptr_t
@@ -79,6 +86,32 @@ _Unwind_GetTextRelBase(struct _Unwind_Context *context) {
/// specified code address "pc".
_LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) {
_LIBUNWIND_TRACE_API("_Unwind_FindEnclosingFunction(pc=%p)", pc);
+#if defined(_AIX)
+ if (pc == NULL)
+ return NULL;
+
+ // Get the start address of the enclosing function from the function's
+ // traceback table.
+ uint32_t *p = (uint32_t *)pc;
+
+ // Keep looking forward until a word of 0 is found. The traceback
+ // table starts at the following word.
+ while (*p)
+ ++p;
+ struct tbtable *TBTable = (struct tbtable *)(p + 1);
+
+ // Get the address of the traceback table extension.
+ p = (uint32_t *)&TBTable->tb_ext;
+
+ // Skip field parminfo if it exists.
+ if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
+ ++p;
+
+ if (TBTable->tb.has_tboff)
+ // *p contains the offset from the function start to traceback table.
+ return (void *)((uintptr_t)TBTable - *p - sizeof(uint32_t));
+ return NULL;
+#else
// This is slow, but works.
// We create an unwind cursor then alter the IP to be pc
unw_cursor_t cursor;
@@ -91,6 +124,7 @@ _LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) {
return (void *)(intptr_t) info.start_ip;
else
return NULL;
+#endif
}
/// Walk every frame and call trace function at each one. If trace function
@@ -109,7 +143,7 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
// Create a mock exception object for force unwinding.
_Unwind_Exception ex;
memset(&ex, '\0', sizeof(ex));
- strcpy((char *)&ex.exception_class, "CLNGUNW");
+ memcpy(&ex.exception_class, "CLNGUNW", sizeof(ex.exception_class));
#endif
// walk each frame
@@ -133,7 +167,7 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
}
// Update the pr_cache in the mock exception object.
- const uint32_t* unwindInfo = (uint32_t *) frameInfo.unwind_info;
+ uint32_t *unwindInfo = (uint32_t *)frameInfo.unwind_info;
ex.pr_cache.fnstart = frameInfo.start_ip;
ex.pr_cache.ehtp = (_Unwind_EHT_Header *) unwindInfo;
ex.pr_cache.additional= frameInfo.flags;
diff --git a/contrib/libs/libunwind/src/UnwindLevel1.c b/contrib/libs/libunwind/src/UnwindLevel1.c
index 72b507829d..39a261c0f8 100644
--- a/contrib/libs/libunwind/src/UnwindLevel1.c
+++ b/contrib/libs/libunwind/src/UnwindLevel1.c
@@ -41,11 +41,16 @@
// In exception handing, some stack frames will be skipped before jumping to
// landing pad and we must adjust CET shadow stack accordingly.
// _LIBUNWIND_POP_CET_SSP is used to adjust CET shadow stack pointer and we
-// directly jump to __libunwind_Registerts_x86/x86_64_jumpto instead of using
+// directly jump to __libunwind_Registers_x86/x86_64_jumpto instead of using
// a regular function call to avoid pushing to CET shadow stack again.
#if !defined(_LIBUNWIND_USE_CET)
-#define __unw_phase2_resume(cursor, fn) __unw_resume((cursor))
+#define __unw_phase2_resume(cursor, fn) \
+ do { \
+ (void)fn; \
+ __unw_resume((cursor)); \
+ } while (0)
#elif defined(_LIBUNWIND_TARGET_I386)
+#define __cet_ss_step_size 4
#define __unw_phase2_resume(cursor, fn) \
do { \
_LIBUNWIND_POP_CET_SSP((fn)); \
@@ -57,6 +62,7 @@
"d"(cetJumpAddress)); \
} while (0)
#elif defined(_LIBUNWIND_TARGET_X86_64)
+#define __cet_ss_step_size 8
#define __unw_phase2_resume(cursor, fn) \
do { \
_LIBUNWIND_POP_CET_SSP((fn)); \
@@ -87,13 +93,13 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
int stepResult = __unw_step(cursor);
if (stepResult == 0) {
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): __unw_step() reached "
+ "unwind_phase1(ex_obj=%p): __unw_step() reached "
"bottom => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_END_OF_STACK;
} else if (stepResult < 0) {
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): __unw_step failed => "
+ "unwind_phase1(ex_obj=%p): __unw_step failed => "
"_URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE1_ERROR;
@@ -112,7 +118,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
unw_word_t sp;
if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): __unw_get_proc_info "
+ "unwind_phase1(ex_obj=%p): __unw_get_proc_info "
"failed => _URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE1_ERROR;
@@ -131,7 +137,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
unw_word_t pc;
__unw_get_reg(cursor, UNW_REG_IP, &pc);
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR
+ "unwind_phase1(ex_obj=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR
", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR "",
(void *)exception_object, pc, frameInfo.start_ip, functionName,
frameInfo.lsda, frameInfo.handler);
@@ -144,7 +150,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
_Unwind_Personality_Fn p =
(_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler);
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): calling personality function %p",
+ "unwind_phase1(ex_obj=%p): calling personality function %p",
(void *)exception_object, (void *)(uintptr_t)p);
_Unwind_Reason_Code personalityResult =
(*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class,
@@ -156,13 +162,13 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
__unw_get_reg(cursor, UNW_REG_SP, &sp);
exception_object->private_2 = (uintptr_t)sp;
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND",
+ "unwind_phase1(ex_obj=%p): _URC_HANDLER_FOUND",
(void *)exception_object);
return _URC_NO_REASON;
case _URC_CONTINUE_UNWIND:
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND",
+ "unwind_phase1(ex_obj=%p): _URC_CONTINUE_UNWIND",
(void *)exception_object);
// continue unwinding
break;
@@ -170,7 +176,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
default:
// something went wrong
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR",
+ "unwind_phase1(ex_obj=%p): _URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE1_ERROR;
}
@@ -178,33 +184,36 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
}
return _URC_NO_REASON;
}
-
+extern int __unw_step_stage2(unw_cursor_t *);
static _Unwind_Reason_Code
unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
__unw_init_local(cursor, uc);
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)",
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p)",
(void *)exception_object);
// uc is initialized by __unw_getcontext in the parent frame. The first stack
// frame walked is unwind_phase2.
unsigned framesWalked __attribute__((unused)) = 1;
+#ifdef _LIBUNWIND_USE_CET
+ unsigned long shadowStackTop = _get_ssp();
+#endif
// Walk each frame until we reach where search phase said to stop.
while (true) {
// Ask libunwind to get next frame (skip over first which is
// _Unwind_RaiseException).
- int stepResult = __unw_step(cursor);
+ int stepResult = __unw_step_stage2(cursor);
if (stepResult == 0) {
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2(ex_ojb=%p): __unw_step() reached "
+ "unwind_phase2(ex_obj=%p): __unw_step_stage2() reached "
"bottom => _URC_END_OF_STACK",
(void *)exception_object);
return _URC_END_OF_STACK;
} else if (stepResult < 0) {
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2(ex_ojb=%p): __unw_step failed => "
+ "unwind_phase2(ex_obj=%p): __unw_step_stage2 failed => "
"_URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
@@ -216,7 +225,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
__unw_get_reg(cursor, UNW_REG_SP, &sp);
if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2(ex_ojb=%p): __unw_get_proc_info "
+ "unwind_phase2(ex_obj=%p): __unw_get_proc_info "
"failed => _URC_FATAL_PHASE1_ERROR",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
@@ -232,7 +241,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
&offset) != UNW_ESUCCESS) ||
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIxPTR
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p): start_ip=0x%" PRIxPTR
", func=%s, sp=0x%" PRIxPTR ", lsda=0x%" PRIxPTR
", personality=0x%" PRIxPTR,
(void *)exception_object, frameInfo.start_ip,
@@ -241,6 +250,20 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
}
#endif
+// In CET enabled environment, we check return address stored in normal stack
+// against return address stored in CET shadow stack, if the 2 addresses don't
+// match, it means return address in normal stack has been corrupted, we return
+// _URC_FATAL_PHASE2_ERROR.
+#ifdef _LIBUNWIND_USE_CET
+ if (shadowStackTop != 0) {
+ unw_word_t retInNormalStack;
+ __unw_get_reg(cursor, UNW_REG_IP, &retInNormalStack);
+ unsigned long retInShadowStack = *(
+ unsigned long *)(shadowStackTop + __cet_ss_step_size * framesWalked);
+ if (retInNormalStack != retInShadowStack)
+ return _URC_FATAL_PHASE2_ERROR;
+ }
+#endif
++framesWalked;
// If there is a personality routine, tell it we are unwinding.
if (frameInfo.handler != 0) {
@@ -258,7 +281,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
case _URC_CONTINUE_UNWIND:
// Continue unwinding
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND",
+ "unwind_phase2(ex_obj=%p): _URC_CONTINUE_UNWIND",
(void *)exception_object);
if (sp == exception_object->private_2) {
// Phase 1 said we would stop at this frame, but we did not...
@@ -268,7 +291,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
break;
case _URC_INSTALL_CONTEXT:
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT",
+ "unwind_phase2(ex_obj=%p): _URC_INSTALL_CONTEXT",
(void *)exception_object);
// Personality routine says to transfer control to landing pad.
// We may get control back if landing pad calls _Unwind_Resume().
@@ -276,7 +299,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except
unw_word_t pc;
__unw_get_reg(cursor, UNW_REG_IP, &pc);
__unw_get_reg(cursor, UNW_REG_SP, &sp);
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering "
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p): re-entering "
"user code with ip=0x%" PRIxPTR
", sp=0x%" PRIxPTR,
(void *)exception_object, pc, sp);
@@ -309,14 +332,15 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
// frame walked is unwind_phase2_forced.
unsigned framesWalked __attribute__((unused)) = 1;
// Walk each frame until we reach where search phase said to stop
- while (__unw_step(cursor) > 0) {
+ while (__unw_step_stage2(cursor) > 0) {
// Update info about this frame.
unw_proc_info_t frameInfo;
if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_step "
- "failed => _URC_END_OF_STACK",
- (void *)exception_object);
+ _LIBUNWIND_TRACE_UNWINDING(
+ "unwind_phase2_forced(ex_obj=%p): __unw_get_proc_info "
+ "failed => _URC_END_OF_STACK",
+ (void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
@@ -331,7 +355,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
(frameInfo.start_ip + offset > frameInfo.end_ip))
functionName = ".anonymous.";
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIxPTR
+ "unwind_phase2_forced(ex_obj=%p): start_ip=0x%" PRIxPTR
", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,
(void *)exception_object, frameInfo.start_ip, functionName,
frameInfo.lsda, frameInfo.handler);
@@ -345,11 +369,11 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
(*stop)(1, action, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)(cursor), stop_parameter);
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2_forced(ex_ojb=%p): stop function returned %d",
+ "unwind_phase2_forced(ex_obj=%p): stop function returned %d",
(void *)exception_object, stopResult);
if (stopResult != _URC_NO_REASON) {
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2_forced(ex_ojb=%p): stopped by stop function",
+ "unwind_phase2_forced(ex_obj=%p): stopped by stop function",
(void *)exception_object);
return _URC_FATAL_PHASE2_ERROR;
}
@@ -360,21 +384,21 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
_Unwind_Personality_Fn p =
(_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler);
_LIBUNWIND_TRACE_UNWINDING(
- "unwind_phase2_forced(ex_ojb=%p): calling personality function %p",
+ "unwind_phase2_forced(ex_obj=%p): calling personality function %p",
(void *)exception_object, (void *)(uintptr_t)p);
_Unwind_Reason_Code personalityResult =
(*p)(1, action, exception_object->exception_class, exception_object,
(struct _Unwind_Context *)(cursor));
switch (personalityResult) {
case _URC_CONTINUE_UNWIND:
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "
"personality returned "
"_URC_CONTINUE_UNWIND",
(void *)exception_object);
// Destructors called, continue unwinding
break;
case _URC_INSTALL_CONTEXT:
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "
"personality returned "
"_URC_INSTALL_CONTEXT",
(void *)exception_object);
@@ -383,7 +407,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
break;
default:
// Personality routine returned an unknown result code.
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): "
"personality returned %d, "
"_URC_FATAL_PHASE2_ERROR",
(void *)exception_object, personalityResult);
@@ -394,7 +418,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
// Call stop function one last time and tell it we've reached the end
// of the stack.
- _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "
+ _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): calling stop "
"function with _UA_END_OF_STACK",
(void *)exception_object);
_Unwind_Action lastAction =
@@ -438,7 +462,7 @@ _Unwind_RaiseException(_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)
@@ -497,11 +521,13 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
_LIBUNWIND_TRACE_API(
"_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR,
(void *)context, result);
+#if !defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
if (result != 0) {
if (*((uint8_t *)result) != 0xFF)
_LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF",
result);
}
+#endif
return result;
}
diff --git a/contrib/libs/libunwind/src/UnwindRegistersRestore.S b/contrib/libs/libunwind/src/UnwindRegistersRestore.S
index 1df97f5fc4..42c2488fc7 100644
--- a/contrib/libs/libunwind/src/UnwindRegistersRestore.S
+++ b/contrib/libs/libunwind/src/UnwindRegistersRestore.S
@@ -8,7 +8,17 @@
#include "assembly.h"
+#define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+#define FROM_16_TO_31 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+
+#define FROM_0_TO_31 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+#define FROM_32_TO_63 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63
+
+#if defined(_AIX)
+ .toc
+#else
.text
+#endif
#if !defined(__USING_SJLJ_EXCEPTIONS__)
@@ -184,9 +194,20 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv)
addi 4, 3, PPC64_OFFS_FP
// load VS register
+#ifdef __LITTLE_ENDIAN__
+// For little-endian targets, we need a swap since lxvd2x will load the register
+// in the incorrect doubleword order.
+// FIXME: when supporting targets older than Power9 on LE is no longer required,
+// this can be changed to simply `lxv n, (16 * n)(4)`.
+#define PPC64_LVS(n) \
+ lxvd2x n, 0, 4 ;\
+ xxswapd n, n ;\
+ addi 4, 4, 16
+#else
#define PPC64_LVS(n) \
lxvd2x n, 0, 4 ;\
addi 4, 4, 16
+#endif
// restore the first 32 VS regs (and also all floating point regs)
PPC64_LVS(0)
@@ -222,27 +243,43 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv)
PPC64_LVS(30)
PPC64_LVS(31)
- // use VRSAVE to conditionally restore the remaining VS regs,
- // that are where the V regs are mapped
+#ifdef __LITTLE_ENDIAN__
+#define PPC64_CLVS_RESTORE(n) \
+ addi 4, 3, PPC64_OFFS_FP + n * 16 ;\
+ lxvd2x n, 0, 4 ;\
+ xxswapd n, n
+#else
+#define PPC64_CLVS_RESTORE(n) \
+ addi 4, 3, PPC64_OFFS_FP + n * 16 ;\
+ lxvd2x n, 0, 4
+#endif
+#if !defined(_AIX)
+ // use VRSAVE to conditionally restore the remaining VS regs, that are
+ // where the V regs are mapped. In the AIX ABI, VRSAVE is not used.
ld 5, PPC64_OFFS_VRSAVE(3) // test VRsave
cmpwi 5, 0
beq Lnovec
// conditionally load VS
-#define PPC64_CLVS_BOTTOM(n) \
- beq Ldone##n ;\
- addi 4, 3, PPC64_OFFS_FP + n * 16 ;\
- lxvd2x n, 0, 4 ;\
+#define PPC64_CLVSl(n) \
+ andis. 0, 5, (1 PPC_LEFT_SHIFT(47-n)) ;\
+ beq Ldone##n ;\
+ PPC64_CLVS_RESTORE(n) ;\
Ldone##n:
-#define PPC64_CLVSl(n) \
- andis. 0, 5, (1 PPC_LEFT_SHIFT(47-n)) ;\
-PPC64_CLVS_BOTTOM(n)
+#define PPC64_CLVSh(n) \
+ andi. 0, 5, (1 PPC_LEFT_SHIFT(63-n)) ;\
+ beq Ldone##n ;\
+ PPC64_CLVS_RESTORE(n) ;\
+Ldone##n:
-#define PPC64_CLVSh(n) \
- andi. 0, 5, (1 PPC_LEFT_SHIFT(63-n)) ;\
-PPC64_CLVS_BOTTOM(n)
+#else
+
+#define PPC64_CLVSl(n) PPC64_CLVS_RESTORE(n)
+#define PPC64_CLVSh(n) PPC64_CLVS_RESTORE(n)
+
+#endif // !defined(_AIX)
PPC64_CLVSl(32)
PPC64_CLVSl(33)
@@ -318,32 +355,44 @@ PPC64_CLVS_BOTTOM(n)
PPC64_LF(31)
#if defined(__ALTIVEC__)
- // restore vector registers if any are in use
+
+#define PPC64_CLV_UNALIGNED_RESTORE(n) \
+ ld 0, (PPC64_OFFS_V + n * 16)(3) ;\
+ std 0, 0(4) ;\
+ ld 0, (PPC64_OFFS_V + n * 16 + 8)(3) ;\
+ std 0, 8(4) ;\
+ lvx n, 0, 4
+
+#if !defined(_AIX)
+ // restore vector registers if any are in use. In the AIX ABI, VRSAVE is
+ // not used.
ld 5, PPC64_OFFS_VRSAVE(3) // test VRsave
cmpwi 5, 0
beq Lnovec
- subi 4, 1, 16
- // r4 is now a 16-byte aligned pointer into the red zone
- // the _vectorScalarRegisters may not be 16-byte aligned
- // so copy via red zone temp buffer
+#define PPC64_CLV_UNALIGNEDl(n) \
+ andis. 0, 5, (1 PPC_LEFT_SHIFT(15-n)) ;\
+ beq Ldone##n ;\
+ PPC64_CLV_UNALIGNED_RESTORE(n) ;\
+Ldone ## n:
-#define PPC64_CLV_UNALIGNED_BOTTOM(n) \
- beq Ldone##n ;\
- ld 0, (PPC64_OFFS_V + n * 16)(3) ;\
- std 0, 0(4) ;\
- ld 0, (PPC64_OFFS_V + n * 16 + 8)(3) ;\
- std 0, 8(4) ;\
- lvx n, 0, 4 ;\
+#define PPC64_CLV_UNALIGNEDh(n) \
+ andi. 0, 5, (1 PPC_LEFT_SHIFT(31-n)) ;\
+ beq Ldone##n ;\
+ PPC64_CLV_UNALIGNED_RESTORE(n) ;\
Ldone ## n:
-#define PPC64_CLV_UNALIGNEDl(n) \
- andis. 0, 5, (1 PPC_LEFT_SHIFT(15-n)) ;\
-PPC64_CLV_UNALIGNED_BOTTOM(n)
+#else
+
+#define PPC64_CLV_UNALIGNEDl(n) PPC64_CLV_UNALIGNED_RESTORE(n)
+#define PPC64_CLV_UNALIGNEDh(n) PPC64_CLV_UNALIGNED_RESTORE(n)
-#define PPC64_CLV_UNALIGNEDh(n) \
- andi. 0, 5, (1 PPC_LEFT_SHIFT(31-n)) ;\
-PPC64_CLV_UNALIGNED_BOTTOM(n)
+#endif // !defined(_AIX)
+
+ subi 4, 1, 16
+ // r4 is now a 16-byte aligned pointer into the red zone
+ // the _vectorScalarRegisters may not be 16-byte aligned
+ // so copy via red zone temp buffer
PPC64_CLV_UNALIGNEDl(0)
PPC64_CLV_UNALIGNEDl(1)
@@ -387,11 +436,23 @@ Lnovec:
ld 0, PPC64_OFFS_SRR0(3)
mtctr 0
+#if defined(_AIX)
+ // After setting GPR1 to a higher address, AIX wipes out the original
+ // stack space below that address invalidated by the new GPR1 value. Use
+ // GPR0 to save the value of GPR3 in the context before it is wiped out.
+ // This compromises the content of GPR0 which is a volatile register.
+ ld 0, (8 * (3 + 2))(3)
+#else
PPC64_LR(0)
+#endif
PPC64_LR(5)
PPC64_LR(4)
PPC64_LR(1)
+#if defined(_AIX)
+ mr 3, 0
+#else
PPC64_LR(3)
+#endif
bctr
#elif defined(__powerpc__)
@@ -404,7 +465,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv)
// thread_state pointer is in r3
//
- // restore integral registerrs
+ // restore integral registers
// skip r0 for now
// skip r1 for now
lwz 2, 16(3)
@@ -475,45 +536,48 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv)
#endif
#if defined(__ALTIVEC__)
- // restore vector registers if any are in use
+
+#define LOAD_VECTOR_RESTORE(_index) \
+ lwz 0, 424+_index*16(3) SEPARATOR \
+ stw 0, 0(4) SEPARATOR \
+ lwz 0, 424+_index*16+4(3) SEPARATOR \
+ stw 0, 4(4) SEPARATOR \
+ lwz 0, 424+_index*16+8(3) SEPARATOR \
+ stw 0, 8(4) SEPARATOR \
+ lwz 0, 424+_index*16+12(3) SEPARATOR \
+ stw 0, 12(4) SEPARATOR \
+ lvx _index, 0, 4
+
+#if !defined(_AIX)
+ // restore vector registers if any are in use. In the AIX ABI, VRSAVE
+ // is not used.
lwz 5, 156(3) // test VRsave
cmpwi 5, 0
beq Lnovec
- subi 4, 1, 16
- rlwinm 4, 4, 0, 0, 27 // mask low 4-bits
- // r4 is now a 16-byte aligned pointer into the red zone
- // the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer
-
-
-#define LOAD_VECTOR_UNALIGNEDl(_index) \
- andis. 0, 5, (1 PPC_LEFT_SHIFT(15-_index)) SEPARATOR \
- beq Ldone ## _index SEPARATOR \
- lwz 0, 424+_index*16(3) SEPARATOR \
- stw 0, 0(%r4) SEPARATOR \
- lwz 0, 424+_index*16+4(%r3) SEPARATOR \
- stw 0, 4(%r4) SEPARATOR \
- lwz 0, 424+_index*16+8(%r3) SEPARATOR \
- stw 0, 8(%r4) SEPARATOR \
- lwz 0, 424+_index*16+12(%r3) SEPARATOR \
- stw 0, 12(%r4) SEPARATOR \
- lvx _index, 0, 4 SEPARATOR \
+#define LOAD_VECTOR_UNALIGNEDl(_index) \
+ andis. 0, 5, (1 PPC_LEFT_SHIFT(15-_index)) SEPARATOR \
+ beq Ldone ## _index SEPARATOR \
+ LOAD_VECTOR_RESTORE(_index) SEPARATOR \
Ldone ## _index:
-#define LOAD_VECTOR_UNALIGNEDh(_index) \
- andi. 0, 5, (1 PPC_LEFT_SHIFT(31-_index)) SEPARATOR \
- beq Ldone ## _index SEPARATOR \
- lwz 0, 424+_index*16(3) SEPARATOR \
- stw 0, 0(4) SEPARATOR \
- lwz 0, 424+_index*16+4(3) SEPARATOR \
- stw 0, 4(4) SEPARATOR \
- lwz 0, 424+_index*16+8(3) SEPARATOR \
- stw 0, 8(%r4) SEPARATOR \
- lwz 0, 424+_index*16+12(3) SEPARATOR \
- stw 0, 12(4) SEPARATOR \
- lvx _index, 0, 4 SEPARATOR \
+#define LOAD_VECTOR_UNALIGNEDh(_index) \
+ andi. 0, 5, (1 PPC_LEFT_SHIFT(31-_index)) SEPARATOR \
+ beq Ldone ## _index SEPARATOR \
+ LOAD_VECTOR_RESTORE(_index) SEPARATOR \
Ldone ## _index:
+#else
+
+#define LOAD_VECTOR_UNALIGNEDl(_index) LOAD_VECTOR_RESTORE(_index)
+#define LOAD_VECTOR_UNALIGNEDh(_index) LOAD_VECTOR_RESTORE(_index)
+
+#endif // !defined(_AIX)
+
+ subi 4, 1, 16
+ rlwinm 4, 4, 0, 0, 27 // mask low 4-bits
+ // r4 is now a 16-byte aligned pointer into the red zone
+ // the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer
LOAD_VECTOR_UNALIGNEDl(0)
LOAD_VECTOR_UNALIGNEDl(1)
@@ -609,7 +673,7 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
ldr d30, [x0, #0x200]
ldr d31, [x0, #0x208]
- // Finally, restore sp. This must be done after the the last read from the
+ // Finally, restore sp. This must be done after 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.
@@ -929,11 +993,13 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind18Registers_mips_o326jumptoEv)
ldc1 $f31, (4 * 36 + 8 * 31)($4)
#endif
#endif
+#if __mips_isa_rev < 6
// restore hi and lo
lw $8, (4 * 33)($4)
mthi $8
lw $8, (4 * 34)($4)
mtlo $8
+#endif
// r0 is zero
lw $1, (4 * 1)($4)
lw $2, (4 * 2)($4)
@@ -986,75 +1052,25 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv)
.set noreorder
.set nomacro
#ifdef __mips_hard_float
- ldc1 $f0, (8 * 35)($4)
- ldc1 $f1, (8 * 36)($4)
- ldc1 $f2, (8 * 37)($4)
- ldc1 $f3, (8 * 38)($4)
- ldc1 $f4, (8 * 39)($4)
- ldc1 $f5, (8 * 40)($4)
- ldc1 $f6, (8 * 41)($4)
- ldc1 $f7, (8 * 42)($4)
- ldc1 $f8, (8 * 43)($4)
- ldc1 $f9, (8 * 44)($4)
- ldc1 $f10, (8 * 45)($4)
- ldc1 $f11, (8 * 46)($4)
- ldc1 $f12, (8 * 47)($4)
- ldc1 $f13, (8 * 48)($4)
- ldc1 $f14, (8 * 49)($4)
- ldc1 $f15, (8 * 50)($4)
- ldc1 $f16, (8 * 51)($4)
- ldc1 $f17, (8 * 52)($4)
- ldc1 $f18, (8 * 53)($4)
- ldc1 $f19, (8 * 54)($4)
- ldc1 $f20, (8 * 55)($4)
- ldc1 $f21, (8 * 56)($4)
- ldc1 $f22, (8 * 57)($4)
- ldc1 $f23, (8 * 58)($4)
- ldc1 $f24, (8 * 59)($4)
- ldc1 $f25, (8 * 60)($4)
- ldc1 $f26, (8 * 61)($4)
- ldc1 $f27, (8 * 62)($4)
- ldc1 $f28, (8 * 63)($4)
- ldc1 $f29, (8 * 64)($4)
- ldc1 $f30, (8 * 65)($4)
- ldc1 $f31, (8 * 66)($4)
+ .irp i,FROM_0_TO_31
+ ldc1 $f\i, (280+8*\i)($4)
+ .endr
#endif
+#if __mips_isa_rev < 6
// restore hi and lo
ld $8, (8 * 33)($4)
mthi $8
ld $8, (8 * 34)($4)
mtlo $8
+#endif
// r0 is zero
ld $1, (8 * 1)($4)
ld $2, (8 * 2)($4)
ld $3, (8 * 3)($4)
// skip a0 for now
- ld $5, (8 * 5)($4)
- ld $6, (8 * 6)($4)
- ld $7, (8 * 7)($4)
- ld $8, (8 * 8)($4)
- ld $9, (8 * 9)($4)
- ld $10, (8 * 10)($4)
- ld $11, (8 * 11)($4)
- ld $12, (8 * 12)($4)
- ld $13, (8 * 13)($4)
- ld $14, (8 * 14)($4)
- ld $15, (8 * 15)($4)
- ld $16, (8 * 16)($4)
- ld $17, (8 * 17)($4)
- ld $18, (8 * 18)($4)
- ld $19, (8 * 19)($4)
- ld $20, (8 * 20)($4)
- ld $21, (8 * 21)($4)
- ld $22, (8 * 22)($4)
- ld $23, (8 * 23)($4)
- ld $24, (8 * 24)($4)
- ld $25, (8 * 25)($4)
- ld $26, (8 * 26)($4)
- ld $27, (8 * 27)($4)
- ld $28, (8 * 28)($4)
- ld $29, (8 * 29)($4)
- ld $30, (8 * 30)($4)
+ .irp i,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
+ ld $\i, (8 * \i)($4)
+ .endr
// load new pc into ra
ld $31, (8 * 32)($4)
// jump to ra, load a0 in the delay slot
@@ -1142,76 +1158,78 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv)
.p2align 2
DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv)
# if defined(__riscv_flen)
- FLOAD f0, (RISCV_FOFFSET + RISCV_FSIZE * 0)(a0)
- FLOAD f1, (RISCV_FOFFSET + RISCV_FSIZE * 1)(a0)
- FLOAD f2, (RISCV_FOFFSET + RISCV_FSIZE * 2)(a0)
- FLOAD f3, (RISCV_FOFFSET + RISCV_FSIZE * 3)(a0)
- FLOAD f4, (RISCV_FOFFSET + RISCV_FSIZE * 4)(a0)
- FLOAD f5, (RISCV_FOFFSET + RISCV_FSIZE * 5)(a0)
- FLOAD f6, (RISCV_FOFFSET + RISCV_FSIZE * 6)(a0)
- FLOAD f7, (RISCV_FOFFSET + RISCV_FSIZE * 7)(a0)
- FLOAD f8, (RISCV_FOFFSET + RISCV_FSIZE * 8)(a0)
- FLOAD f9, (RISCV_FOFFSET + RISCV_FSIZE * 9)(a0)
- FLOAD f10, (RISCV_FOFFSET + RISCV_FSIZE * 10)(a0)
- FLOAD f11, (RISCV_FOFFSET + RISCV_FSIZE * 11)(a0)
- FLOAD f12, (RISCV_FOFFSET + RISCV_FSIZE * 12)(a0)
- FLOAD f13, (RISCV_FOFFSET + RISCV_FSIZE * 13)(a0)
- FLOAD f14, (RISCV_FOFFSET + RISCV_FSIZE * 14)(a0)
- FLOAD f15, (RISCV_FOFFSET + RISCV_FSIZE * 15)(a0)
- FLOAD f16, (RISCV_FOFFSET + RISCV_FSIZE * 16)(a0)
- FLOAD f17, (RISCV_FOFFSET + RISCV_FSIZE * 17)(a0)
- FLOAD f18, (RISCV_FOFFSET + RISCV_FSIZE * 18)(a0)
- FLOAD f19, (RISCV_FOFFSET + RISCV_FSIZE * 19)(a0)
- FLOAD f20, (RISCV_FOFFSET + RISCV_FSIZE * 20)(a0)
- FLOAD f21, (RISCV_FOFFSET + RISCV_FSIZE * 21)(a0)
- FLOAD f22, (RISCV_FOFFSET + RISCV_FSIZE * 22)(a0)
- FLOAD f23, (RISCV_FOFFSET + RISCV_FSIZE * 23)(a0)
- FLOAD f24, (RISCV_FOFFSET + RISCV_FSIZE * 24)(a0)
- FLOAD f25, (RISCV_FOFFSET + RISCV_FSIZE * 25)(a0)
- FLOAD f26, (RISCV_FOFFSET + RISCV_FSIZE * 26)(a0)
- FLOAD f27, (RISCV_FOFFSET + RISCV_FSIZE * 27)(a0)
- FLOAD f28, (RISCV_FOFFSET + RISCV_FSIZE * 28)(a0)
- FLOAD f29, (RISCV_FOFFSET + RISCV_FSIZE * 29)(a0)
- FLOAD f30, (RISCV_FOFFSET + RISCV_FSIZE * 30)(a0)
- FLOAD f31, (RISCV_FOFFSET + RISCV_FSIZE * 31)(a0)
+ .irp i,FROM_0_TO_31
+ FLOAD f\i, (RISCV_FOFFSET + RISCV_FSIZE * \i)(a0)
+ .endr
# endif
// x0 is zero
ILOAD x1, (RISCV_ISIZE * 0)(a0) // restore pc into ra
- ILOAD x2, (RISCV_ISIZE * 2)(a0)
- ILOAD x3, (RISCV_ISIZE * 3)(a0)
- ILOAD x4, (RISCV_ISIZE * 4)(a0)
- ILOAD x5, (RISCV_ISIZE * 5)(a0)
- ILOAD x6, (RISCV_ISIZE * 6)(a0)
- ILOAD x7, (RISCV_ISIZE * 7)(a0)
- ILOAD x8, (RISCV_ISIZE * 8)(a0)
- ILOAD x9, (RISCV_ISIZE * 9)(a0)
+ .irp i,2,3,4,5,6,7,8,9
+ ILOAD x\i, (RISCV_ISIZE * \i)(a0)
+ .endr
// skip a0 for now
- ILOAD x11, (RISCV_ISIZE * 11)(a0)
- ILOAD x12, (RISCV_ISIZE * 12)(a0)
- ILOAD x13, (RISCV_ISIZE * 13)(a0)
- ILOAD x14, (RISCV_ISIZE * 14)(a0)
- ILOAD x15, (RISCV_ISIZE * 15)(a0)
- ILOAD x16, (RISCV_ISIZE * 16)(a0)
- ILOAD x17, (RISCV_ISIZE * 17)(a0)
- ILOAD x18, (RISCV_ISIZE * 18)(a0)
- ILOAD x19, (RISCV_ISIZE * 19)(a0)
- ILOAD x20, (RISCV_ISIZE * 20)(a0)
- ILOAD x21, (RISCV_ISIZE * 21)(a0)
- ILOAD x22, (RISCV_ISIZE * 22)(a0)
- ILOAD x23, (RISCV_ISIZE * 23)(a0)
- ILOAD x24, (RISCV_ISIZE * 24)(a0)
- ILOAD x25, (RISCV_ISIZE * 25)(a0)
- ILOAD x26, (RISCV_ISIZE * 26)(a0)
- ILOAD x27, (RISCV_ISIZE * 27)(a0)
- ILOAD x28, (RISCV_ISIZE * 28)(a0)
- ILOAD x29, (RISCV_ISIZE * 29)(a0)
- ILOAD x30, (RISCV_ISIZE * 30)(a0)
- ILOAD x31, (RISCV_ISIZE * 31)(a0)
+ .irp i,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+ ILOAD x\i, (RISCV_ISIZE * \i)(a0)
+ .endr
ILOAD x10, (RISCV_ISIZE * 10)(a0) // restore a0
ret // jump to ra
+#elif defined(__s390x__)
+
+DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_s390x6jumptoEv)
+//
+// void libunwind::Registers_s390x::jumpto()
+//
+// On entry:
+// thread_state pointer is in r2
+//
+
+ // Skip PSWM, but load PSWA into r1
+ lg %r1, 8(%r2)
+
+ // Restore FPRs
+ .irp i,FROM_0_TO_15
+ ld %f\i, (144+8*\i)(%r2)
+ .endr
+
+ // Restore GPRs - skipping %r0 and %r1
+ lmg %r2, %r15, 32(%r2)
+
+ // Return to PSWA (was loaded into %r1 above)
+ br %r1
+
+#elif defined(__loongarch__) && __loongarch_grlen == 64
+
+//
+// void libunwind::Registers_loongarch::jumpto()
+//
+// On entry:
+// thread_state pointer is in $a0($r4)
+//
+ .p2align 2
+DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind19Registers_loongarch6jumptoEv)
+# if __loongarch_frlen == 64
+ .irp i,FROM_0_TO_31
+ fld.d $f\i, $a0, (8 * 33 + 8 * \i)
+ .endr
+# endif
+
+ // $r0 is zero
+ .irp i,1,2,3
+ ld.d $r\i, $a0, (8 * \i)
+ .endr
+ // skip $a0 for now
+ .irp i,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+ ld.d $r\i, $a0, (8 * \i)
+ .endr
+
+ ld.d $ra, $a0, (8 * 32) // load new pc into $ra
+ ld.d $a0, $a0, (8 * 4) // restore $a0 last
+
+ jr $ra
+
#endif
#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
diff --git a/contrib/libs/libunwind/src/UnwindRegistersSave.S b/contrib/libs/libunwind/src/UnwindRegistersSave.S
index b39489235c..19a0e87d68 100644
--- a/contrib/libs/libunwind/src/UnwindRegistersSave.S
+++ b/contrib/libs/libunwind/src/UnwindRegistersSave.S
@@ -8,7 +8,17 @@
#include "assembly.h"
+#define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+#define FROM_16_TO_31 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+
+#define FROM_0_TO_31 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+#define FROM_32_TO_63 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63
+
+#if defined(_AIX)
+ .toc
+#else
.text
+#endif
#if !defined(__USING_SJLJ_EXCEPTIONS__)
@@ -164,11 +174,13 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
sw $31, (4 * 31)($4)
# Store return address to pc
sw $31, (4 * 32)($4)
+#if __mips_isa_rev < 6
# hi and lo
mfhi $8
sw $8, (4 * 33)($4)
mflo $8
sw $8, (4 * 34)($4)
+#endif
#ifdef __mips_hard_float
#if __mips_fpr != 64
sdc1 $f0, (4 * 36 + 8 * 0)($4)
@@ -240,77 +252,22 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
.set noat
.set noreorder
.set nomacro
- sd $1, (8 * 1)($4)
- sd $2, (8 * 2)($4)
- sd $3, (8 * 3)($4)
- sd $4, (8 * 4)($4)
- sd $5, (8 * 5)($4)
- sd $6, (8 * 6)($4)
- sd $7, (8 * 7)($4)
- sd $8, (8 * 8)($4)
- sd $9, (8 * 9)($4)
- sd $10, (8 * 10)($4)
- sd $11, (8 * 11)($4)
- sd $12, (8 * 12)($4)
- sd $13, (8 * 13)($4)
- sd $14, (8 * 14)($4)
- sd $15, (8 * 15)($4)
- sd $16, (8 * 16)($4)
- sd $17, (8 * 17)($4)
- sd $18, (8 * 18)($4)
- sd $19, (8 * 19)($4)
- sd $20, (8 * 20)($4)
- sd $21, (8 * 21)($4)
- sd $22, (8 * 22)($4)
- sd $23, (8 * 23)($4)
- sd $24, (8 * 24)($4)
- sd $25, (8 * 25)($4)
- sd $26, (8 * 26)($4)
- sd $27, (8 * 27)($4)
- sd $28, (8 * 28)($4)
- sd $29, (8 * 29)($4)
- sd $30, (8 * 30)($4)
- sd $31, (8 * 31)($4)
+ .irp i,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+ sd $\i, (8 * \i)($4)
+ .endr
# Store return address to pc
sd $31, (8 * 32)($4)
+#if __mips_isa_rev < 6
# hi and lo
mfhi $8
sd $8, (8 * 33)($4)
mflo $8
sd $8, (8 * 34)($4)
+#endif
#ifdef __mips_hard_float
- sdc1 $f0, (8 * 35)($4)
- sdc1 $f1, (8 * 36)($4)
- sdc1 $f2, (8 * 37)($4)
- sdc1 $f3, (8 * 38)($4)
- sdc1 $f4, (8 * 39)($4)
- sdc1 $f5, (8 * 40)($4)
- sdc1 $f6, (8 * 41)($4)
- sdc1 $f7, (8 * 42)($4)
- sdc1 $f8, (8 * 43)($4)
- sdc1 $f9, (8 * 44)($4)
- sdc1 $f10, (8 * 45)($4)
- sdc1 $f11, (8 * 46)($4)
- sdc1 $f12, (8 * 47)($4)
- sdc1 $f13, (8 * 48)($4)
- sdc1 $f14, (8 * 49)($4)
- sdc1 $f15, (8 * 50)($4)
- sdc1 $f16, (8 * 51)($4)
- sdc1 $f17, (8 * 52)($4)
- sdc1 $f18, (8 * 53)($4)
- sdc1 $f19, (8 * 54)($4)
- sdc1 $f20, (8 * 55)($4)
- sdc1 $f21, (8 * 56)($4)
- sdc1 $f22, (8 * 57)($4)
- sdc1 $f23, (8 * 58)($4)
- sdc1 $f24, (8 * 59)($4)
- sdc1 $f25, (8 * 60)($4)
- sdc1 $f26, (8 * 61)($4)
- sdc1 $f27, (8 * 62)($4)
- sdc1 $f28, (8 * 63)($4)
- sdc1 $f29, (8 * 64)($4)
- sdc1 $f30, (8 * 65)($4)
- sdc1 $f31, (8 * 66)($4)
+ .irp i,FROM_0_TO_31
+ sdc1 $f\i, (280+8*\i)($4)
+ .endr
#endif
jr $31
# return UNW_ESUCCESS
@@ -334,8 +291,11 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
// On entry:
// thread_state pointer is in r3
//
+#if defined(_AIX)
+DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(__unw_getcontext, unw_getcontext)
+#else
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
-
+#endif
// store register (GPR)
#define PPC64_STR(n) \
std n, (8 * (n + 2))(3)
@@ -345,9 +305,21 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
mflr 0
std 0, PPC64_OFFS_SRR0(3) // store lr as ssr0
PPC64_STR(1)
+ PPC64_STR(4) // Save r4 first since it will be used for fixing r2.
+#if defined(_AIX)
+ // The TOC register (r2) was changed by the glue code if unw_getcontext
+ // is called from a different module. Save the original TOC register
+ // in the context if this is the case.
+ mflr 4
+ lwz 4, 0(4) // Get the first instruction at the return address.
+ xoris 0, 4, 0xe841 // Is it reloading the TOC register "ld 2,40(1)"?
+ cmplwi 0, 0x28
+ bne 0, LnoR2Fix // No need to fix up r2 if it is not.
+ ld 2, 40(1) // Use the saved TOC register in the stack.
+LnoR2Fix:
+#endif
PPC64_STR(2)
PPC64_STR(3)
- PPC64_STR(4)
PPC64_STR(5)
PPC64_STR(6)
PPC64_STR(7)
@@ -380,7 +352,12 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
std 0, PPC64_OFFS_CR(3)
mfxer 0
std 0, PPC64_OFFS_XER(3)
+#if defined(_AIX)
+ // LR value saved from the register is not used, initialize it to 0.
+ li 0, 0
+#else
mflr 0
+#endif
std 0, PPC64_OFFS_LR(3)
mfctr 0
std 0, PPC64_OFFS_CTR(3)
@@ -395,9 +372,20 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
addi 4, 3, PPC64_OFFS_FP
// store VS register
+#ifdef __LITTLE_ENDIAN__
+// For little-endian targets, we need a swap since stxvd2x will store the
+// register in the incorrect doubleword order.
+// FIXME: when supporting targets older than Power9 on LE is no longer required
+// this can be changed to simply `stxv n, 16 * n(4)`.
#define PPC64_STVS(n) \
+ xxswapd n, n ;\
stxvd2x n, 0, 4 ;\
addi 4, 4, 16
+#else
+#define PPC64_STVS(n) \
+ stxvd2x n, 0, 4 ;\
+ addi 4, 4, 16
+#endif
PPC64_STVS(0)
PPC64_STVS(1)
@@ -567,14 +555,30 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
// On entry:
// thread_state pointer is in r3
//
+#if defined(_AIX)
+DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(__unw_getcontext, unw_getcontext)
+#else
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
+#endif
stw 0, 8(3)
mflr 0
stw 0, 0(3) // store lr as ssr0
stw 1, 12(3)
+ stw 4, 24(3) // Save r4 first since it will be used for fixing r2.
+#if defined(_AIX)
+ // The TOC register (r2) was changed by the glue code if unw_getcontext
+ // is called from a different module. Save the original TOC register
+ // in the context if this is the case.
+ mflr 4
+ lwz 4, 0(4) // Get the instruction at the return address.
+ xoris 0, 4, 0x8041 // Is it reloading the TOC register "lwz 2,20(1)"?
+ cmplwi 0, 0x14
+ bne 0, LnoR2Fix // No need to fix up r2 if it is not.
+ lwz 2, 20(1) // Use the saved TOC register in the stack.
+LnoR2Fix:
+#endif
stw 2, 16(3)
stw 3, 20(3)
- stw 4, 24(3)
stw 5, 28(3)
stw 6, 32(3)
stw 7, 36(3)
@@ -611,6 +615,11 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
// save CR registers
mfcr 0
stw 0, 136(3)
+#if defined(_AIX)
+ // LR value from the register is not used, initialize it to 0.
+ li 0, 0
+ stw 0, 144(3)
+#endif
// save CTR register
mfctr 0
stw 0, 148(3)
@@ -771,7 +780,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
@
@ On entry:
@ thread_state pointer is in r0
-@
+@
@ Per EHABI #4.7 this only saves the core integer registers.
@ EHABI #7.4.5 notes that in general all VRS registers should be restored
@ however this is very hard to do for VFP registers because it is unknown
@@ -1099,75 +1108,71 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
#
DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
ISTORE x1, (RISCV_ISIZE * 0)(a0) // store ra as pc
- ISTORE x1, (RISCV_ISIZE * 1)(a0)
- ISTORE x2, (RISCV_ISIZE * 2)(a0)
- ISTORE x3, (RISCV_ISIZE * 3)(a0)
- ISTORE x4, (RISCV_ISIZE * 4)(a0)
- ISTORE x5, (RISCV_ISIZE * 5)(a0)
- ISTORE x6, (RISCV_ISIZE * 6)(a0)
- ISTORE x7, (RISCV_ISIZE * 7)(a0)
- ISTORE x8, (RISCV_ISIZE * 8)(a0)
- ISTORE x9, (RISCV_ISIZE * 9)(a0)
- ISTORE x10, (RISCV_ISIZE * 10)(a0)
- ISTORE x11, (RISCV_ISIZE * 11)(a0)
- ISTORE x12, (RISCV_ISIZE * 12)(a0)
- ISTORE x13, (RISCV_ISIZE * 13)(a0)
- ISTORE x14, (RISCV_ISIZE * 14)(a0)
- ISTORE x15, (RISCV_ISIZE * 15)(a0)
- ISTORE x16, (RISCV_ISIZE * 16)(a0)
- ISTORE x17, (RISCV_ISIZE * 17)(a0)
- ISTORE x18, (RISCV_ISIZE * 18)(a0)
- ISTORE x19, (RISCV_ISIZE * 19)(a0)
- ISTORE x20, (RISCV_ISIZE * 20)(a0)
- ISTORE x21, (RISCV_ISIZE * 21)(a0)
- ISTORE x22, (RISCV_ISIZE * 22)(a0)
- ISTORE x23, (RISCV_ISIZE * 23)(a0)
- ISTORE x24, (RISCV_ISIZE * 24)(a0)
- ISTORE x25, (RISCV_ISIZE * 25)(a0)
- ISTORE x26, (RISCV_ISIZE * 26)(a0)
- ISTORE x27, (RISCV_ISIZE * 27)(a0)
- ISTORE x28, (RISCV_ISIZE * 28)(a0)
- ISTORE x29, (RISCV_ISIZE * 29)(a0)
- ISTORE x30, (RISCV_ISIZE * 30)(a0)
- ISTORE x31, (RISCV_ISIZE * 31)(a0)
+ .irp i,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+ ISTORE x\i, (RISCV_ISIZE * \i)(a0)
+ .endr
# if defined(__riscv_flen)
- FSTORE f0, (RISCV_FOFFSET + RISCV_FSIZE * 0)(a0)
- FSTORE f1, (RISCV_FOFFSET + RISCV_FSIZE * 1)(a0)
- FSTORE f2, (RISCV_FOFFSET + RISCV_FSIZE * 2)(a0)
- FSTORE f3, (RISCV_FOFFSET + RISCV_FSIZE * 3)(a0)
- FSTORE f4, (RISCV_FOFFSET + RISCV_FSIZE * 4)(a0)
- FSTORE f5, (RISCV_FOFFSET + RISCV_FSIZE * 5)(a0)
- FSTORE f6, (RISCV_FOFFSET + RISCV_FSIZE * 6)(a0)
- FSTORE f7, (RISCV_FOFFSET + RISCV_FSIZE * 7)(a0)
- FSTORE f8, (RISCV_FOFFSET + RISCV_FSIZE * 8)(a0)
- FSTORE f9, (RISCV_FOFFSET + RISCV_FSIZE * 9)(a0)
- FSTORE f10, (RISCV_FOFFSET + RISCV_FSIZE * 10)(a0)
- FSTORE f11, (RISCV_FOFFSET + RISCV_FSIZE * 11)(a0)
- FSTORE f12, (RISCV_FOFFSET + RISCV_FSIZE * 12)(a0)
- FSTORE f13, (RISCV_FOFFSET + RISCV_FSIZE * 13)(a0)
- FSTORE f14, (RISCV_FOFFSET + RISCV_FSIZE * 14)(a0)
- FSTORE f15, (RISCV_FOFFSET + RISCV_FSIZE * 15)(a0)
- FSTORE f16, (RISCV_FOFFSET + RISCV_FSIZE * 16)(a0)
- FSTORE f17, (RISCV_FOFFSET + RISCV_FSIZE * 17)(a0)
- FSTORE f18, (RISCV_FOFFSET + RISCV_FSIZE * 18)(a0)
- FSTORE f19, (RISCV_FOFFSET + RISCV_FSIZE * 19)(a0)
- FSTORE f20, (RISCV_FOFFSET + RISCV_FSIZE * 20)(a0)
- FSTORE f21, (RISCV_FOFFSET + RISCV_FSIZE * 21)(a0)
- FSTORE f22, (RISCV_FOFFSET + RISCV_FSIZE * 22)(a0)
- FSTORE f23, (RISCV_FOFFSET + RISCV_FSIZE * 23)(a0)
- FSTORE f24, (RISCV_FOFFSET + RISCV_FSIZE * 24)(a0)
- FSTORE f25, (RISCV_FOFFSET + RISCV_FSIZE * 25)(a0)
- FSTORE f26, (RISCV_FOFFSET + RISCV_FSIZE * 26)(a0)
- FSTORE f27, (RISCV_FOFFSET + RISCV_FSIZE * 27)(a0)
- FSTORE f28, (RISCV_FOFFSET + RISCV_FSIZE * 28)(a0)
- FSTORE f29, (RISCV_FOFFSET + RISCV_FSIZE * 29)(a0)
- FSTORE f30, (RISCV_FOFFSET + RISCV_FSIZE * 30)(a0)
- FSTORE f31, (RISCV_FOFFSET + RISCV_FSIZE * 31)(a0)
+ .irp i,FROM_0_TO_31
+ FSTORE f\i, (RISCV_FOFFSET + RISCV_FSIZE * \i)(a0)
+ .endr
# endif
li a0, 0 // return UNW_ESUCCESS
ret // jump to ra
+
+#elif defined(__s390x__)
+
+//
+// extern int __unw_getcontext(unw_context_t* thread_state)
+//
+// On entry:
+// thread_state pointer is in r2
+//
+DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
+
+ // Save GPRs
+ stmg %r0, %r15, 16(%r2)
+
+ // Save PSWM
+ epsw %r0, %r1
+ stm %r0, %r1, 0(%r2)
+
+ // Store return address as PSWA
+ stg %r14, 8(%r2)
+
+ // Save FPRs
+ .irp i,FROM_0_TO_15
+ std %f\i, (144+8*\i)(%r2)
+ .endr
+
+ // Return UNW_ESUCCESS
+ lghi %r2, 0
+ br %r14
+
+#elif defined(__loongarch__) && __loongarch_grlen == 64
+
+#
+# extern int __unw_getcontext(unw_context_t* thread_state)
+#
+# On entry:
+# thread_state pointer is in $a0($r4)
+#
+DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
+ .irp i,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+ st.d $r\i, $a0, (8*\i)
+ .endr
+ st.d $r1, $a0, (8 * 32) // store $ra to pc
+
+# if __loongarch_frlen == 64
+ .irp i,FROM_0_TO_31
+ fst.d $f\i, $a0, (8 * 33 + 8 * \i)
+ .endr
+# endif
+
+ move $a0, $zero // UNW_ESUCCESS
+ jr $ra
+
#endif
WEAK_ALIAS(__unw_getcontext, unw_getcontext)
diff --git a/contrib/libs/libunwind/src/Unwind_AppleExtras.cpp b/contrib/libs/libunwind/src/Unwind_AppleExtras.cpp
deleted file mode 100644
index ffb49a89e5..0000000000
--- a/contrib/libs/libunwind/src/Unwind_AppleExtras.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//
-//===----------------------------------------------------------------------===//
-
-#include "config.h"
-
-
-// static linker symbols to prevent wrong two level namespace for _Unwind symbols
-#if defined(__arm__)
- #define NOT_HERE_BEFORE_5_0(sym) \
- extern const char sym##_tmp30 __asm("$ld$hide$os3.0$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp30 = 0; \
- extern const char sym##_tmp31 __asm("$ld$hide$os3.1$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp31 = 0; \
- extern const char sym##_tmp32 __asm("$ld$hide$os3.2$_" #sym );\
- __attribute__((visibility("default"))) const char sym##_tmp32 = 0; \
- extern const char sym##_tmp40 __asm("$ld$hide$os4.0$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp40 = 0; \
- extern const char sym##_tmp41 __asm("$ld$hide$os4.1$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp41 = 0; \
- extern const char sym##_tmp42 __asm("$ld$hide$os4.2$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp42 = 0; \
- extern const char sym##_tmp43 __asm("$ld$hide$os4.3$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp43 = 0;
-#elif defined(__aarch64__)
- #define NOT_HERE_BEFORE_10_6(sym)
- #define NEVER_HERE(sym)
-#else
- #define NOT_HERE_BEFORE_10_6(sym) \
- extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
- extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp5 = 0;
- #define NEVER_HERE(sym) \
- extern const char sym##_tmp4 __asm("$ld$hide$os10.4$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \
- extern const char sym##_tmp5 __asm("$ld$hide$os10.5$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp5 = 0; \
- extern const char sym##_tmp6 __asm("$ld$hide$os10.6$_" #sym ); \
- __attribute__((visibility("default"))) const char sym##_tmp6 = 0;
-#endif
-
-
-#if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
-
-//
-// symbols in libSystem.dylib in 10.6 and later, but are in libgcc_s.dylib in
-// earlier versions
-//
-NOT_HERE_BEFORE_10_6(_Unwind_DeleteException)
-NOT_HERE_BEFORE_10_6(_Unwind_Find_FDE)
-NOT_HERE_BEFORE_10_6(_Unwind_ForcedUnwind)
-NOT_HERE_BEFORE_10_6(_Unwind_GetGR)
-NOT_HERE_BEFORE_10_6(_Unwind_GetIP)
-NOT_HERE_BEFORE_10_6(_Unwind_GetLanguageSpecificData)
-NOT_HERE_BEFORE_10_6(_Unwind_GetRegionStart)
-NOT_HERE_BEFORE_10_6(_Unwind_RaiseException)
-NOT_HERE_BEFORE_10_6(_Unwind_Resume)
-NOT_HERE_BEFORE_10_6(_Unwind_SetGR)
-NOT_HERE_BEFORE_10_6(_Unwind_SetIP)
-NOT_HERE_BEFORE_10_6(_Unwind_Backtrace)
-NOT_HERE_BEFORE_10_6(_Unwind_FindEnclosingFunction)
-NOT_HERE_BEFORE_10_6(_Unwind_GetCFA)
-NOT_HERE_BEFORE_10_6(_Unwind_GetDataRelBase)
-NOT_HERE_BEFORE_10_6(_Unwind_GetTextRelBase)
-NOT_HERE_BEFORE_10_6(_Unwind_Resume_or_Rethrow)
-NOT_HERE_BEFORE_10_6(_Unwind_GetIPInfo)
-NOT_HERE_BEFORE_10_6(__register_frame)
-NOT_HERE_BEFORE_10_6(__deregister_frame)
-
-//
-// symbols in libSystem.dylib for compatibility, but we don't want any new code
-// using them
-//
-NEVER_HERE(__register_frame_info_bases)
-NEVER_HERE(__register_frame_info)
-NEVER_HERE(__register_frame_info_table_bases)
-NEVER_HERE(__register_frame_info_table)
-NEVER_HERE(__register_frame_table)
-NEVER_HERE(__deregister_frame_info)
-NEVER_HERE(__deregister_frame_info_bases)
-
-#endif // defined(_LIBUNWIND_BUILD_ZERO_COST_APIS)
-
-
-
-
-#if defined(_LIBUNWIND_BUILD_SJLJ_APIS)
-//
-// symbols in libSystem.dylib in iOS 5.0 and later, but are in libgcc_s.dylib in
-// earlier versions
-//
-NOT_HERE_BEFORE_5_0(_Unwind_GetLanguageSpecificData)
-NOT_HERE_BEFORE_5_0(_Unwind_GetRegionStart)
-NOT_HERE_BEFORE_5_0(_Unwind_GetIP)
-NOT_HERE_BEFORE_5_0(_Unwind_SetGR)
-NOT_HERE_BEFORE_5_0(_Unwind_SetIP)
-NOT_HERE_BEFORE_5_0(_Unwind_DeleteException)
-NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Register)
-NOT_HERE_BEFORE_5_0(_Unwind_GetGR)
-NOT_HERE_BEFORE_5_0(_Unwind_GetIPInfo)
-NOT_HERE_BEFORE_5_0(_Unwind_GetCFA)
-NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume)
-NOT_HERE_BEFORE_5_0(_Unwind_SjLj_RaiseException)
-NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume_or_Rethrow)
-NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Unregister)
-
-#endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS)
diff --git a/contrib/libs/libunwind/src/assembly.h b/contrib/libs/libunwind/src/assembly.h
index 89293a555b..fb07d04071 100644
--- a/contrib/libs/libunwind/src/assembly.h
+++ b/contrib/libs/libunwind/src/assembly.h
@@ -67,7 +67,8 @@
#define SEPARATOR ;
#endif
-#if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1)
+#if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1) && \
+ !defined(_AIX)
#define PPC64_OPD1 .section .opd,"aw",@progbits SEPARATOR
#define PPC64_OPD2 SEPARATOR \
.p2align 3 SEPARATOR \
@@ -203,12 +204,57 @@
#elif defined(__sparc__)
+#elif defined(_AIX)
+
+#if defined(__powerpc64__)
+#define VBYTE_LEN 8
+#define CSECT_ALIGN 3
+#else
+#define VBYTE_LEN 4
+#define CSECT_ALIGN 2
+#endif
+
+// clang-format off
+#define DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(name, aliasname) \
+ .csect .text[PR], 2 SEPARATOR \
+ .csect .name[PR], 2 SEPARATOR \
+ .globl name[DS] SEPARATOR \
+ .globl .name[PR] SEPARATOR \
+ .align 4 SEPARATOR \
+ .csect name[DS], CSECT_ALIGN SEPARATOR \
+aliasname: \
+ .vbyte VBYTE_LEN, .name[PR] SEPARATOR \
+ .vbyte VBYTE_LEN, TOC[TC0] SEPARATOR \
+ .vbyte VBYTE_LEN, 0 SEPARATOR \
+ .weak aliasname SEPARATOR \
+ .weak .aliasname SEPARATOR \
+ .csect .name[PR], 2 SEPARATOR \
+.aliasname: \
+
+#define WEAK_ALIAS(name, aliasname)
+#define NO_EXEC_STACK_DIRECTIVE
+
+// clang-format on
#else
#error Unsupported target
#endif
+#if defined(_AIX)
+ // clang-format off
+#define DEFINE_LIBUNWIND_FUNCTION(name) \
+ .globl name[DS] SEPARATOR \
+ .globl .name SEPARATOR \
+ .align 4 SEPARATOR \
+ .csect name[DS], CSECT_ALIGN SEPARATOR \
+ .vbyte VBYTE_LEN, .name SEPARATOR \
+ .vbyte VBYTE_LEN, TOC[TC0] SEPARATOR \
+ .vbyte VBYTE_LEN, 0 SEPARATOR \
+ .csect .text[PR], 2 SEPARATOR \
+.name:
+ // clang-format on
+#else
#define DEFINE_LIBUNWIND_FUNCTION(name) \
.globl SYMBOL_NAME(name) SEPARATOR \
HIDDEN_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
@@ -217,6 +263,7 @@
SYMBOL_NAME(name): \
PPC64_OPD2 \
AARCH64_BTI
+#endif
#if defined(__arm__)
#if !defined(__ARM_ARCH)
diff --git a/contrib/libs/libunwind/src/cet_unwind.h b/contrib/libs/libunwind/src/cet_unwind.h
index e371be20c4..c364ed3e12 100644
--- a/contrib/libs/libunwind/src/cet_unwind.h
+++ b/contrib/libs/libunwind/src/cet_unwind.h
@@ -36,6 +36,6 @@
#endif
extern void *__libunwind_cet_get_registers(unw_cursor_t *);
-extern void *__libunwind_cet_get_jump_target();
+extern void *__libunwind_cet_get_jump_target(void);
#endif
diff --git a/contrib/libs/libunwind/src/config.h b/contrib/libs/libunwind/src/config.h
index 5ae1604f65..deb5a4d4d7 100644
--- a/contrib/libs/libunwind/src/config.h
+++ b/contrib/libs/libunwind/src/config.h
@@ -43,6 +43,15 @@
// For ARM EHABI, Bionic didn't implement dl_iterate_phdr until API 21. After
// API 21, dl_iterate_phdr exists, but dl_unwind_find_exidx is much faster.
#define _LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX 1
+#elif defined(_AIX)
+// The traceback table at the end of each function is used for unwinding.
+#define _LIBUNWIND_SUPPORT_TBTAB_UNWIND 1
+#elif defined(__HAIKU__)
+ #if defined(_LIBUNWIND_USE_HAIKU_BSD_LIB)
+ #define _LIBUNWIND_USE_DL_ITERATE_PHDR 1
+ #endif
+ #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
+ #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1
#else
// Assume an ELF system with a dl_iterate_phdr function.
#define _LIBUNWIND_USE_DL_ITERATE_PHDR 1
@@ -57,7 +66,7 @@
#define _LIBUNWIND_EXPORT
#define _LIBUNWIND_HIDDEN
#else
- #if !defined(__ELF__) && !defined(__MACH__)
+ #if !defined(__ELF__) && !defined(__MACH__) && !defined(_AIX)
#define _LIBUNWIND_EXPORT __declspec(dllexport)
#define _LIBUNWIND_HIDDEN
#else
@@ -80,7 +89,7 @@
__asm__(".globl " SYMBOL_NAME(aliasname)); \
__asm__(SYMBOL_NAME(aliasname) " = " SYMBOL_NAME(name)); \
_LIBUNWIND_ALIAS_VISIBILITY(SYMBOL_NAME(aliasname))
-#elif defined(__ELF__)
+#elif defined(__ELF__) || defined(_AIX) || defined(__wasm__)
#define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \
extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \
__attribute__((weak, alias(#name)));
@@ -105,14 +114,10 @@
#define _LIBUNWIND_BUILD_SJLJ_APIS
#endif
-#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__)
-#define _LIBUNWIND_SUPPORT_FRAME_APIS
-#endif
-
#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || \
(!defined(__APPLE__) && defined(__arm__)) || defined(__aarch64__) || \
defined(__mips__) || defined(__riscv) || defined(__hexagon__) || \
- defined(__sparc__)
+ defined(__sparc__) || defined(__s390x__) || defined(__loongarch__)
#if !defined(_LIBUNWIND_BUILD_SJLJ_APIS)
#define _LIBUNWIND_BUILD_ZERO_COST_APIS
#endif
@@ -122,7 +127,7 @@
#if defined(_LIBUNWIND_REMEMBER_STACK_ALLOC) || defined(__APPLE__) || \
defined(__linux__) || defined(__ANDROID__) || defined(__MINGW32__) || \
defined(_LIBUNWIND_IS_BAREMETAL)
-#define _LIBUNWIND_REMEMBER_ALLOC(_size) alloca(_size)
+#define _LIBUNWIND_REMEMBER_ALLOC(_size) __builtin_alloca(_size)
#define _LIBUNWIND_REMEMBER_FREE(_ptr) \
do { \
} while (0)
@@ -159,10 +164,14 @@
#define _LIBUNWIND_LOG0(msg)
#define _LIBUNWIND_LOG(msg, ...)
#else
-#define _LIBUNWIND_LOG0(msg) \
- fprintf(stderr, "libunwind: " msg "\n")
-#define _LIBUNWIND_LOG(msg, ...) \
- fprintf(stderr, "libunwind: " msg "\n", __VA_ARGS__)
+#define _LIBUNWIND_LOG0(msg) do { \
+ fprintf(stderr, "libunwind: " msg "\n"); \
+ fflush(stderr); \
+ } while (0)
+#define _LIBUNWIND_LOG(msg, ...) do { \
+ fprintf(stderr, "libunwind: " msg "\n", __VA_ARGS__); \
+ fflush(stderr); \
+ } while (0)
#endif
#if defined(NDEBUG)
@@ -188,9 +197,9 @@
#ifdef __cplusplus
extern "C" {
#endif
- extern bool logAPIs();
- extern bool logUnwinding();
- extern bool logDWARF();
+ extern bool logAPIs(void);
+ extern bool logUnwinding(void);
+ extern bool logDWARF(void);
#ifdef __cplusplus
}
#endif
diff --git a/contrib/libs/libunwind/src/libunwind.cpp b/contrib/libs/libunwind/src/libunwind.cpp
index 03f8b75b5b..217dde9098 100644
--- a/contrib/libs/libunwind/src/libunwind.cpp
+++ b/contrib/libs/libunwind/src/libunwind.cpp
@@ -26,7 +26,7 @@
#include <sanitizer/asan_interface.h>
#endif
-#if !defined(__USING_SJLJ_EXCEPTIONS__)
+#if !defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__USING_WASM_EXCEPTIONS__)
#include "AddressSpace.hpp"
#include "UnwindCursor.hpp"
@@ -75,6 +75,10 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor,
# define REGISTER_KIND Registers_riscv
#elif defined(__ve__)
# define REGISTER_KIND Registers_ve
+#elif defined(__s390x__)
+# define REGISTER_KIND Registers_s390x
+#elif defined(__loongarch__) && __loongarch_grlen == 64
+#define REGISTER_KIND Registers_loongarch
#else
# error Architecture not supported
#endif
@@ -115,7 +119,7 @@ _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
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
+ // special case altering IP to re-find info (being called by personality
// function)
if (regNum == UNW_REG_IP) {
unw_proc_info_t info;
@@ -179,6 +183,15 @@ _LIBUNWIND_HIDDEN int __unw_step(unw_cursor_t *cursor) {
}
_LIBUNWIND_WEAK_ALIAS(__unw_step, unw_step)
+// Move cursor to next frame and for stage2 of unwinding.
+// This resets MTE tags of tagged frames to zero.
+extern "C" _LIBUNWIND_HIDDEN int __unw_step_stage2(unw_cursor_t *cursor) {
+ _LIBUNWIND_TRACE_API("__unw_step_stage2(cursor=%p)",
+ static_cast<void *>(cursor));
+ AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
+ return co->step(true);
+}
+
/// Get unwind info at cursor position in stack frame.
_LIBUNWIND_HIDDEN int __unw_get_proc_info(unw_cursor_t *cursor,
unw_proc_info_t *info) {
@@ -247,6 +260,16 @@ _LIBUNWIND_HIDDEN int __unw_is_signal_frame(unw_cursor_t *cursor) {
}
_LIBUNWIND_WEAK_ALIAS(__unw_is_signal_frame, unw_is_signal_frame)
+#ifdef _AIX
+_LIBUNWIND_EXPORT uintptr_t __unw_get_data_rel_base(unw_cursor_t *cursor) {
+ _LIBUNWIND_TRACE_API("unw_get_data_rel_base(cursor=%p)",
+ static_cast<void *>(cursor));
+ AbstractUnwindCursor *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
+ return co->getDataRelBase();
+}
+_LIBUNWIND_WEAK_ALIAS(__unw_get_data_rel_base, unw_get_data_rel_base)
+#endif
+
#ifdef __arm__
// Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD
_LIBUNWIND_HIDDEN void __unw_save_vfp_as_X(unw_cursor_t *cursor) {
@@ -301,7 +324,7 @@ void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
auto p = (LocalAddressSpace::pint_t)eh_frame_start;
- while (true) {
+ while (LocalAddressSpace::sThisAddressSpace.get32(p)) {
if (CFI_Parser<LocalAddressSpace>::decodeFDE(
LocalAddressSpace::sThisAddressSpace, p, &fdeInfo, &cieInfo,
true) == NULL) {
@@ -324,9 +347,90 @@ void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start) {
}
#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
-#endif // !defined(__USING_SJLJ_EXCEPTIONS__)
+#endif // !defined(__USING_SJLJ_EXCEPTIONS__) &&
+ // !defined(__USING_WASM_EXCEPTIONS__)
+
+#ifdef __APPLE__
+
+namespace libunwind {
+
+static constexpr size_t MAX_DYNAMIC_UNWIND_SECTIONS_FINDERS = 8;
+
+static RWMutex findDynamicUnwindSectionsLock;
+static size_t numDynamicUnwindSectionsFinders = 0;
+static unw_find_dynamic_unwind_sections
+ dynamicUnwindSectionsFinders[MAX_DYNAMIC_UNWIND_SECTIONS_FINDERS] = {0};
+
+bool findDynamicUnwindSections(void *addr, unw_dynamic_unwind_sections *info) {
+ bool found = false;
+ findDynamicUnwindSectionsLock.lock_shared();
+ for (size_t i = 0; i != numDynamicUnwindSectionsFinders; ++i) {
+ if (dynamicUnwindSectionsFinders[i]((unw_word_t)addr, info)) {
+ found = true;
+ break;
+ }
+ }
+ findDynamicUnwindSectionsLock.unlock_shared();
+ return found;
+}
+
+} // namespace libunwind
+
+int __unw_add_find_dynamic_unwind_sections(
+ unw_find_dynamic_unwind_sections find_dynamic_unwind_sections) {
+ findDynamicUnwindSectionsLock.lock();
+ // Check that we have enough space...
+ if (numDynamicUnwindSectionsFinders == MAX_DYNAMIC_UNWIND_SECTIONS_FINDERS) {
+ findDynamicUnwindSectionsLock.unlock();
+ return UNW_ENOMEM;
+ }
+
+ // Check for value already present...
+ for (size_t i = 0; i != numDynamicUnwindSectionsFinders; ++i) {
+ if (dynamicUnwindSectionsFinders[i] == find_dynamic_unwind_sections) {
+ findDynamicUnwindSectionsLock.unlock();
+ return UNW_EINVAL;
+ }
+ }
+
+ // Success -- add callback entry.
+ dynamicUnwindSectionsFinders[numDynamicUnwindSectionsFinders++] =
+ find_dynamic_unwind_sections;
+ findDynamicUnwindSectionsLock.unlock();
+
+ return UNW_ESUCCESS;
+}
+
+int __unw_remove_find_dynamic_unwind_sections(
+ unw_find_dynamic_unwind_sections find_dynamic_unwind_sections) {
+ findDynamicUnwindSectionsLock.lock();
+
+ // Find index to remove.
+ size_t finderIdx = numDynamicUnwindSectionsFinders;
+ for (size_t i = 0; i != numDynamicUnwindSectionsFinders; ++i) {
+ if (dynamicUnwindSectionsFinders[i] == find_dynamic_unwind_sections) {
+ finderIdx = i;
+ break;
+ }
+ }
+
+ // If no such registration is present then error out.
+ if (finderIdx == numDynamicUnwindSectionsFinders) {
+ findDynamicUnwindSectionsLock.unlock();
+ return UNW_EINVAL;
+ }
+
+ // Remove entry.
+ for (size_t i = finderIdx; i != numDynamicUnwindSectionsFinders - 1; ++i)
+ dynamicUnwindSectionsFinders[i] = dynamicUnwindSectionsFinders[i + 1];
+ dynamicUnwindSectionsFinders[--numDynamicUnwindSectionsFinders] = nullptr;
+
+ findDynamicUnwindSectionsLock.unlock();
+ return UNW_ESUCCESS;
+}
+#endif // __APPLE__
// Add logging hooks in Debug builds only
#ifndef NDEBUG
diff --git a/contrib/libs/libunwind/src/libunwind_ext.h b/contrib/libs/libunwind/src/libunwind_ext.h
index 7065ffcdae..28db43a4f6 100644
--- a/contrib/libs/libunwind/src/libunwind_ext.h
+++ b/contrib/libs/libunwind/src/libunwind_ext.h
@@ -43,6 +43,10 @@ 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 *);
+#if defined(_AIX)
+extern uintptr_t __unw_get_data_rel_base(unw_cursor_t *);
+#endif
+
// SPI
extern void __unw_iterate_dwarf_unwind_cache(void (*func)(
unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh));
@@ -54,6 +58,71 @@ extern void __unw_remove_dynamic_fde(unw_word_t fde);
extern void __unw_add_dynamic_eh_frame_section(unw_word_t eh_frame_start);
extern void __unw_remove_dynamic_eh_frame_section(unw_word_t eh_frame_start);
+#ifdef __APPLE__
+
+// Holds a description of the object-format-header (if any) and unwind info
+// sections for a given address:
+//
+// * dso_base should point to a header for the JIT'd object containing the
+// given address. The header's type should match the format type that
+// libunwind was compiled for (so a mach_header or mach_header_64 on Darwin).
+// A value of zero indicates that no such header exists.
+//
+// * dwarf_section and dwarf_section_length hold the address range of a DWARF
+// eh-frame section associated with the given address, if any. If the
+// dwarf_section_length field is zero it indicates that no such section
+// exists (and in this case dwarf_section should also be set to zero).
+//
+// * compact_unwind_section and compact_unwind_section_length hold the address
+// range of a compact-unwind info section associated with the given address,
+// if any. If the compact_unwind_section_length field is zero it indicates
+// that no such section exists (and in this case compact_unwind_section
+// should also be set to zero).
+//
+// See the unw_find_dynamic_unwind_sections type below for more details.
+struct unw_dynamic_unwind_sections {
+ unw_word_t dso_base;
+ unw_word_t dwarf_section;
+ size_t dwarf_section_length;
+ unw_word_t compact_unwind_section;
+ size_t compact_unwind_section_length;
+};
+
+// Typedef for unwind-info lookup callbacks. Functions of this type can be
+// registered and deregistered using __unw_add_find_dynamic_unwind_sections
+// and __unw_remove_find_dynamic_unwind_sections respectively.
+//
+// An unwind-info lookup callback should return 1 to indicate that it found
+// unwind-info for the given address, or 0 to indicate that it did not find
+// unwind-info for the given address. If found, the callback should populate
+// some or all of the fields of the info argument (which is guaranteed to be
+// non-null with all fields zero-initialized):
+typedef int (*unw_find_dynamic_unwind_sections)(
+ unw_word_t addr, struct unw_dynamic_unwind_sections *info);
+
+// Register a dynamic unwind-info lookup callback. If libunwind does not find
+// unwind info for a given frame in the executable program or normal dynamic
+// shared objects then it will call all registered dynamic lookup functions
+// in registration order until either one of them returns true, or the end
+// of the list is reached. This lookup will happen before libunwind searches
+// any eh-frames registered via __register_frame or
+// __unw_add_dynamic_eh_frame_section.
+//
+// Returns UNW_ESUCCESS for successful registrations. If the given callback
+// has already been registered then UNW_EINVAL will be returned. If all
+// available callback entries are in use then UNW_ENOMEM will be returned.
+extern int __unw_add_find_dynamic_unwind_sections(
+ unw_find_dynamic_unwind_sections find_dynamic_unwind_sections);
+
+// Deregister a dynacim unwind-info lookup callback.
+//
+// Returns UNW_ESUCCESS for successful deregistrations. If the given callback
+// has already been registered then UNW_EINVAL will be returned.
+extern int __unw_remove_find_dynamic_unwind_sections(
+ unw_find_dynamic_unwind_sections find_dynamic_unwind_sections);
+
+#endif
+
#if defined(_LIBUNWIND_ARM_EHABI)
extern const uint32_t* decode_eht_entry(const uint32_t*, size_t*, size_t*);
extern _Unwind_Reason_Code _Unwind_VRS_Interpret(_Unwind_Context *context,
diff --git a/contrib/libs/libunwind/ya.make b/contrib/libs/libunwind/ya.make
index ff465ee5cb..f1d9bbe121 100644
--- a/contrib/libs/libunwind/ya.make
+++ b/contrib/libs/libunwind/ya.make
@@ -11,9 +11,9 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-VERSION(14.0.6)
+VERSION(18.1.0-rc1)
-ORIGINAL_SOURCE(https://github.com/llvm/llvm-project/archive/llvmorg-14.0.6.tar.gz)
+ORIGINAL_SOURCE(https://github.com/llvm/llvm-project/archive/llvmorg-18.1.0-rc1.tar.gz)
DISABLE(USE_LTO)
@@ -51,6 +51,7 @@ SRCS(
src/Unwind-EHABI.cpp
src/Unwind-seh.cpp
src/Unwind-sjlj.c
+ src/Unwind-wasm.c
src/UnwindLevel1-gcc-ext.c
src/UnwindLevel1.c
src/UnwindRegistersRestore.S
@@ -58,10 +59,4 @@ SRCS(
src/libunwind.cpp
)
-IF (OS_DARWIN OR OS_IOS)
- SRCS(
- src/Unwind_AppleExtras.cpp
- )
-ENDIF()
-
END()