authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-04 18:09:10-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-08-04 18:09:10-07:00
log2f635c3ce9be74f9e9ffb71324f7ba51bd2987f4
treef04b0f4fb7a0e5ce0e36829bfd9aaa032447ac2a
parentc0d9578a84c95f66f34729f6c8842a98a995f223

update libunwind to LLVM 15

release/15.x commit 134fd359a5d884f16662a9edd22ab24feeb1498c

21 files changed, 1515 insertions(+), 134 deletions(-)

lib/libunwind/include/__libunwind_config.h+10-1
...@@ -9,8 +9,10 @@...@@ -9,8 +9,10 @@
9#ifndef ____LIBUNWIND_CONFIG_H__9#ifndef ____LIBUNWIND_CONFIG_H__
10#define ____LIBUNWIND_CONFIG_H__10#define ____LIBUNWIND_CONFIG_H__
1111
12#define _LIBUNWIND_VERSION 15000
13
12#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \14#if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \
13 !defined(__ARM_DWARF_EH__)15 !defined(__ARM_DWARF_EH__) && !defined(__SEH__)
14#define _LIBUNWIND_ARM_EHABI16#define _LIBUNWIND_ARM_EHABI
15#endif17#endif
1618
...@@ -27,6 +29,7 @@...@@ -27,6 +29,7 @@
27#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON 3429#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON 34
28#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 6430#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 64
29#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE 14331#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE 143
32#define _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X 83
3033
31#if defined(_LIBUNWIND_IS_NATIVE_ONLY)34#if defined(_LIBUNWIND_IS_NATIVE_ONLY)
32# if defined(__linux__)35# if defined(__linux__)
...@@ -158,6 +161,11 @@...@@ -158,6 +161,11 @@
158# define _LIBUNWIND_CONTEXT_SIZE 67161# define _LIBUNWIND_CONTEXT_SIZE 67
159# define _LIBUNWIND_CURSOR_SIZE 79162# define _LIBUNWIND_CURSOR_SIZE 79
160# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE163# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE
164# elif defined(__s390x__)
165# define _LIBUNWIND_TARGET_S390X 1
166# define _LIBUNWIND_CONTEXT_SIZE 34
167# define _LIBUNWIND_CURSOR_SIZE 46
168# define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X
161# else169# else
162# error "Unsupported architecture."170# error "Unsupported architecture."
163# endif171# endif
...@@ -176,6 +184,7 @@...@@ -176,6 +184,7 @@
176# define _LIBUNWIND_TARGET_HEXAGON 1184# define _LIBUNWIND_TARGET_HEXAGON 1
177# define _LIBUNWIND_TARGET_RISCV 1185# define _LIBUNWIND_TARGET_RISCV 1
178# define _LIBUNWIND_TARGET_VE 1186# define _LIBUNWIND_TARGET_VE 1
187# define _LIBUNWIND_TARGET_S390X 1
179# define _LIBUNWIND_CONTEXT_SIZE 167188# define _LIBUNWIND_CONTEXT_SIZE 167
180# define _LIBUNWIND_CURSOR_SIZE 179189# define _LIBUNWIND_CURSOR_SIZE 179
181# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287190# define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287
lib/libunwind/include/libunwind.h+46-1
...@@ -81,7 +81,7 @@ typedef struct unw_addr_space *unw_addr_space_t;...@@ -81,7 +81,7 @@ typedef struct unw_addr_space *unw_addr_space_t;
8181
82typedef int unw_regnum_t;82typedef int unw_regnum_t;
83typedef uintptr_t unw_word_t;83typedef uintptr_t unw_word_t;
84#if defined(__arm__) && !defined(__ARM_DWARF_EH__)84#if defined(__arm__) && !defined(__ARM_DWARF_EH__) && !defined(__SEH__)
85typedef uint64_t unw_fpreg_t;85typedef uint64_t unw_fpreg_t;
86#else86#else
87typedef double unw_fpreg_t;87typedef double unw_fpreg_t;
...@@ -120,6 +120,9 @@ extern int unw_resume(unw_cursor_t *) LIBUNWIND_AVAIL;...@@ -120,6 +120,9 @@ extern int unw_resume(unw_cursor_t *) LIBUNWIND_AVAIL;
120extern void unw_save_vfp_as_X(unw_cursor_t *) LIBUNWIND_AVAIL;120extern void unw_save_vfp_as_X(unw_cursor_t *) LIBUNWIND_AVAIL;
121#endif121#endif
122122
123#ifdef _AIX
124extern uintptr_t unw_get_data_rel_base(unw_cursor_t *) LIBUNWIND_AVAIL;
125#endif
123126
124extern const char *unw_regname(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL;127extern const char *unw_regname(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL;
125extern int unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *) LIBUNWIND_AVAIL;128extern int unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *) LIBUNWIND_AVAIL;
...@@ -1174,4 +1177,46 @@ enum {...@@ -1174,4 +1177,46 @@ enum {
1174 UNW_VE_VL = 145,1177 UNW_VE_VL = 145,
1175};1178};
11761179
1180// s390x register numbers
1181enum {
1182 UNW_S390X_R0 = 0,
1183 UNW_S390X_R1 = 1,
1184 UNW_S390X_R2 = 2,
1185 UNW_S390X_R3 = 3,
1186 UNW_S390X_R4 = 4,
1187 UNW_S390X_R5 = 5,
1188 UNW_S390X_R6 = 6,
1189 UNW_S390X_R7 = 7,
1190 UNW_S390X_R8 = 8,
1191 UNW_S390X_R9 = 9,
1192 UNW_S390X_R10 = 10,
1193 UNW_S390X_R11 = 11,
1194 UNW_S390X_R12 = 12,
1195 UNW_S390X_R13 = 13,
1196 UNW_S390X_R14 = 14,
1197 UNW_S390X_R15 = 15,
1198 UNW_S390X_F0 = 16,
1199 UNW_S390X_F2 = 17,
1200 UNW_S390X_F4 = 18,
1201 UNW_S390X_F6 = 19,
1202 UNW_S390X_F1 = 20,
1203 UNW_S390X_F3 = 21,
1204 UNW_S390X_F5 = 22,
1205 UNW_S390X_F7 = 23,
1206 UNW_S390X_F8 = 24,
1207 UNW_S390X_F10 = 25,
1208 UNW_S390X_F12 = 26,
1209 UNW_S390X_F14 = 27,
1210 UNW_S390X_F9 = 28,
1211 UNW_S390X_F11 = 29,
1212 UNW_S390X_F13 = 30,
1213 UNW_S390X_F15 = 31,
1214 // 32-47 Control Registers
1215 // 48-63 Access Registers
1216 UNW_S390X_PSWM = 64,
1217 UNW_S390X_PSWA = 65,
1218 // 66-67 Reserved
1219 // 68-83 Vector Registers %v16-%v31
1220};
1221
1177#endif1222#endif
lib/libunwind/include/unwind.h+1-1
...@@ -160,7 +160,7 @@ extern const void *_Unwind_Find_FDE(const void *pc, struct dwarf_eh_bases *);...@@ -160,7 +160,7 @@ extern const void *_Unwind_Find_FDE(const void *pc, struct dwarf_eh_bases *);
160extern void *_Unwind_FindEnclosingFunction(void *pc);160extern void *_Unwind_FindEnclosingFunction(void *pc);
161161
162// Mac OS X does not support text-rel and data-rel addressing so these functions162// Mac OS X does not support text-rel and data-rel addressing so these functions
163// are unimplemented163// are unimplemented.
164extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context)164extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context)
165 LIBUNWIND_UNAVAIL;165 LIBUNWIND_UNAVAIL;
166extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context)166extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context)
lib/libunwind/src/AddressSpace.hpp+21-2
...@@ -24,7 +24,7 @@...@@ -24,7 +24,7 @@
24#include "Registers.hpp"24#include "Registers.hpp"
2525
26#ifndef _LIBUNWIND_USE_DLADDR26#ifndef _LIBUNWIND_USE_DLADDR
27 #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32)27 #if !(defined(_LIBUNWIND_IS_BAREMETAL) || defined(_WIN32) || defined(_AIX))
28 #define _LIBUNWIND_USE_DLADDR 128 #define _LIBUNWIND_USE_DLADDR 1
29 #else29 #else
30 #define _LIBUNWIND_USE_DLADDR 030 #define _LIBUNWIND_USE_DLADDR 0
...@@ -45,6 +45,13 @@ struct EHABIIndexEntry {...@@ -45,6 +45,13 @@ struct EHABIIndexEntry {
45};45};
46#endif46#endif
4747
48#if defined(_AIX)
49namespace libunwind {
50char *getFuncNameFromTBTable(uintptr_t pc, uint16_t &NameLen,
51 unw_word_t *offset);
52}
53#endif
54
48#ifdef __APPLE__55#ifdef __APPLE__
4956
50 struct dyld_unwind_sections57 struct dyld_unwind_sections
...@@ -544,6 +551,7 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,...@@ -544,6 +551,7 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
544 DWORD err = GetLastError();551 DWORD err = GetLastError();
545 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: EnumProcessModules failed, "552 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: EnumProcessModules failed, "
546 "returned error %d", (int)err);553 "returned error %d", (int)err);
554 (void)err;
547 return false;555 return false;
548 }556 }
549557
...@@ -580,6 +588,11 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,...@@ -580,6 +588,11 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
580 (void)targetAddr;588 (void)targetAddr;
581 (void)info;589 (void)info;
582 return true;590 return true;
591#elif defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
592 // The traceback table is used for unwinding.
593 (void)targetAddr;
594 (void)info;
595 return true;
583#elif defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX)596#elif defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX)
584 int length = 0;597 int length = 0;
585 info.arm_section =598 info.arm_section =
...@@ -596,7 +609,6 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,...@@ -596,7 +609,6 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr,
596 return false;609 return false;
597}610}
598611
599
600inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {612inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) {
601 // TO DO: if OS has way to dynamically register FDEs, check that.613 // TO DO: if OS has way to dynamically register FDEs, check that.
602 (void)targetAddr;614 (void)targetAddr;
...@@ -616,6 +628,13 @@ inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,...@@ -616,6 +628,13 @@ inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf,
616 return true;628 return true;
617 }629 }
618 }630 }
631#elif defined(_AIX)
632 uint16_t nameLen;
633 char *funcName = getFuncNameFromTBTable(addr, nameLen, offset);
634 if (funcName != NULL) {
635 snprintf(buf, bufLen, "%.*s", nameLen, funcName);
636 return true;
637 }
619#else638#else
620 (void)addr;639 (void)addr;
621 (void)buf;640 (void)buf;
lib/libunwind/src/DwarfInstructions.hpp+24-4
...@@ -72,6 +72,10 @@ private:...@@ -72,6 +72,10 @@ private:
72 assert(0 && "getCFA(): unknown location");72 assert(0 && "getCFA(): unknown location");
73 __builtin_unreachable();73 __builtin_unreachable();
74 }74 }
75#if defined(_LIBUNWIND_TARGET_AARCH64)
76 static bool getRA_SIGN_STATE(A &addressSpace, R registers, pint_t cfa,
77 PrologInfo &prolog);
78#endif
75};79};
7680
77template <typename R>81template <typename R>
...@@ -166,6 +170,21 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister(...@@ -166,6 +170,21 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister(
166 }170 }
167 _LIBUNWIND_ABORT("unsupported restore location for vector register");171 _LIBUNWIND_ABORT("unsupported restore location for vector register");
168}172}
173#if defined(_LIBUNWIND_TARGET_AARCH64)
174template <typename A, typename R>
175bool DwarfInstructions<A, R>::getRA_SIGN_STATE(A &addressSpace, R registers,
176 pint_t cfa, PrologInfo &prolog) {
177 pint_t raSignState;
178 auto regloc = prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE];
179 if (regloc.location == CFI_Parser<A>::kRegisterUnused)
180 raSignState = static_cast<pint_t>(regloc.value);
181 else
182 raSignState = getSavedRegister(addressSpace, registers, cfa, regloc);
183
184 // Only bit[0] is meaningful.
185 return raSignState & 0x01;
186}
187#endif
169188
170template <typename A, typename R>189template <typename A, typename R>
171int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,190int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
...@@ -194,9 +213,10 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,...@@ -194,9 +213,10 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
194 newRegisters.setSP(cfa);213 newRegisters.setSP(cfa);
195214
196 pint_t returnAddress = 0;215 pint_t returnAddress = 0;
197 const int lastReg = R::lastDwarfRegNum();216 constexpr int lastReg = R::lastDwarfRegNum();
198 assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >= lastReg &&217 static_assert(static_cast<int>(CFI_Parser<A>::kMaxRegisterNumber) >=
199 "register range too large");218 lastReg,
219 "register range too large");
200 assert(lastReg >= (int)cieInfo.returnAddressRegister &&220 assert(lastReg >= (int)cieInfo.returnAddressRegister &&
201 "register range does not contain return address register");221 "register range does not contain return address register");
202 for (int i = 0; i <= lastReg; ++i) {222 for (int i = 0; i <= lastReg; ++i) {
...@@ -235,7 +255,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,...@@ -235,7 +255,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
235 // restored. autia1716 is used instead of autia as autia1716 assembles255 // restored. autia1716 is used instead of autia as autia1716 assembles
236 // to a NOP on pre-v8.3a architectures.256 // to a NOP on pre-v8.3a architectures.
237 if ((R::getArch() == REGISTERS_ARM64) &&257 if ((R::getArch() == REGISTERS_ARM64) &&
238 prolog.savedRegisters[UNW_AARCH64_RA_SIGN_STATE].value &&258 getRA_SIGN_STATE(addressSpace, registers, cfa, prolog) &&
239 returnAddress != 0) {259 returnAddress != 0) {
240#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)260#if !defined(_LIBUNWIND_IS_NATIVE_ONLY)
241 return UNW_ECROSSRASIGNING;261 return UNW_ECROSSRASIGNING;
lib/libunwind/src/EHHeaderParser.hpp+2-1
...@@ -57,7 +57,8 @@ bool EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,...@@ -57,7 +57,8 @@ bool EHHeaderParser<A>::decodeEHHdr(A &addressSpace, pint_t ehHdrStart,
57 pint_t p = ehHdrStart;57 pint_t p = ehHdrStart;
58 uint8_t version = addressSpace.get8(p++);58 uint8_t version = addressSpace.get8(p++);
59 if (version != 1) {59 if (version != 1) {
60 _LIBUNWIND_LOG0("Unsupported .eh_frame_hdr version");60 _LIBUNWIND_LOG("unsupported .eh_frame_hdr version: %" PRIu8 " at %" PRIx64,
61 version, static_cast<uint64_t>(ehHdrStart));
61 return false;62 return false;
62 }63 }
6364
lib/libunwind/src/Registers.hpp+334-14
...@@ -39,6 +39,7 @@ enum {...@@ -39,6 +39,7 @@ enum {
39 REGISTERS_HEXAGON,39 REGISTERS_HEXAGON,
40 REGISTERS_RISCV,40 REGISTERS_RISCV,
41 REGISTERS_VE,41 REGISTERS_VE,
42 REGISTERS_S390X,
42};43};
4344
44#if defined(_LIBUNWIND_TARGET_I386)45#if defined(_LIBUNWIND_TARGET_I386)
...@@ -69,7 +70,9 @@ public:...@@ -69,7 +70,9 @@ public:
69 void setVectorRegister(int num, v128 value);70 void setVectorRegister(int num, v128 value);
70 static const char *getRegisterName(int num);71 static const char *getRegisterName(int num);
71 void jumpto() { __libunwind_Registers_x86_jumpto(this); }72 void jumpto() { __libunwind_Registers_x86_jumpto(this); }
72 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; }73 static constexpr int lastDwarfRegNum() {
74 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86;
75 }
73 static int getArch() { return REGISTERS_X86; }76 static int getArch() { return REGISTERS_X86; }
7477
75 uint32_t getSP() const { return _registers.__esp; }78 uint32_t getSP() const { return _registers.__esp; }
...@@ -285,7 +288,9 @@ public:...@@ -285,7 +288,9 @@ public:
285 void setVectorRegister(int num, v128 value);288 void setVectorRegister(int num, v128 value);
286 static const char *getRegisterName(int num);289 static const char *getRegisterName(int num);
287 void jumpto() { __libunwind_Registers_x86_64_jumpto(this); }290 void jumpto() { __libunwind_Registers_x86_64_jumpto(this); }
288 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; }291 static constexpr int lastDwarfRegNum() {
292 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64;
293 }
289 static int getArch() { return REGISTERS_X86_64; }294 static int getArch() { return REGISTERS_X86_64; }
290295
291 uint64_t getSP() const { return _registers.__rsp; }296 uint64_t getSP() const { return _registers.__rsp; }
...@@ -602,13 +607,17 @@ public:...@@ -602,13 +607,17 @@ public:
602 void setVectorRegister(int num, v128 value);607 void setVectorRegister(int num, v128 value);
603 static const char *getRegisterName(int num);608 static const char *getRegisterName(int num);
604 void jumpto();609 void jumpto();
605 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC; }610 static constexpr int lastDwarfRegNum() {
611 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC;
612 }
606 static int getArch() { return REGISTERS_PPC; }613 static int getArch() { return REGISTERS_PPC; }
607614
608 uint64_t getSP() const { return _registers.__r1; }615 uint64_t getSP() const { return _registers.__r1; }
609 void setSP(uint32_t value) { _registers.__r1 = value; }616 void setSP(uint32_t value) { _registers.__r1 = value; }
610 uint64_t getIP() const { return _registers.__srr0; }617 uint64_t getIP() const { return _registers.__srr0; }
611 void setIP(uint32_t value) { _registers.__srr0 = value; }618 void setIP(uint32_t value) { _registers.__srr0 = value; }
619 uint64_t getCR() const { return _registers.__cr; }
620 void setCR(uint32_t value) { _registers.__cr = value; }
612621
613private:622private:
614 struct ppc_thread_state_t {623 struct ppc_thread_state_t {
...@@ -1168,13 +1177,17 @@ public:...@@ -1168,13 +1177,17 @@ public:
1168 void setVectorRegister(int num, v128 value);1177 void setVectorRegister(int num, v128 value);
1169 static const char *getRegisterName(int num);1178 static const char *getRegisterName(int num);
1170 void jumpto();1179 void jumpto();
1171 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64; }1180 static constexpr int lastDwarfRegNum() {
1181 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_PPC64;
1182 }
1172 static int getArch() { return REGISTERS_PPC64; }1183 static int getArch() { return REGISTERS_PPC64; }
11731184
1174 uint64_t getSP() const { return _registers.__r1; }1185 uint64_t getSP() const { return _registers.__r1; }
1175 void setSP(uint64_t value) { _registers.__r1 = value; }1186 void setSP(uint64_t value) { _registers.__r1 = value; }
1176 uint64_t getIP() const { return _registers.__srr0; }1187 uint64_t getIP() const { return _registers.__srr0; }
1177 void setIP(uint64_t value) { _registers.__srr0 = value; }1188 void setIP(uint64_t value) { _registers.__srr0 = value; }
1189 uint64_t getCR() const { return _registers.__cr; }
1190 void setCR(uint64_t value) { _registers.__cr = value; }
11781191
1179private:1192private:
1180 struct ppc64_thread_state_t {1193 struct ppc64_thread_state_t {
...@@ -1813,7 +1826,9 @@ public:...@@ -1813,7 +1826,9 @@ public:
1813 void setVectorRegister(int num, v128 value);1826 void setVectorRegister(int num, v128 value);
1814 static const char *getRegisterName(int num);1827 static const char *getRegisterName(int num);
1815 void jumpto() { __libunwind_Registers_arm64_jumpto(this); }1828 void jumpto() { __libunwind_Registers_arm64_jumpto(this); }
1816 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; }1829 static constexpr int lastDwarfRegNum() {
1830 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64;
1831 }
1817 static int getArch() { return REGISTERS_ARM64; }1832 static int getArch() { return REGISTERS_ARM64; }
18181833
1819 uint64_t getSP() const { return _registers.__sp; }1834 uint64_t getSP() const { return _registers.__sp; }
...@@ -2103,7 +2118,9 @@ public:...@@ -2103,7 +2118,9 @@ public:
2103 restoreSavedFloatRegisters();2118 restoreSavedFloatRegisters();
2104 restoreCoreAndJumpTo();2119 restoreCoreAndJumpTo();
2105 }2120 }
2106 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM; }2121 static constexpr int lastDwarfRegNum() {
2122 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM;
2123 }
2107 static int getArch() { return REGISTERS_ARM; }2124 static int getArch() { return REGISTERS_ARM; }
21082125
2109 uint32_t getSP() const { return _registers.__sp; }2126 uint32_t getSP() const { return _registers.__sp; }
...@@ -2603,7 +2620,9 @@ public:...@@ -2603,7 +2620,9 @@ public:
2603 void setVectorRegister(int num, v128 value);2620 void setVectorRegister(int num, v128 value);
2604 static const char *getRegisterName(int num);2621 static const char *getRegisterName(int num);
2605 void jumpto();2622 void jumpto();
2606 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K; }2623 static constexpr int lastDwarfRegNum() {
2624 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K;
2625 }
2607 static int getArch() { return REGISTERS_OR1K; }2626 static int getArch() { return REGISTERS_OR1K; }
26082627
2609 uint64_t getSP() const { return _registers.__r[1]; }2628 uint64_t getSP() const { return _registers.__r[1]; }
...@@ -2800,7 +2819,9 @@ public:...@@ -2800,7 +2819,9 @@ public:
2800 void setVectorRegister(int num, v128 value);2819 void setVectorRegister(int num, v128 value);
2801 static const char *getRegisterName(int num);2820 static const char *getRegisterName(int num);
2802 void jumpto();2821 void jumpto();
2803 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }2822 static constexpr int lastDwarfRegNum() {
2823 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS;
2824 }
2804 static int getArch() { return REGISTERS_MIPS_O32; }2825 static int getArch() { return REGISTERS_MIPS_O32; }
28052826
2806 uint32_t getSP() const { return _registers.__r[29]; }2827 uint32_t getSP() const { return _registers.__r[29]; }
...@@ -3127,7 +3148,9 @@ public:...@@ -3127,7 +3148,9 @@ public:
3127 void setVectorRegister(int num, v128 value);3148 void setVectorRegister(int num, v128 value);
3128 static const char *getRegisterName(int num);3149 static const char *getRegisterName(int num);
3129 void jumpto();3150 void jumpto();
3130 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS; }3151 static constexpr int lastDwarfRegNum() {
3152 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS;
3153 }
3131 static int getArch() { return REGISTERS_MIPS_NEWABI; }3154 static int getArch() { return REGISTERS_MIPS_NEWABI; }
31323155
3133 uint64_t getSP() const { return _registers.__r[29]; }3156 uint64_t getSP() const { return _registers.__r[29]; }
...@@ -3422,7 +3445,9 @@ public:...@@ -3422,7 +3445,9 @@ public:
3422 void setVectorRegister(int num, v128 value);3445 void setVectorRegister(int num, v128 value);
3423 static const char *getRegisterName(int num);3446 static const char *getRegisterName(int num);
3424 void jumpto();3447 void jumpto();
3425 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC; }3448 static constexpr int lastDwarfRegNum() {
3449 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC;
3450 }
3426 static int getArch() { return REGISTERS_SPARC; }3451 static int getArch() { return REGISTERS_SPARC; }
34273452
3428 uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6]; }3453 uint64_t getSP() const { return _registers.__regs[UNW_SPARC_O6]; }
...@@ -3606,7 +3631,7 @@ public:...@@ -3606,7 +3631,7 @@ public:
3606 void setVectorRegister(int num, v128 value);3631 void setVectorRegister(int num, v128 value);
3607 const char *getRegisterName(int num);3632 const char *getRegisterName(int num);
3608 void jumpto();3633 void jumpto();
3609 static int lastDwarfRegNum() {3634 static constexpr int lastDwarfRegNum() {
3610 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64;3635 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC64;
3611 }3636 }
3612 static int getArch() { return REGISTERS_SPARC64; }3637 static int getArch() { return REGISTERS_SPARC64; }
...@@ -3791,7 +3816,9 @@ public:...@@ -3791,7 +3816,9 @@ public:
3791 void setVectorRegister(int num, v128 value);3816 void setVectorRegister(int num, v128 value);
3792 const char *getRegisterName(int num);3817 const char *getRegisterName(int num);
3793 void jumpto();3818 void jumpto();
3794 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON; }3819 static constexpr int lastDwarfRegNum() {
3820 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON;
3821 }
3795 static int getArch() { return REGISTERS_HEXAGON; }3822 static int getArch() { return REGISTERS_HEXAGON; }
37963823
3797 uint32_t getSP() const { return _registers.__r[UNW_HEXAGON_R29]; }3824 uint32_t getSP() const { return _registers.__r[UNW_HEXAGON_R29]; }
...@@ -4004,7 +4031,9 @@ public:...@@ -4004,7 +4031,9 @@ public:
4004 void setVectorRegister(int num, v128 value);4031 void setVectorRegister(int num, v128 value);
4005 static const char *getRegisterName(int num);4032 static const char *getRegisterName(int num);
4006 void jumpto();4033 void jumpto();
4007 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV; }4034 static constexpr int lastDwarfRegNum() {
4035 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV;
4036 }
4008 static int getArch() { return REGISTERS_RISCV; }4037 static int getArch() { return REGISTERS_RISCV; }
40094038
4010 reg_t getSP() const { return _registers[2]; }4039 reg_t getSP() const { return _registers[2]; }
...@@ -4290,7 +4319,9 @@ public:...@@ -4290,7 +4319,9 @@ public:
4290 void setVectorRegister(int num, v128 value);4319 void setVectorRegister(int num, v128 value);
4291 static const char *getRegisterName(int num);4320 static const char *getRegisterName(int num);
4292 void jumpto();4321 void jumpto();
4293 static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE; }4322 static constexpr int lastDwarfRegNum() {
4323 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE;
4324 }
4294 static int getArch() { return REGISTERS_VE; }4325 static int getArch() { return REGISTERS_VE; }
42954326
4296 uint64_t getSP() const { return _registers.__s[11]; }4327 uint64_t getSP() const { return _registers.__s[11]; }
...@@ -4712,6 +4743,295 @@ inline const char *Registers_ve::getRegisterName(int regNum) {...@@ -4712,6 +4743,295 @@ inline const char *Registers_ve::getRegisterName(int regNum) {
4712}4743}
4713#endif // _LIBUNWIND_TARGET_VE4744#endif // _LIBUNWIND_TARGET_VE
47144745
4746#if defined(_LIBUNWIND_TARGET_S390X)
4747/// Registers_s390x holds the register state of a thread in a
4748/// 64-bit Linux on IBM zSystems process.
4749class _LIBUNWIND_HIDDEN Registers_s390x {
4750public:
4751 Registers_s390x();
4752 Registers_s390x(const void *registers);
4753
4754 bool validRegister(int num) const;
4755 uint64_t getRegister(int num) const;
4756 void setRegister(int num, uint64_t value);
4757 bool validFloatRegister(int num) const;
4758 double getFloatRegister(int num) const;
4759 void setFloatRegister(int num, double value);
4760 bool validVectorRegister(int num) const;
4761 v128 getVectorRegister(int num) const;
4762 void setVectorRegister(int num, v128 value);
4763 static const char *getRegisterName(int num);
4764 void jumpto();
4765 static constexpr int lastDwarfRegNum() {
4766 return _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X;
4767 }
4768 static int getArch() { return REGISTERS_S390X; }
4769
4770 uint64_t getSP() const { return _registers.__gpr[15]; }
4771 void setSP(uint64_t value) { _registers.__gpr[15] = value; }
4772 uint64_t getIP() const { return _registers.__pswa; }
4773 void setIP(uint64_t value) { _registers.__pswa = value; }
4774
4775private:
4776 struct s390x_thread_state_t {
4777 uint64_t __pswm; // Problem Status Word: Mask
4778 uint64_t __pswa; // Problem Status Word: Address (PC)
4779 uint64_t __gpr[16]; // General Purpose Registers
4780 double __fpr[16]; // Floating-Point Registers
4781 };
4782
4783 s390x_thread_state_t _registers;
4784};
4785
4786inline Registers_s390x::Registers_s390x(const void *registers) {
4787 static_assert((check_fit<Registers_s390x, unw_context_t>::does_fit),
4788 "s390x registers do not fit into unw_context_t");
4789 memcpy(&_registers, static_cast<const uint8_t *>(registers),
4790 sizeof(_registers));
4791}
4792
4793inline Registers_s390x::Registers_s390x() {
4794 memset(&_registers, 0, sizeof(_registers));
4795}
4796
4797inline bool Registers_s390x::validRegister(int regNum) const {
4798 switch (regNum) {
4799 case UNW_S390X_PSWM:
4800 case UNW_S390X_PSWA:
4801 case UNW_REG_IP:
4802 case UNW_REG_SP:
4803 return true;
4804 }
4805
4806 if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15)
4807 return true;
4808
4809 return false;
4810}
4811
4812inline uint64_t Registers_s390x::getRegister(int regNum) const {
4813 if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15)
4814 return _registers.__gpr[regNum - UNW_S390X_R0];
4815
4816 switch (regNum) {
4817 case UNW_S390X_PSWM:
4818 return _registers.__pswm;
4819 case UNW_S390X_PSWA:
4820 case UNW_REG_IP:
4821 return _registers.__pswa;
4822 case UNW_REG_SP:
4823 return _registers.__gpr[15];
4824 }
4825 _LIBUNWIND_ABORT("unsupported s390x register");
4826}
4827
4828inline void Registers_s390x::setRegister(int regNum, uint64_t value) {
4829 if (regNum >= UNW_S390X_R0 && regNum <= UNW_S390X_R15) {
4830 _registers.__gpr[regNum - UNW_S390X_R0] = value;
4831 return;
4832 }
4833
4834 switch (regNum) {
4835 case UNW_S390X_PSWM:
4836 _registers.__pswm = value;
4837 return;
4838 case UNW_S390X_PSWA:
4839 case UNW_REG_IP:
4840 _registers.__pswa = value;
4841 return;
4842 case UNW_REG_SP:
4843 _registers.__gpr[15] = value;
4844 return;
4845 }
4846 _LIBUNWIND_ABORT("unsupported s390x register");
4847}
4848
4849inline bool Registers_s390x::validFloatRegister(int regNum) const {
4850 return regNum >= UNW_S390X_F0 && regNum <= UNW_S390X_F15;
4851}
4852
4853inline double Registers_s390x::getFloatRegister(int regNum) const {
4854 // NOTE: FPR DWARF register numbers are not consecutive.
4855 switch (regNum) {
4856 case UNW_S390X_F0:
4857 return _registers.__fpr[0];
4858 case UNW_S390X_F1:
4859 return _registers.__fpr[1];
4860 case UNW_S390X_F2:
4861 return _registers.__fpr[2];
4862 case UNW_S390X_F3:
4863 return _registers.__fpr[3];
4864 case UNW_S390X_F4:
4865 return _registers.__fpr[4];
4866 case UNW_S390X_F5:
4867 return _registers.__fpr[5];
4868 case UNW_S390X_F6:
4869 return _registers.__fpr[6];
4870 case UNW_S390X_F7:
4871 return _registers.__fpr[7];
4872 case UNW_S390X_F8:
4873 return _registers.__fpr[8];
4874 case UNW_S390X_F9:
4875 return _registers.__fpr[9];
4876 case UNW_S390X_F10:
4877 return _registers.__fpr[10];
4878 case UNW_S390X_F11:
4879 return _registers.__fpr[11];
4880 case UNW_S390X_F12:
4881 return _registers.__fpr[12];
4882 case UNW_S390X_F13:
4883 return _registers.__fpr[13];
4884 case UNW_S390X_F14:
4885 return _registers.__fpr[14];
4886 case UNW_S390X_F15:
4887 return _registers.__fpr[15];
4888 }
4889 _LIBUNWIND_ABORT("unsupported s390x register");
4890}
4891
4892inline void Registers_s390x::setFloatRegister(int regNum, double value) {
4893 // NOTE: FPR DWARF register numbers are not consecutive.
4894 switch (regNum) {
4895 case UNW_S390X_F0:
4896 _registers.__fpr[0] = value;
4897 return;
4898 case UNW_S390X_F1:
4899 _registers.__fpr[1] = value;
4900 return;
4901 case UNW_S390X_F2:
4902 _registers.__fpr[2] = value;
4903 return;
4904 case UNW_S390X_F3:
4905 _registers.__fpr[3] = value;
4906 return;
4907 case UNW_S390X_F4:
4908 _registers.__fpr[4] = value;
4909 return;
4910 case UNW_S390X_F5:
4911 _registers.__fpr[5] = value;
4912 return;
4913 case UNW_S390X_F6:
4914 _registers.__fpr[6] = value;
4915 return;
4916 case UNW_S390X_F7:
4917 _registers.__fpr[7] = value;
4918 return;
4919 case UNW_S390X_F8:
4920 _registers.__fpr[8] = value;
4921 return;
4922 case UNW_S390X_F9:
4923 _registers.__fpr[9] = value;
4924 return;
4925 case UNW_S390X_F10:
4926 _registers.__fpr[10] = value;
4927 return;
4928 case UNW_S390X_F11:
4929 _registers.__fpr[11] = value;
4930 return;
4931 case UNW_S390X_F12:
4932 _registers.__fpr[12] = value;
4933 return;
4934 case UNW_S390X_F13:
4935 _registers.__fpr[13] = value;
4936 return;
4937 case UNW_S390X_F14:
4938 _registers.__fpr[14] = value;
4939 return;
4940 case UNW_S390X_F15:
4941 _registers.__fpr[15] = value;
4942 return;
4943 }
4944 _LIBUNWIND_ABORT("unsupported s390x register");
4945}
4946
4947inline bool Registers_s390x::validVectorRegister(int /*regNum*/) const {
4948 return false;
4949}
4950
4951inline v128 Registers_s390x::getVectorRegister(int /*regNum*/) const {
4952 _LIBUNWIND_ABORT("s390x vector support not implemented");
4953}
4954
4955inline void Registers_s390x::setVectorRegister(int /*regNum*/, v128 /*value*/) {
4956 _LIBUNWIND_ABORT("s390x vector support not implemented");
4957}
4958
4959inline const char *Registers_s390x::getRegisterName(int regNum) {
4960 switch (regNum) {
4961 case UNW_REG_IP:
4962 return "ip";
4963 case UNW_REG_SP:
4964 return "sp";
4965 case UNW_S390X_R0:
4966 return "r0";
4967 case UNW_S390X_R1:
4968 return "r1";
4969 case UNW_S390X_R2:
4970 return "r2";
4971 case UNW_S390X_R3:
4972 return "r3";
4973 case UNW_S390X_R4:
4974 return "r4";
4975 case UNW_S390X_R5:
4976 return "r5";
4977 case UNW_S390X_R6:
4978 return "r6";
4979 case UNW_S390X_R7:
4980 return "r7";
4981 case UNW_S390X_R8:
4982 return "r8";
4983 case UNW_S390X_R9:
4984 return "r9";
4985 case UNW_S390X_R10:
4986 return "r10";
4987 case UNW_S390X_R11:
4988 return "r11";
4989 case UNW_S390X_R12:
4990 return "r12";
4991 case UNW_S390X_R13:
4992 return "r13";
4993 case UNW_S390X_R14:
4994 return "r14";
4995 case UNW_S390X_R15:
4996 return "r15";
4997 case UNW_S390X_F0:
4998 return "f0";
4999 case UNW_S390X_F1:
5000 return "f1";
5001 case UNW_S390X_F2:
5002 return "f2";
5003 case UNW_S390X_F3:
5004 return "f3";
5005 case UNW_S390X_F4:
5006 return "f4";
5007 case UNW_S390X_F5:
5008 return "f5";
5009 case UNW_S390X_F6:
5010 return "f6";
5011 case UNW_S390X_F7:
5012 return "f7";
5013 case UNW_S390X_F8:
5014 return "f8";
5015 case UNW_S390X_F9:
5016 return "f9";
5017 case UNW_S390X_F10:
5018 return "f10";
5019 case UNW_S390X_F11:
5020 return "f11";
5021 case UNW_S390X_F12:
5022 return "f12";
5023 case UNW_S390X_F13:
5024 return "f13";
5025 case UNW_S390X_F14:
5026 return "f14";
5027 case UNW_S390X_F15:
5028 return "f15";
5029 }
5030 return "unknown register";
5031}
5032#endif // _LIBUNWIND_TARGET_S390X
5033
5034
4715} // namespace libunwind5035} // namespace libunwind
47165036
4717#endif // __REGISTERS_HPP__5037#endif // __REGISTERS_HPP__
lib/libunwind/src/Unwind-EHABI.cpp+5-4
...@@ -432,10 +432,11 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data,...@@ -432,10 +432,11 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data,
432 uint32_t sp;432 uint32_t sp;
433 uint32_t pac;433 uint32_t pac;
434 _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);434 _Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);
435 _Unwind_VRS_Get(context, _UVRSC_PSEUDO, UNW_ARM_RA_AUTH_CODE,435 _Unwind_VRS_Get(context, _UVRSC_PSEUDO, 0, _UVRSD_UINT32, &pac);
436 _UVRSD_UINT32, &pac);
437 __asm__ __volatile__("autg %0, %1, %2" : : "r"(pac), "r"(lr), "r"(sp) :);436 __asm__ __volatile__("autg %0, %1, %2" : : "r"(pac), "r"(lr), "r"(sp) :);
438 }437 }
438#else
439 (void)hasReturnAddrAuthCode;
439#endif440#endif
440 _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr);441 _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr);
441 }442 }
...@@ -1136,8 +1137,7 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,...@@ -1136,8 +1137,7 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
1136 }1137 }
1137 uint32_t pac = *sp++;1138 uint32_t pac = *sp++;
1138 _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);1139 _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);
1139 return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_RA_AUTH_CODE,1140 return _Unwind_VRS_Set(context, _UVRSC_PSEUDO, 0, _UVRSD_UINT32, &pac);
1140 _UVRSD_UINT32, &pac);
1141 }1141 }
1142 }1142 }
1143 _LIBUNWIND_ABORT("unsupported register class");1143 _LIBUNWIND_ABORT("unsupported register class");
...@@ -1193,6 +1193,7 @@ _Unwind_DeleteException(_Unwind_Exception *exception_object) {...@@ -1193,6 +1193,7 @@ _Unwind_DeleteException(_Unwind_Exception *exception_object) {
1193extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code1193extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code
1194__gnu_unwind_frame(_Unwind_Exception *exception_object,1194__gnu_unwind_frame(_Unwind_Exception *exception_object,
1195 struct _Unwind_Context *context) {1195 struct _Unwind_Context *context) {
1196 (void)exception_object;
1196 unw_cursor_t *cursor = (unw_cursor_t *)context;1197 unw_cursor_t *cursor = (unw_cursor_t *)context;
1197 switch (__unw_step(cursor)) {1198 switch (__unw_step(cursor)) {
1198 case UNW_STEP_SUCCESS:1199 case UNW_STEP_SUCCESS:
lib/libunwind/src/Unwind-seh.cpp+3-3
...@@ -104,7 +104,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,...@@ -104,7 +104,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx,
104 if (!ctx) {104 if (!ctx) {
105 __unw_init_seh(&cursor, disp->ContextRecord);105 __unw_init_seh(&cursor, disp->ContextRecord);
106 __unw_seh_set_disp_ctx(&cursor, disp);106 __unw_seh_set_disp_ctx(&cursor, disp);
107 __unw_set_reg(&cursor, UNW_REG_IP, disp->ControlPc - 1);107 __unw_set_reg(&cursor, UNW_REG_IP, disp->ControlPc);
108 ctx = (struct _Unwind_Context *)&cursor;108 ctx = (struct _Unwind_Context *)&cursor;
109109
110 if (!IS_UNWINDING(ms_exc->ExceptionFlags)) {110 if (!IS_UNWINDING(ms_exc->ExceptionFlags)) {
...@@ -255,8 +255,8 @@ unwind_phase2_forced(unw_context_t *uc,...@@ -255,8 +255,8 @@ unwind_phase2_forced(unw_context_t *uc,
255 (frameInfo.start_ip + offset > frameInfo.end_ip))255 (frameInfo.start_ip + offset > frameInfo.end_ip))
256 functionName = ".anonymous.";256 functionName = ".anonymous.";
257 _LIBUNWIND_TRACE_UNWINDING(257 _LIBUNWIND_TRACE_UNWINDING(
258 "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIx64258 "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIxPTR
259 ", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64,259 ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,
260 (void *)exception_object, frameInfo.start_ip, functionName,260 (void *)exception_object, frameInfo.start_ip, functionName,
261 frameInfo.lsda, frameInfo.handler);261 frameInfo.lsda, frameInfo.handler);
262 }262 }
lib/libunwind/src/UnwindCursor.hpp+714-19
...@@ -24,6 +24,19 @@...@@ -24,6 +24,19 @@
24#ifdef __APPLE__24#ifdef __APPLE__
25 #include <mach-o/dyld.h>25 #include <mach-o/dyld.h>
26#endif26#endif
27#ifdef _AIX
28#include <dlfcn.h>
29#include <sys/debug.h>
30#include <sys/pseg.h>
31#endif
32
33#if defined(_LIBUNWIND_TARGET_LINUX) && \
34 (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_S390X))
35#include <sys/syscall.h>
36#include <sys/uio.h>
37#include <unistd.h>
38#define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1
39#endif
2740
28#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)41#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
29// Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and42// Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and
...@@ -451,6 +464,12 @@ public:...@@ -451,6 +464,12 @@ public:
451 virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); }464 virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); }
452#endif465#endif
453466
467#ifdef _AIX
468 virtual uintptr_t getDataRelBase() {
469 _LIBUNWIND_ABORT("getDataRelBase not implemented");
470 }
471#endif
472
454#if defined(_LIBUNWIND_USE_CET)473#if defined(_LIBUNWIND_USE_CET)
455 virtual void *get_registers() {474 virtual void *get_registers() {
456 _LIBUNWIND_ABORT("get_registers not implemented");475 _LIBUNWIND_ABORT("get_registers not implemented");
...@@ -499,6 +518,14 @@ private:...@@ -499,6 +518,14 @@ private:
499 pint_t getLastPC() const { return _dispContext.ControlPc; }518 pint_t getLastPC() const { return _dispContext.ControlPc; }
500 void setLastPC(pint_t pc) { _dispContext.ControlPc = pc; }519 void setLastPC(pint_t pc) { _dispContext.ControlPc = pc; }
501 RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {520 RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {
521#ifdef __arm__
522 // Remove the thumb bit; FunctionEntry ranges don't include the thumb bit.
523 pc &= ~1U;
524#endif
525 // If pc points exactly at the end of the range, we might resolve the
526 // next function instead. Decrement pc by 1 to fit inside the current
527 // function.
528 pc -= 1;
502 _dispContext.FunctionEntry = RtlLookupFunctionEntry(pc,529 _dispContext.FunctionEntry = RtlLookupFunctionEntry(pc,
503 &_dispContext.ImageBase,530 &_dispContext.ImageBase,
504 _dispContext.HistoryTable);531 _dispContext.HistoryTable);
...@@ -844,7 +871,7 @@ void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {...@@ -844,7 +871,7 @@ void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
844 uint32_t w;871 uint32_t w;
845 float f;872 float f;
846 } d;873 } d;
847 d.f = value;874 d.f = (float)value;
848 _msContext.S[regNum - UNW_ARM_S0] = d.w;875 _msContext.S[regNum - UNW_ARM_S0] = d.w;
849 }876 }
850 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {877 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {
...@@ -910,9 +937,14 @@ public:...@@ -910,9 +937,14 @@ public:
910 virtual void saveVFPAsX();937 virtual void saveVFPAsX();
911#endif938#endif
912939
940#ifdef _AIX
941 virtual uintptr_t getDataRelBase();
942#endif
943
913#if defined(_LIBUNWIND_USE_CET)944#if defined(_LIBUNWIND_USE_CET)
914 virtual void *get_registers() { return &_registers; }945 virtual void *get_registers() { return &_registers; }
915#endif946#endif
947
916 // libunwind does not and should not depend on C++ library which means that we948 // libunwind does not and should not depend on C++ library which means that we
917 // need our own defition of inline placement new.949 // need our own defition of inline placement new.
918 static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }950 static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }
...@@ -937,7 +969,7 @@ private:...@@ -937,7 +969,7 @@ private:
937 }969 }
938#endif970#endif
939971
940#if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64)972#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
941 bool setInfoForSigReturn() {973 bool setInfoForSigReturn() {
942 R dummy;974 R dummy;
943 return setInfoForSigReturn(dummy);975 return setInfoForSigReturn(dummy);
...@@ -946,8 +978,14 @@ private:...@@ -946,8 +978,14 @@ private:
946 R dummy;978 R dummy;
947 return stepThroughSigReturn(dummy);979 return stepThroughSigReturn(dummy);
948 }980 }
981#if defined(_LIBUNWIND_TARGET_AARCH64)
949 bool setInfoForSigReturn(Registers_arm64 &);982 bool setInfoForSigReturn(Registers_arm64 &);
950 int stepThroughSigReturn(Registers_arm64 &);983 int stepThroughSigReturn(Registers_arm64 &);
984#endif
985#if defined(_LIBUNWIND_TARGET_S390X)
986 bool setInfoForSigReturn(Registers_s390x &);
987 int stepThroughSigReturn(Registers_s390x &);
988#endif
951 template <typename Registers> bool setInfoForSigReturn(Registers &) {989 template <typename Registers> bool setInfoForSigReturn(Registers &) {
952 return false;990 return false;
953 }991 }
...@@ -1204,6 +1242,12 @@ private:...@@ -1204,6 +1242,12 @@ private:
1204 }1242 }
1205#endif1243#endif
12061244
1245#if defined (_LIBUNWIND_TARGET_S390X)
1246 compact_unwind_encoding_t dwarfEncoding(Registers_s390x &) const {
1247 return 0;
1248 }
1249#endif
1250
1207#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)1251#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
12081252
1209#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)1253#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
...@@ -1220,13 +1264,23 @@ private:...@@ -1220,13 +1264,23 @@ private:
1220 int stepWithSEHData() { /* FIXME: Implement */ return 0; }1264 int stepWithSEHData() { /* FIXME: Implement */ return 0; }
1221#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)1265#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
12221266
1267#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
1268 bool getInfoFromTBTable(pint_t pc, R &registers);
1269 int stepWithTBTable(pint_t pc, tbtable *TBTable, R &registers,
1270 bool &isSignalFrame);
1271 int stepWithTBTableData() {
1272 return stepWithTBTable(reinterpret_cast<pint_t>(this->getReg(UNW_REG_IP)),
1273 reinterpret_cast<tbtable *>(_info.unwind_info),
1274 _registers, _isSignalFrame);
1275 }
1276#endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
12231277
1224 A &_addressSpace;1278 A &_addressSpace;
1225 R _registers;1279 R _registers;
1226 unw_proc_info_t _info;1280 unw_proc_info_t _info;
1227 bool _unwindInfoMissing;1281 bool _unwindInfoMissing;
1228 bool _isSignalFrame;1282 bool _isSignalFrame;
1229#if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64)1283#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
1230 bool _isSigReturn = false;1284 bool _isSigReturn = false;
1231#endif1285#endif
1232};1286};
...@@ -1292,6 +1346,13 @@ template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {...@@ -1292,6 +1346,13 @@ template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {
1292}1346}
1293#endif1347#endif
12941348
1349#ifdef _AIX
1350template <typename A, typename R>
1351uintptr_t UnwindCursor<A, R>::getDataRelBase() {
1352 return reinterpret_cast<uintptr_t>(_info.extra);
1353}
1354#endif
1355
1295template <typename A, typename R>1356template <typename A, typename R>
1296const char *UnwindCursor<A, R>::getRegisterName(int regNum) {1357const char *UnwindCursor<A, R>::getRegisterName(int regNum) {
1297 return _registers.getRegisterName(regNum);1358 return _registers.getRegisterName(regNum);
...@@ -1912,20 +1973,517 @@ bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {...@@ -1912,20 +1973,517 @@ bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {
1912 _info.handler = 0;1973 _info.handler = 0;
1913 }1974 }
1914 }1975 }
1915#elif defined(_LIBUNWIND_TARGET_ARM)
1916 _info.end_ip = _info.start_ip + unwindEntry->FunctionLength;
1917 _info.lsda = 0; // FIXME
1918 _info.handler = 0; // FIXME
1919#endif1976#endif
1920 setLastPC(pc);1977 setLastPC(pc);
1921 return true;1978 return true;
1922}1979}
1923#endif1980#endif
19241981
1982#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
1983// Masks for traceback table field xtbtable.
1984enum xTBTableMask : uint8_t {
1985 reservedBit = 0x02, // The traceback table was incorrectly generated if set
1986 // (see comments in function getInfoFromTBTable().
1987 ehInfoBit = 0x08 // Exception handling info is present if set
1988};
1989
1990enum frameType : unw_word_t {
1991 frameWithXLEHStateTable = 0,
1992 frameWithEHInfo = 1
1993};
1994
1995extern "C" {
1996typedef _Unwind_Reason_Code __xlcxx_personality_v0_t(int, _Unwind_Action,
1997 uint64_t,
1998 _Unwind_Exception *,
1999 struct _Unwind_Context *);
2000__attribute__((__weak__)) __xlcxx_personality_v0_t __xlcxx_personality_v0;
2001}
2002
2003static __xlcxx_personality_v0_t *xlcPersonalityV0;
2004static RWMutex xlcPersonalityV0InitLock;
2005
2006template <typename A, typename R>
2007bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R &registers) {
2008 uint32_t *p = reinterpret_cast<uint32_t *>(pc);
2009
2010 // Keep looking forward until a word of 0 is found. The traceback
2011 // table starts at the following word.
2012 while (*p)
2013 ++p;
2014 tbtable *TBTable = reinterpret_cast<tbtable *>(p + 1);
2015
2016 if (_LIBUNWIND_TRACING_UNWINDING) {
2017 char functionBuf[512];
2018 const char *functionName = functionBuf;
2019 unw_word_t offset;
2020 if (!getFunctionName(functionBuf, sizeof(functionBuf), &offset)) {
2021 functionName = ".anonymous.";
2022 }
2023 _LIBUNWIND_TRACE_UNWINDING("%s: Look up traceback table of func=%s at %p",
2024 __func__, functionName,
2025 reinterpret_cast<void *>(TBTable));
2026 }
2027
2028 // If the traceback table does not contain necessary info, bypass this frame.
2029 if (!TBTable->tb.has_tboff)
2030 return false;
2031
2032 // Structure tbtable_ext contains important data we are looking for.
2033 p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext);
2034
2035 // Skip field parminfo if it exists.
2036 if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
2037 ++p;
2038
2039 // p now points to tb_offset, the offset from start of function to TB table.
2040 unw_word_t start_ip =
2041 reinterpret_cast<unw_word_t>(TBTable) - *p - sizeof(uint32_t);
2042 unw_word_t end_ip = reinterpret_cast<unw_word_t>(TBTable);
2043 ++p;
2044
2045 _LIBUNWIND_TRACE_UNWINDING("start_ip=%p, end_ip=%p\n",
2046 reinterpret_cast<void *>(start_ip),
2047 reinterpret_cast<void *>(end_ip));
2048
2049 // Skip field hand_mask if it exists.
2050 if (TBTable->tb.int_hndl)
2051 ++p;
2052
2053 unw_word_t lsda = 0;
2054 unw_word_t handler = 0;
2055 unw_word_t flags = frameType::frameWithXLEHStateTable;
2056
2057 if (TBTable->tb.lang == TB_CPLUSPLUS && TBTable->tb.has_ctl) {
2058 // State table info is available. The ctl_info field indicates the
2059 // number of CTL anchors. There should be only one entry for the C++
2060 // state table.
2061 assert(*p == 1 && "libunwind: there must be only one ctl_info entry");
2062 ++p;
2063 // p points to the offset of the state table into the stack.
2064 pint_t stateTableOffset = *p++;
2065
2066 int framePointerReg;
2067
2068 // Skip fields name_len and name if exist.
2069 if (TBTable->tb.name_present) {
2070 const uint16_t name_len = *(reinterpret_cast<uint16_t *>(p));
2071 p = reinterpret_cast<uint32_t *>(reinterpret_cast<char *>(p) + name_len +
2072 sizeof(uint16_t));
2073 }
2074
2075 if (TBTable->tb.uses_alloca)
2076 framePointerReg = *(reinterpret_cast<char *>(p));
2077 else
2078 framePointerReg = 1; // default frame pointer == SP
2079
2080 _LIBUNWIND_TRACE_UNWINDING(
2081 "framePointerReg=%d, framePointer=%p, "
2082 "stateTableOffset=%#lx\n",
2083 framePointerReg,
2084 reinterpret_cast<void *>(_registers.getRegister(framePointerReg)),
2085 stateTableOffset);
2086 lsda = _registers.getRegister(framePointerReg) + stateTableOffset;
2087
2088 // Since the traceback table generated by the legacy XLC++ does not
2089 // provide the location of the personality for the state table,
2090 // function __xlcxx_personality_v0(), which is the personality for the state
2091 // table and is exported from libc++abi, is directly assigned as the
2092 // handler here. When a legacy XLC++ frame is encountered, the symbol
2093 // is resolved dynamically using dlopen() to avoid hard dependency from
2094 // libunwind on libc++abi.
2095
2096 // Resolve the function pointer to the state table personality if it has
2097 // not already.
2098 if (xlcPersonalityV0 == NULL) {
2099 xlcPersonalityV0InitLock.lock();
2100 if (xlcPersonalityV0 == NULL) {
2101 // If libc++abi is statically linked in, symbol __xlcxx_personality_v0
2102 // has been resolved at the link time.
2103 xlcPersonalityV0 = &__xlcxx_personality_v0;
2104 if (xlcPersonalityV0 == NULL) {
2105 // libc++abi is dynamically linked. Resolve __xlcxx_personality_v0
2106 // using dlopen().
2107 const char libcxxabi[] = "libc++abi.a(libc++abi.so.1)";
2108 void *libHandle;
2109 libHandle = dlopen(libcxxabi, RTLD_MEMBER | RTLD_NOW);
2110 if (libHandle == NULL) {
2111 _LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n",
2112 errno);
2113 assert(0 && "dlopen() failed");
2114 }
2115 xlcPersonalityV0 = reinterpret_cast<__xlcxx_personality_v0_t *>(
2116 dlsym(libHandle, "__xlcxx_personality_v0"));
2117 if (xlcPersonalityV0 == NULL) {
2118 _LIBUNWIND_TRACE_UNWINDING("dlsym() failed with errno=%d\n", errno);
2119 assert(0 && "dlsym() failed");
2120 }
2121 dlclose(libHandle);
2122 }
2123 }
2124 xlcPersonalityV0InitLock.unlock();
2125 }
2126 handler = reinterpret_cast<unw_word_t>(xlcPersonalityV0);
2127 _LIBUNWIND_TRACE_UNWINDING("State table: LSDA=%p, Personality=%p\n",
2128 reinterpret_cast<void *>(lsda),
2129 reinterpret_cast<void *>(handler));
2130 } else if (TBTable->tb.longtbtable) {
2131 // This frame has the traceback table extension. Possible cases are
2132 // 1) a C++ frame that has the 'eh_info' structure; 2) a C++ frame that
2133 // is not EH aware; or, 3) a frame of other languages. We need to figure out
2134 // if the traceback table extension contains the 'eh_info' structure.
2135 //
2136 // We also need to deal with the complexity arising from some XL compiler
2137 // versions use the wrong ordering of 'longtbtable' and 'has_vec' bits
2138 // where the 'longtbtable' bit is meant to be the 'has_vec' bit and vice
2139 // versa. For frames of code generated by those compilers, the 'longtbtable'
2140 // bit may be set but there isn't really a traceback table extension.
2141 //
2142 // In </usr/include/sys/debug.h>, there is the following definition of
2143 // 'struct tbtable_ext'. It is not really a structure but a dummy to
2144 // collect the description of optional parts of the traceback table.
2145 //
2146 // struct tbtable_ext {
2147 // ...
2148 // char alloca_reg; /* Register for alloca automatic storage */
2149 // struct vec_ext vec_ext; /* Vector extension (if has_vec is set) */
2150 // unsigned char xtbtable; /* More tbtable fields, if longtbtable is set*/
2151 // };
2152 //
2153 // Depending on how the 'has_vec'/'longtbtable' bit is interpreted, the data
2154 // following 'alloca_reg' can be treated either as 'struct vec_ext' or
2155 // 'unsigned char xtbtable'. 'xtbtable' bits are defined in
2156 // </usr/include/sys/debug.h> as flags. The 7th bit '0x02' is currently
2157 // unused and should not be set. 'struct vec_ext' is defined in
2158 // </usr/include/sys/debug.h> as follows:
2159 //
2160 // struct vec_ext {
2161 // unsigned vr_saved:6; /* Number of non-volatile vector regs saved
2162 // */
2163 // /* first register saved is assumed to be */
2164 // /* 32 - vr_saved */
2165 // unsigned saves_vrsave:1; /* Set if vrsave is saved on the stack */
2166 // unsigned has_varargs:1;
2167 // ...
2168 // };
2169 //
2170 // Here, the 7th bit is used as 'saves_vrsave'. To determine whether it
2171 // is 'struct vec_ext' or 'xtbtable' that follows 'alloca_reg',
2172 // we checks if the 7th bit is set or not because 'xtbtable' should
2173 // never have the 7th bit set. The 7th bit of 'xtbtable' will be reserved
2174 // in the future to make sure the mitigation works. This mitigation
2175 // is not 100% bullet proof because 'struct vec_ext' may not always have
2176 // 'saves_vrsave' bit set.
2177 //
2178 // 'reservedBit' is defined in enum 'xTBTableMask' above as the mask for
2179 // checking the 7th bit.
2180
2181 // p points to field name len.
2182 uint8_t *charPtr = reinterpret_cast<uint8_t *>(p);
2183
2184 // Skip fields name_len and name if they exist.
2185 if (TBTable->tb.name_present) {
2186 const uint16_t name_len = *(reinterpret_cast<uint16_t *>(charPtr));
2187 charPtr = charPtr + name_len + sizeof(uint16_t);
2188 }
2189
2190 // Skip field alloc_reg if it exists.
2191 if (TBTable->tb.uses_alloca)
2192 ++charPtr;
2193
2194 // Check traceback table bit has_vec. Skip struct vec_ext if it exists.
2195 if (TBTable->tb.has_vec)
2196 // Note struct vec_ext does exist at this point because whether the
2197 // ordering of longtbtable and has_vec bits is correct or not, both
2198 // are set.
2199 charPtr += sizeof(struct vec_ext);
2200
2201 // charPtr points to field 'xtbtable'. Check if the EH info is available.
2202 // Also check if the reserved bit of the extended traceback table field
2203 // 'xtbtable' is set. If it is, the traceback table was incorrectly
2204 // generated by an XL compiler that uses the wrong ordering of 'longtbtable'
2205 // and 'has_vec' bits and this is in fact 'struct vec_ext'. So skip the
2206 // frame.
2207 if ((*charPtr & xTBTableMask::ehInfoBit) &&
2208 !(*charPtr & xTBTableMask::reservedBit)) {
2209 // Mark this frame has the new EH info.
2210 flags = frameType::frameWithEHInfo;
2211
2212 // eh_info is available.
2213 charPtr++;
2214 // The pointer is 4-byte aligned.
2215 if (reinterpret_cast<uintptr_t>(charPtr) % 4)
2216 charPtr += 4 - reinterpret_cast<uintptr_t>(charPtr) % 4;
2217 uintptr_t *ehInfo =
2218 reinterpret_cast<uintptr_t *>(*(reinterpret_cast<uintptr_t *>(
2219 registers.getRegister(2) +
2220 *(reinterpret_cast<uintptr_t *>(charPtr)))));
2221
2222 // ehInfo points to structure en_info. The first member is version.
2223 // Only version 0 is currently supported.
2224 assert(*(reinterpret_cast<uint32_t *>(ehInfo)) == 0 &&
2225 "libunwind: ehInfo version other than 0 is not supported");
2226
2227 // Increment ehInfo to point to member lsda.
2228 ++ehInfo;
2229 lsda = *ehInfo++;
2230
2231 // enInfo now points to member personality.
2232 handler = *ehInfo;
2233
2234 _LIBUNWIND_TRACE_UNWINDING("Range table: LSDA=%#lx, Personality=%#lx\n",
2235 lsda, handler);
2236 }
2237 }
2238
2239 _info.start_ip = start_ip;
2240 _info.end_ip = end_ip;
2241 _info.lsda = lsda;
2242 _info.handler = handler;
2243 _info.gp = 0;
2244 _info.flags = flags;
2245 _info.format = 0;
2246 _info.unwind_info = reinterpret_cast<unw_word_t>(TBTable);
2247 _info.unwind_info_size = 0;
2248 _info.extra = registers.getRegister(2);
2249
2250 return true;
2251}
2252
2253// Step back up the stack following the frame back link.
2254template <typename A, typename R>
2255int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
2256 R &registers, bool &isSignalFrame) {
2257 if (_LIBUNWIND_TRACING_UNWINDING) {
2258 char functionBuf[512];
2259 const char *functionName = functionBuf;
2260 unw_word_t offset;
2261 if (!getFunctionName(functionBuf, sizeof(functionBuf), &offset)) {
2262 functionName = ".anonymous.";
2263 }
2264 _LIBUNWIND_TRACE_UNWINDING("%s: Look up traceback table of func=%s at %p",
2265 __func__, functionName,
2266 reinterpret_cast<void *>(TBTable));
2267 }
2268
2269#if defined(__powerpc64__)
2270 // Instruction to reload TOC register "l r2,40(r1)"
2271 const uint32_t loadTOCRegInst = 0xe8410028;
2272 const int32_t unwPPCF0Index = UNW_PPC64_F0;
2273 const int32_t unwPPCV0Index = UNW_PPC64_V0;
2274#else
2275 // Instruction to reload TOC register "l r2,20(r1)"
2276 const uint32_t loadTOCRegInst = 0x80410014;
2277 const int32_t unwPPCF0Index = UNW_PPC_F0;
2278 const int32_t unwPPCV0Index = UNW_PPC_V0;
2279#endif
2280
2281 R newRegisters = registers;
2282
2283 // lastStack points to the stack frame of the next routine up.
2284 pint_t lastStack = *(reinterpret_cast<pint_t *>(registers.getSP()));
2285
2286 // Return address is the address after call site instruction.
2287 pint_t returnAddress;
2288
2289 if (isSignalFrame) {
2290 _LIBUNWIND_TRACE_UNWINDING("Possible signal handler frame: lastStack=%p",
2291 reinterpret_cast<void *>(lastStack));
2292
2293 sigcontext *sigContext = reinterpret_cast<sigcontext *>(
2294 reinterpret_cast<char *>(lastStack) + STKMIN);
2295 returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;
2296
2297 _LIBUNWIND_TRACE_UNWINDING("From sigContext=%p, returnAddress=%p\n",
2298 reinterpret_cast<void *>(sigContext),
2299 reinterpret_cast<void *>(returnAddress));
2300
2301 if (returnAddress < 0x10000000) {
2302 // Try again using STKMINALIGN
2303 sigContext = reinterpret_cast<sigcontext *>(
2304 reinterpret_cast<char *>(lastStack) + STKMINALIGN);
2305 returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;
2306 if (returnAddress < 0x10000000) {
2307 _LIBUNWIND_TRACE_UNWINDING("Bad returnAddress=%p\n",
2308 reinterpret_cast<void *>(returnAddress));
2309 return UNW_EBADFRAME;
2310 } else {
2311 _LIBUNWIND_TRACE_UNWINDING("Tried again using STKMINALIGN: "
2312 "sigContext=%p, returnAddress=%p. "
2313 "Seems to be a valid address\n",
2314 reinterpret_cast<void *>(sigContext),
2315 reinterpret_cast<void *>(returnAddress));
2316 }
2317 }
2318 // Restore the condition register from sigcontext.
2319 newRegisters.setCR(sigContext->sc_jmpbuf.jmp_context.cr);
2320
2321 // Restore GPRs from sigcontext.
2322 for (int i = 0; i < 32; ++i)
2323 newRegisters.setRegister(i, sigContext->sc_jmpbuf.jmp_context.gpr[i]);
2324
2325 // Restore FPRs from sigcontext.
2326 for (int i = 0; i < 32; ++i)
2327 newRegisters.setFloatRegister(i + unwPPCF0Index,
2328 sigContext->sc_jmpbuf.jmp_context.fpr[i]);
2329
2330 // Restore vector registers if there is an associated extended context
2331 // structure.
2332 if (sigContext->sc_jmpbuf.jmp_context.msr & __EXTCTX) {
2333 ucontext_t *uContext = reinterpret_cast<ucontext_t *>(sigContext);
2334 if (uContext->__extctx->__extctx_magic == __EXTCTX_MAGIC) {
2335 for (int i = 0; i < 32; ++i)
2336 newRegisters.setVectorRegister(
2337 i + unwPPCV0Index, *(reinterpret_cast<v128 *>(
2338 &(uContext->__extctx->__vmx.__vr[i]))));
2339 }
2340 }
2341 } else {
2342 // Step up a normal frame.
2343 returnAddress = reinterpret_cast<pint_t *>(lastStack)[2];
2344
2345 _LIBUNWIND_TRACE_UNWINDING("Extract info from lastStack=%p, "
2346 "returnAddress=%p\n",
2347 reinterpret_cast<void *>(lastStack),
2348 reinterpret_cast<void *>(returnAddress));
2349 _LIBUNWIND_TRACE_UNWINDING("fpr_regs=%d, gpr_regs=%d, saves_cr=%d\n",
2350 TBTable->tb.fpr_saved, TBTable->tb.gpr_saved,
2351 TBTable->tb.saves_cr);
2352
2353 // Restore FP registers.
2354 char *ptrToRegs = reinterpret_cast<char *>(lastStack);
2355 double *FPRegs = reinterpret_cast<double *>(
2356 ptrToRegs - (TBTable->tb.fpr_saved * sizeof(double)));
2357 for (int i = 0; i < TBTable->tb.fpr_saved; ++i)
2358 newRegisters.setFloatRegister(
2359 32 - TBTable->tb.fpr_saved + i + unwPPCF0Index, FPRegs[i]);
2360
2361 // Restore GP registers.
2362 ptrToRegs = reinterpret_cast<char *>(FPRegs);
2363 uintptr_t *GPRegs = reinterpret_cast<uintptr_t *>(
2364 ptrToRegs - (TBTable->tb.gpr_saved * sizeof(uintptr_t)));
2365 for (int i = 0; i < TBTable->tb.gpr_saved; ++i)
2366 newRegisters.setRegister(32 - TBTable->tb.gpr_saved + i, GPRegs[i]);
2367
2368 // Restore Vector registers.
2369 ptrToRegs = reinterpret_cast<char *>(GPRegs);
2370
2371 // Restore vector registers only if this is a Clang frame. Also
2372 // check if traceback table bit has_vec is set. If it is, structure
2373 // vec_ext is available.
2374 if (_info.flags == frameType::frameWithEHInfo && TBTable->tb.has_vec) {
2375
2376 // Get to the vec_ext structure to check if vector registers are saved.
2377 uint32_t *p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext);
2378
2379 // Skip field parminfo if exists.
2380 if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
2381 ++p;
2382
2383 // Skip field tb_offset if exists.
2384 if (TBTable->tb.has_tboff)
2385 ++p;
2386
2387 // Skip field hand_mask if exists.
2388 if (TBTable->tb.int_hndl)
2389 ++p;
2390
2391 // Skip fields ctl_info and ctl_info_disp if exist.
2392 if (TBTable->tb.has_ctl) {
2393 // Skip field ctl_info.
2394 ++p;
2395 // Skip field ctl_info_disp.
2396 ++p;
2397 }
2398
2399 // Skip fields name_len and name if exist.
2400 // p is supposed to point to field name_len now.
2401 uint8_t *charPtr = reinterpret_cast<uint8_t *>(p);
2402 if (TBTable->tb.name_present) {
2403 const uint16_t name_len = *(reinterpret_cast<uint16_t *>(charPtr));
2404 charPtr = charPtr + name_len + sizeof(uint16_t);
2405 }
2406
2407 // Skip field alloc_reg if it exists.
2408 if (TBTable->tb.uses_alloca)
2409 ++charPtr;
2410
2411 struct vec_ext *vec_ext = reinterpret_cast<struct vec_ext *>(charPtr);
2412
2413 _LIBUNWIND_TRACE_UNWINDING("vr_saved=%d\n", vec_ext->vr_saved);
2414
2415 // Restore vector register(s) if saved on the stack.
2416 if (vec_ext->vr_saved) {
2417 // Saved vector registers are 16-byte aligned.
2418 if (reinterpret_cast<uintptr_t>(ptrToRegs) % 16)
2419 ptrToRegs -= reinterpret_cast<uintptr_t>(ptrToRegs) % 16;
2420 v128 *VecRegs = reinterpret_cast<v128 *>(ptrToRegs - vec_ext->vr_saved *
2421 sizeof(v128));
2422 for (int i = 0; i < vec_ext->vr_saved; ++i) {
2423 newRegisters.setVectorRegister(
2424 32 - vec_ext->vr_saved + i + unwPPCV0Index, VecRegs[i]);
2425 }
2426 }
2427 }
2428 if (TBTable->tb.saves_cr) {
2429 // Get the saved condition register. The condition register is only
2430 // a single word.
2431 newRegisters.setCR(
2432 *(reinterpret_cast<uint32_t *>(lastStack + sizeof(uintptr_t))));
2433 }
2434
2435 // Restore the SP.
2436 newRegisters.setSP(lastStack);
2437
2438 // The first instruction after return.
2439 uint32_t firstInstruction = *(reinterpret_cast<uint32_t *>(returnAddress));
2440
2441 // Do we need to set the TOC register?
2442 _LIBUNWIND_TRACE_UNWINDING(
2443 "Current gpr2=%p\n",
2444 reinterpret_cast<void *>(newRegisters.getRegister(2)));
2445 if (firstInstruction == loadTOCRegInst) {
2446 _LIBUNWIND_TRACE_UNWINDING(
2447 "Set gpr2=%p from frame\n",
2448 reinterpret_cast<void *>(reinterpret_cast<pint_t *>(lastStack)[5]));
2449 newRegisters.setRegister(2, reinterpret_cast<pint_t *>(lastStack)[5]);
2450 }
2451 }
2452 _LIBUNWIND_TRACE_UNWINDING("lastStack=%p, returnAddress=%p, pc=%p\n",
2453 reinterpret_cast<void *>(lastStack),
2454 reinterpret_cast<void *>(returnAddress),
2455 reinterpret_cast<void *>(pc));
2456
2457 // The return address is the address after call site instruction, so
2458 // setting IP to that simualates a return.
2459 newRegisters.setIP(reinterpret_cast<uintptr_t>(returnAddress));
2460
2461 // Simulate the step by replacing the register set with the new ones.
2462 registers = newRegisters;
2463
2464 // Check if the next frame is a signal frame.
2465 pint_t nextStack = *(reinterpret_cast<pint_t *>(registers.getSP()));
2466
2467 // Return address is the address after call site instruction.
2468 pint_t nextReturnAddress = reinterpret_cast<pint_t *>(nextStack)[2];
2469
2470 if (nextReturnAddress > 0x01 && nextReturnAddress < 0x10000) {
2471 _LIBUNWIND_TRACE_UNWINDING("The next is a signal handler frame: "
2472 "nextStack=%p, next return address=%p\n",
2473 reinterpret_cast<void *>(nextStack),
2474 reinterpret_cast<void *>(nextReturnAddress));
2475 isSignalFrame = true;
2476 } else {
2477 isSignalFrame = false;
2478 }
2479
2480 return UNW_STEP_SUCCESS;
2481}
2482#endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
19252483
1926template <typename A, typename R>2484template <typename A, typename R>
1927void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {2485void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
1928#if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64)2486#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
1929 _isSigReturn = false;2487 _isSigReturn = false;
1930#endif2488#endif
19312489
...@@ -1948,7 +2506,14 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {...@@ -1948,7 +2506,14 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
1948 // To disambiguate this, back up the pc when we know it is a return2506 // To disambiguate this, back up the pc when we know it is a return
1949 // address.2507 // address.
1950 if (isReturnAddress)2508 if (isReturnAddress)
2509#if defined(_AIX)
2510 // PC needs to be a 4-byte aligned address to be able to look for a
2511 // word of 0 that indicates the start of the traceback table at the end
2512 // of a function on AIX.
2513 pc -= 4;
2514#else
1951 --pc;2515 --pc;
2516#endif
19522517
1953 // Ask address space object to find unwind sections for this pc.2518 // Ask address space object to find unwind sections for this pc.
1954 UnwindInfoSections sects;2519 UnwindInfoSections sects;
...@@ -1982,6 +2547,12 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {...@@ -1982,6 +2547,12 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
1982 return;2547 return;
1983#endif2548#endif
19842549
2550#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2551 // If there is unwind info in the traceback table, look there next.
2552 if (this->getInfoFromTBTable(pc, _registers))
2553 return;
2554#endif
2555
1985#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)2556#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1986 // If there is dwarf unwind info, look there next.2557 // If there is dwarf unwind info, look there next.
1987 if (sects.dwarf_section != 0) {2558 if (sects.dwarf_section != 0) {
...@@ -2027,7 +2598,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {...@@ -2027,7 +2598,7 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
2027 }2598 }
2028#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)2599#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
20292600
2030#if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64)2601#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
2031 if (setInfoForSigReturn())2602 if (setInfoForSigReturn())
2032 return;2603 return;
2033#endif2604#endif
...@@ -2036,7 +2607,8 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {...@@ -2036,7 +2607,8 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
2036 _unwindInfoMissing = true;2607 _unwindInfoMissing = true;
2037}2608}
20382609
2039#if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64)2610#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
2611 defined(_LIBUNWIND_TARGET_AARCH64)
2040template <typename A, typename R>2612template <typename A, typename R>
2041bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {2613bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {
2042 // Look for the sigreturn trampoline. The trampoline's body is two2614 // Look for the sigreturn trampoline. The trampoline's body is two
...@@ -2055,14 +2627,28 @@ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {...@@ -2055,14 +2627,28 @@ bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {
2055 //2627 //
2056 // [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/vdso/sigreturn.S2628 // [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/vdso/sigreturn.S
2057 const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));2629 const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
2630 // The PC might contain an invalid address if the unwind info is bad, so
2631 // directly accessing it could cause a segfault. Use process_vm_readv to read
2632 // the memory safely instead. process_vm_readv was added in Linux 3.2, and
2633 // AArch64 supported was added in Linux 3.7, so the syscall is guaranteed to
2634 // be present. Unfortunately, there are Linux AArch64 environments where the
2635 // libc wrapper for the syscall might not be present (e.g. Android 5), so call
2636 // the syscall directly instead.
2637 uint32_t instructions[2];
2638 struct iovec local_iov = {&instructions, sizeof instructions};
2639 struct iovec remote_iov = {reinterpret_cast<void *>(pc), sizeof instructions};
2640 long bytesRead =
2641 syscall(SYS_process_vm_readv, getpid(), &local_iov, 1, &remote_iov, 1, 0);
2058 // Look for instructions: mov x8, #0x8b; svc #0x02642 // Look for instructions: mov x8, #0x8b; svc #0x0
2059 if (_addressSpace.get32(pc) == 0xd2801168 &&2643 if (bytesRead != sizeof instructions || instructions[0] != 0xd2801168 ||
2060 _addressSpace.get32(pc + 4) == 0xd4000001) {2644 instructions[1] != 0xd4000001)
2061 _info = {};2645 return false;
2062 _isSigReturn = true;2646
2063 return true;2647 _info = {};
2064 }2648 _info.start_ip = pc;
2065 return false;2649 _info.end_ip = pc + 4;
2650 _isSigReturn = true;
2651 return true;
2066}2652}
20672653
2068template <typename A, typename R>2654template <typename A, typename R>
...@@ -2096,7 +2682,114 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {...@@ -2096,7 +2682,114 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {
2096 _isSignalFrame = true;2682 _isSignalFrame = true;
2097 return UNW_STEP_SUCCESS;2683 return UNW_STEP_SUCCESS;
2098}2684}
2099#endif // defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64)2685#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
2686 // defined(_LIBUNWIND_TARGET_AARCH64)
2687
2688#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
2689 defined(_LIBUNWIND_TARGET_S390X)
2690template <typename A, typename R>
2691bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_s390x &) {
2692 // Look for the sigreturn trampoline. The trampoline's body is a
2693 // specific instruction (see below). Typically the trampoline comes from the
2694 // vDSO (i.e. the __kernel_[rt_]sigreturn function). A libc might provide its
2695 // own restorer function, though, or user-mode QEMU might write a trampoline
2696 // onto the stack.
2697 const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
2698 // The PC might contain an invalid address if the unwind info is bad, so
2699 // directly accessing it could cause a segfault. Use process_vm_readv to
2700 // read the memory safely instead.
2701 uint16_t inst;
2702 struct iovec local_iov = {&inst, sizeof inst};
2703 struct iovec remote_iov = {reinterpret_cast<void *>(pc), sizeof inst};
2704 long bytesRead = process_vm_readv(getpid(), &local_iov, 1, &remote_iov, 1, 0);
2705 if (bytesRead == sizeof inst && (inst == 0x0a77 || inst == 0x0aad)) {
2706 _info = {};
2707 _info.start_ip = pc;
2708 _info.end_ip = pc + 2;
2709 _isSigReturn = true;
2710 return true;
2711 }
2712 return false;
2713}
2714
2715template <typename A, typename R>
2716int UnwindCursor<A, R>::stepThroughSigReturn(Registers_s390x &) {
2717 // Determine current SP.
2718 const pint_t sp = static_cast<pint_t>(this->getReg(UNW_REG_SP));
2719 // According to the s390x ABI, the CFA is at (incoming) SP + 160.
2720 const pint_t cfa = sp + 160;
2721
2722 // Determine current PC and instruction there (this must be either
2723 // a "svc __NR_sigreturn" or "svc __NR_rt_sigreturn").
2724 const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
2725 const uint16_t inst = _addressSpace.get16(pc);
2726
2727 // Find the addresses of the signo and sigcontext in the frame.
2728 pint_t pSigctx = 0;
2729 pint_t pSigno = 0;
2730
2731 // "svc __NR_sigreturn" uses a non-RT signal trampoline frame.
2732 if (inst == 0x0a77) {
2733 // Layout of a non-RT signal trampoline frame, starting at the CFA:
2734 // - 8-byte signal mask
2735 // - 8-byte pointer to sigcontext, followed by signo
2736 // - 4-byte signo
2737 pSigctx = _addressSpace.get64(cfa + 8);
2738 pSigno = pSigctx + 344;
2739 }
2740
2741 // "svc __NR_rt_sigreturn" uses a RT signal trampoline frame.
2742 if (inst == 0x0aad) {
2743 // Layout of a RT signal trampoline frame, starting at the CFA:
2744 // - 8-byte retcode (+ alignment)
2745 // - 128-byte siginfo struct (starts with signo)
2746 // - ucontext struct:
2747 // - 8-byte long (uc_flags)
2748 // - 8-byte pointer (uc_link)
2749 // - 24-byte stack_t
2750 // - 8 bytes of padding because sigcontext has 16-byte alignment
2751 // - sigcontext/mcontext_t
2752 pSigctx = cfa + 8 + 128 + 8 + 8 + 24 + 8;
2753 pSigno = cfa + 8;
2754 }
2755
2756 assert(pSigctx != 0);
2757 assert(pSigno != 0);
2758
2759 // Offsets from sigcontext to each register.
2760 const pint_t kOffsetPc = 8;
2761 const pint_t kOffsetGprs = 16;
2762 const pint_t kOffsetFprs = 216;
2763
2764 // Restore all registers.
2765 for (int i = 0; i < 16; ++i) {
2766 uint64_t value = _addressSpace.get64(pSigctx + kOffsetGprs +
2767 static_cast<pint_t>(i * 8));
2768 _registers.setRegister(UNW_S390X_R0 + i, value);
2769 }
2770 for (int i = 0; i < 16; ++i) {
2771 static const int fpr[16] = {
2772 UNW_S390X_F0, UNW_S390X_F1, UNW_S390X_F2, UNW_S390X_F3,
2773 UNW_S390X_F4, UNW_S390X_F5, UNW_S390X_F6, UNW_S390X_F7,
2774 UNW_S390X_F8, UNW_S390X_F9, UNW_S390X_F10, UNW_S390X_F11,
2775 UNW_S390X_F12, UNW_S390X_F13, UNW_S390X_F14, UNW_S390X_F15
2776 };
2777 double value = _addressSpace.getDouble(pSigctx + kOffsetFprs +
2778 static_cast<pint_t>(i * 8));
2779 _registers.setFloatRegister(fpr[i], value);
2780 }
2781 _registers.setIP(_addressSpace.get64(pSigctx + kOffsetPc));
2782
2783 // SIGILL, SIGFPE and SIGTRAP are delivered with psw_addr
2784 // after the faulting instruction rather than before it.
2785 // Do not set _isSignalFrame in that case.
2786 uint32_t signo = _addressSpace.get32(pSigno);
2787 _isSignalFrame = (signo != 4 && signo != 5 && signo != 8);
2788
2789 return UNW_STEP_SUCCESS;
2790}
2791#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
2792 // defined(_LIBUNWIND_TARGET_S390X)
21002793
2101template <typename A, typename R>2794template <typename A, typename R>
2102int UnwindCursor<A, R>::step() {2795int UnwindCursor<A, R>::step() {
...@@ -2106,7 +2799,7 @@ int UnwindCursor<A, R>::step() {...@@ -2106,7 +2799,7 @@ int UnwindCursor<A, R>::step() {
21062799
2107 // Use unwinding info to modify register set as if function returned.2800 // Use unwinding info to modify register set as if function returned.
2108 int result;2801 int result;
2109#if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64)2802#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
2110 if (_isSigReturn) {2803 if (_isSigReturn) {
2111 result = this->stepThroughSigReturn();2804 result = this->stepThroughSigReturn();
2112 } else2805 } else
...@@ -2116,6 +2809,8 @@ int UnwindCursor<A, R>::step() {...@@ -2116,6 +2809,8 @@ int UnwindCursor<A, R>::step() {
2116 result = this->stepWithCompactEncoding();2809 result = this->stepWithCompactEncoding();
2117#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)2810#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
2118 result = this->stepWithSEHData();2811 result = this->stepWithSEHData();
2812#elif defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2813 result = this->stepWithTBTableData();
2119#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)2814#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2120 result = this->stepWithDwarfFDE();2815 result = this->stepWithDwarfFDE();
2121#elif defined(_LIBUNWIND_ARM_EHABI)2816#elif defined(_LIBUNWIND_ARM_EHABI)
lib/libunwind/src/UnwindLevel1-gcc-ext.c+5-2
...@@ -59,12 +59,15 @@ _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) {...@@ -59,12 +59,15 @@ _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) {
59/// relative encodings.59/// relative encodings.
60_LIBUNWIND_EXPORT uintptr_t60_LIBUNWIND_EXPORT uintptr_t
61_Unwind_GetDataRelBase(struct _Unwind_Context *context) {61_Unwind_GetDataRelBase(struct _Unwind_Context *context) {
62 (void)context;
63 _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", (void *)context);62 _LIBUNWIND_TRACE_API("_Unwind_GetDataRelBase(context=%p)", (void *)context);
63#if defined(_AIX)
64 return unw_get_data_rel_base((unw_cursor_t *)context);
65#else
66 (void)context;
64 _LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented");67 _LIBUNWIND_ABORT("_Unwind_GetDataRelBase() not implemented");
68#endif
65}69}
6670
67
68/// Called by personality handler during phase 2 to get base address for text71/// Called by personality handler during phase 2 to get base address for text
69/// relative encodings.72/// relative encodings.
70_LIBUNWIND_EXPORT uintptr_t73_LIBUNWIND_EXPORT uintptr_t
lib/libunwind/src/UnwindLevel1.c+7-1
...@@ -44,7 +44,11 @@...@@ -44,7 +44,11 @@
44// directly jump to __libunwind_Registerts_x86/x86_64_jumpto instead of using44// directly jump to __libunwind_Registerts_x86/x86_64_jumpto instead of using
45// a regular function call to avoid pushing to CET shadow stack again.45// a regular function call to avoid pushing to CET shadow stack again.
46#if !defined(_LIBUNWIND_USE_CET)46#if !defined(_LIBUNWIND_USE_CET)
47#define __unw_phase2_resume(cursor, fn) __unw_resume((cursor))47#define __unw_phase2_resume(cursor, fn) \
48 do { \
49 (void)fn; \
50 __unw_resume((cursor)); \
51 } while (0)
48#elif defined(_LIBUNWIND_TARGET_I386)52#elif defined(_LIBUNWIND_TARGET_I386)
49#define __unw_phase2_resume(cursor, fn) \53#define __unw_phase2_resume(cursor, fn) \
50 do { \54 do { \
...@@ -480,11 +484,13 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {...@@ -480,11 +484,13 @@ _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
480 _LIBUNWIND_TRACE_API(484 _LIBUNWIND_TRACE_API(
481 "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR,485 "_Unwind_GetLanguageSpecificData(context=%p) => 0x%" PRIxPTR,
482 (void *)context, result);486 (void *)context, result);
487#if !defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
483 if (result != 0) {488 if (result != 0) {
484 if (*((uint8_t *)result) != 0xFF)489 if (*((uint8_t *)result) != 0xFF)
485 _LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF",490 _LIBUNWIND_DEBUG_LOG("lsda at 0x%" PRIxPTR " does not start with 0xFF",
486 result);491 result);
487 }492 }
493#endif
488 return result;494 return result;
489}495}
490496
lib/libunwind/src/UnwindRegistersRestore.S+138-61
...@@ -8,7 +8,11 @@...@@ -8,7 +8,11 @@
88
9#include "assembly.h"9#include "assembly.h"
1010
11#if defined(_AIX)
12 .toc
13#else
11 .text14 .text
15#endif
1216
13#if !defined(__USING_SJLJ_EXCEPTIONS__)17#if !defined(__USING_SJLJ_EXCEPTIONS__)
1418
...@@ -222,27 +226,36 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv)...@@ -222,27 +226,36 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv)
222 PPC64_LVS(30)226 PPC64_LVS(30)
223 PPC64_LVS(31)227 PPC64_LVS(31)
224228
225 // use VRSAVE to conditionally restore the remaining VS regs,229#define PPC64_CLVS_RESTORE(n) \
226 // that are where the V regs are mapped230 addi 4, 3, PPC64_OFFS_FP + n * 16 ;\
231 lxvd2x n, 0, 4
227232
233#if !defined(_AIX)
234 // use VRSAVE to conditionally restore the remaining VS regs, that are
235 // where the V regs are mapped. In the AIX ABI, VRSAVE is not used.
228 ld 5, PPC64_OFFS_VRSAVE(3) // test VRsave236 ld 5, PPC64_OFFS_VRSAVE(3) // test VRsave
229 cmpwi 5, 0237 cmpwi 5, 0
230 beq Lnovec238 beq Lnovec
231239
232// conditionally load VS240// conditionally load VS
233#define PPC64_CLVS_BOTTOM(n) \241#define PPC64_CLVSl(n) \
234 beq Ldone##n ;\242 andis. 0, 5, (1 PPC_LEFT_SHIFT(47-n)) ;\
235 addi 4, 3, PPC64_OFFS_FP + n * 16 ;\243 beq Ldone##n ;\
236 lxvd2x n, 0, 4 ;\244 PPC64_CLVS_RESTORE(n) ;\
237Ldone##n:245Ldone##n:
238246
239#define PPC64_CLVSl(n) \247#define PPC64_CLVSh(n) \
240 andis. 0, 5, (1 PPC_LEFT_SHIFT(47-n)) ;\248 andi. 0, 5, (1 PPC_LEFT_SHIFT(63-n)) ;\
241PPC64_CLVS_BOTTOM(n)249 beq Ldone##n ;\
250 PPC64_CLVS_RESTORE(n) ;\
251Ldone##n:
252
253#else
242254
243#define PPC64_CLVSh(n) \255#define PPC64_CLVSl(n) PPC64_CLVS_RESTORE(n)
244 andi. 0, 5, (1 PPC_LEFT_SHIFT(63-n)) ;\256#define PPC64_CLVSh(n) PPC64_CLVS_RESTORE(n)
245PPC64_CLVS_BOTTOM(n)257
258#endif // !defined(_AIX)
246259
247 PPC64_CLVSl(32)260 PPC64_CLVSl(32)
248 PPC64_CLVSl(33)261 PPC64_CLVSl(33)
...@@ -318,32 +331,44 @@ PPC64_CLVS_BOTTOM(n)...@@ -318,32 +331,44 @@ PPC64_CLVS_BOTTOM(n)
318 PPC64_LF(31)331 PPC64_LF(31)
319332
320#if defined(__ALTIVEC__)333#if defined(__ALTIVEC__)
321 // restore vector registers if any are in use334
335#define PPC64_CLV_UNALIGNED_RESTORE(n) \
336 ld 0, (PPC64_OFFS_V + n * 16)(3) ;\
337 std 0, 0(4) ;\
338 ld 0, (PPC64_OFFS_V + n * 16 + 8)(3) ;\
339 std 0, 8(4) ;\
340 lvx n, 0, 4
341
342#if !defined(_AIX)
343 // restore vector registers if any are in use. In the AIX ABI, VRSAVE is
344 // not used.
322 ld 5, PPC64_OFFS_VRSAVE(3) // test VRsave345 ld 5, PPC64_OFFS_VRSAVE(3) // test VRsave
323 cmpwi 5, 0346 cmpwi 5, 0
324 beq Lnovec347 beq Lnovec
325348
326 subi 4, 1, 16349#define PPC64_CLV_UNALIGNEDl(n) \
327 // r4 is now a 16-byte aligned pointer into the red zone350 andis. 0, 5, (1 PPC_LEFT_SHIFT(15-n)) ;\
328 // the _vectorScalarRegisters may not be 16-byte aligned351 beq Ldone##n ;\
329 // so copy via red zone temp buffer352 PPC64_CLV_UNALIGNED_RESTORE(n) ;\
353Ldone ## n:
330354
331#define PPC64_CLV_UNALIGNED_BOTTOM(n) \355#define PPC64_CLV_UNALIGNEDh(n) \
332 beq Ldone##n ;\356 andi. 0, 5, (1 PPC_LEFT_SHIFT(31-n)) ;\
333 ld 0, (PPC64_OFFS_V + n * 16)(3) ;\357 beq Ldone##n ;\
334 std 0, 0(4) ;\358 PPC64_CLV_UNALIGNED_RESTORE(n) ;\
335 ld 0, (PPC64_OFFS_V + n * 16 + 8)(3) ;\
336 std 0, 8(4) ;\
337 lvx n, 0, 4 ;\
338Ldone ## n:359Ldone ## n:
339360
340#define PPC64_CLV_UNALIGNEDl(n) \361#else
341 andis. 0, 5, (1 PPC_LEFT_SHIFT(15-n)) ;\362
342PPC64_CLV_UNALIGNED_BOTTOM(n)363#define PPC64_CLV_UNALIGNEDl(n) PPC64_CLV_UNALIGNED_RESTORE(n)
364#define PPC64_CLV_UNALIGNEDh(n) PPC64_CLV_UNALIGNED_RESTORE(n)
365
366#endif // !defined(_AIX)
343367
344#define PPC64_CLV_UNALIGNEDh(n) \368 subi 4, 1, 16
345 andi. 0, 5, (1 PPC_LEFT_SHIFT(31-n)) ;\369 // r4 is now a 16-byte aligned pointer into the red zone
346PPC64_CLV_UNALIGNED_BOTTOM(n)370 // the _vectorScalarRegisters may not be 16-byte aligned
371 // so copy via red zone temp buffer
347372
348 PPC64_CLV_UNALIGNEDl(0)373 PPC64_CLV_UNALIGNEDl(0)
349 PPC64_CLV_UNALIGNEDl(1)374 PPC64_CLV_UNALIGNEDl(1)
...@@ -387,11 +412,23 @@ Lnovec:...@@ -387,11 +412,23 @@ Lnovec:
387 ld 0, PPC64_OFFS_SRR0(3)412 ld 0, PPC64_OFFS_SRR0(3)
388 mtctr 0413 mtctr 0
389414
415#if defined(_AIX)
416 // After setting GPR1 to a higher address, AIX wipes out the original
417 // stack space below that address invalidated by the new GPR1 value. Use
418 // GPR0 to save the value of GPR3 in the context before it is wiped out.
419 // This compromises the content of GPR0 which is a volatile register.
420 ld 0, (8 * (3 + 2))(3)
421#else
390 PPC64_LR(0)422 PPC64_LR(0)
423#endif
391 PPC64_LR(5)424 PPC64_LR(5)
392 PPC64_LR(4)425 PPC64_LR(4)
393 PPC64_LR(1)426 PPC64_LR(1)
427#if defined(_AIX)
428 mr 3, 0
429#else
394 PPC64_LR(3)430 PPC64_LR(3)
431#endif
395 bctr432 bctr
396433
397#elif defined(__powerpc__)434#elif defined(__powerpc__)
...@@ -475,45 +512,48 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv)...@@ -475,45 +512,48 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv)
475#endif512#endif
476513
477#if defined(__ALTIVEC__)514#if defined(__ALTIVEC__)
478 // restore vector registers if any are in use515
516#define LOAD_VECTOR_RESTORE(_index) \
517 lwz 0, 424+_index*16(3) SEPARATOR \
518 stw 0, 0(4) SEPARATOR \
519 lwz 0, 424+_index*16+4(3) SEPARATOR \
520 stw 0, 4(4) SEPARATOR \
521 lwz 0, 424+_index*16+8(3) SEPARATOR \
522 stw 0, 8(4) SEPARATOR \
523 lwz 0, 424+_index*16+12(3) SEPARATOR \
524 stw 0, 12(4) SEPARATOR \
525 lvx _index, 0, 4
526
527#if !defined(_AIX)
528 // restore vector registers if any are in use. In the AIX ABI, VRSAVE
529 // is not used.
479 lwz 5, 156(3) // test VRsave530 lwz 5, 156(3) // test VRsave
480 cmpwi 5, 0531 cmpwi 5, 0
481 beq Lnovec532 beq Lnovec
482533
483 subi 4, 1, 16534#define LOAD_VECTOR_UNALIGNEDl(_index) \
484 rlwinm 4, 4, 0, 0, 27 // mask low 4-bits535 andis. 0, 5, (1 PPC_LEFT_SHIFT(15-_index)) SEPARATOR \
485 // r4 is now a 16-byte aligned pointer into the red zone536 beq Ldone ## _index SEPARATOR \
486 // the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer537 LOAD_VECTOR_RESTORE(_index) SEPARATOR \
487
488
489#define LOAD_VECTOR_UNALIGNEDl(_index) \
490 andis. 0, 5, (1 PPC_LEFT_SHIFT(15-_index)) SEPARATOR \
491 beq Ldone ## _index SEPARATOR \
492 lwz 0, 424+_index*16(3) SEPARATOR \
493 stw 0, 0(%r4) SEPARATOR \
494 lwz 0, 424+_index*16+4(%r3) SEPARATOR \
495 stw 0, 4(%r4) SEPARATOR \
496 lwz 0, 424+_index*16+8(%r3) SEPARATOR \
497 stw 0, 8(%r4) SEPARATOR \
498 lwz 0, 424+_index*16+12(%r3) SEPARATOR \
499 stw 0, 12(%r4) SEPARATOR \
500 lvx _index, 0, 4 SEPARATOR \
501 Ldone ## _index:538 Ldone ## _index:
502539
503#define LOAD_VECTOR_UNALIGNEDh(_index) \540#define LOAD_VECTOR_UNALIGNEDh(_index) \
504 andi. 0, 5, (1 PPC_LEFT_SHIFT(31-_index)) SEPARATOR \541 andi. 0, 5, (1 PPC_LEFT_SHIFT(31-_index)) SEPARATOR \
505 beq Ldone ## _index SEPARATOR \542 beq Ldone ## _index SEPARATOR \
506 lwz 0, 424+_index*16(3) SEPARATOR \543 LOAD_VECTOR_RESTORE(_index) SEPARATOR \
507 stw 0, 0(4) SEPARATOR \
508 lwz 0, 424+_index*16+4(3) SEPARATOR \
509 stw 0, 4(4) SEPARATOR \
510 lwz 0, 424+_index*16+8(3) SEPARATOR \
511 stw 0, 8(%r4) SEPARATOR \
512 lwz 0, 424+_index*16+12(3) SEPARATOR \
513 stw 0, 12(4) SEPARATOR \
514 lvx _index, 0, 4 SEPARATOR \
515 Ldone ## _index:544 Ldone ## _index:
516545
546#else
547
548#define LOAD_VECTOR_UNALIGNEDl(_index) LOAD_VECTOR_RESTORE(_index)
549#define LOAD_VECTOR_UNALIGNEDh(_index) LOAD_VECTOR_RESTORE(_index)
550
551#endif // !defined(_AIX)
552
553 subi 4, 1, 16
554 rlwinm 4, 4, 0, 0, 27 // mask low 4-bits
555 // r4 is now a 16-byte aligned pointer into the red zone
556 // the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer
517557
518 LOAD_VECTOR_UNALIGNEDl(0)558 LOAD_VECTOR_UNALIGNEDl(0)
519 LOAD_VECTOR_UNALIGNEDl(1)559 LOAD_VECTOR_UNALIGNEDl(1)
...@@ -1212,6 +1252,43 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv)...@@ -1212,6 +1252,43 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv)
12121252
1213 ret // jump to ra1253 ret // jump to ra
12141254
1255#elif defined(__s390x__)
1256
1257DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_s390x6jumptoEv)
1258//
1259// void libunwind::Registers_s390x::jumpto()
1260//
1261// On entry:
1262// thread_state pointer is in r2
1263//
1264
1265 // Skip PSWM, but load PSWA into r1
1266 lg %r1, 8(%r2)
1267
1268 // Restore FPRs
1269 ld %f0, 144(%r2)
1270 ld %f1, 152(%r2)
1271 ld %f2, 160(%r2)
1272 ld %f3, 168(%r2)
1273 ld %f4, 176(%r2)
1274 ld %f5, 184(%r2)
1275 ld %f6, 192(%r2)
1276 ld %f7, 200(%r2)
1277 ld %f8, 208(%r2)
1278 ld %f9, 216(%r2)
1279 ld %f10, 224(%r2)
1280 ld %f11, 232(%r2)
1281 ld %f12, 240(%r2)
1282 ld %f13, 248(%r2)
1283 ld %f14, 256(%r2)
1284 ld %f15, 264(%r2)
1285
1286 // Restore GPRs - skipping %r0 and %r1
1287 lmg %r2, %r15, 32(%r2)
1288
1289 // Return to PSWA (was loaded into %r1 above)
1290 br %r1
1291
1215#endif1292#endif
12161293
1217#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */1294#endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */
lib/libunwind/src/UnwindRegistersSave.S+55-1
...@@ -8,7 +8,11 @@...@@ -8,7 +8,11 @@
88
9#include "assembly.h"9#include "assembly.h"
1010
11#if defined(_AIX)
12 .toc
13#else
11 .text14 .text
15#endif
1216
13#if !defined(__USING_SJLJ_EXCEPTIONS__)17#if !defined(__USING_SJLJ_EXCEPTIONS__)
1418
...@@ -334,8 +338,11 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)...@@ -334,8 +338,11 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
334// On entry:338// On entry:
335// thread_state pointer is in r3339// thread_state pointer is in r3
336//340//
341#if defined(_AIX)
342DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(__unw_getcontext, unw_getcontext)
343#else
337DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)344DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
338345#endif
339// store register (GPR)346// store register (GPR)
340#define PPC64_STR(n) \347#define PPC64_STR(n) \
341 std n, (8 * (n + 2))(3)348 std n, (8 * (n + 2))(3)
...@@ -567,7 +574,11 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)...@@ -567,7 +574,11 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
567// On entry:574// On entry:
568// thread_state pointer is in r3575// thread_state pointer is in r3
569//576//
577#if defined(_AIX)
578DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(__unw_getcontext, unw_getcontext)
579#else
570DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)580DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
581#endif
571 stw 0, 8(3)582 stw 0, 8(3)
572 mflr 0583 mflr 0
573 stw 0, 0(3) // store lr as ssr0584 stw 0, 0(3) // store lr as ssr0
...@@ -1168,6 +1179,49 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)...@@ -1168,6 +1179,49 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
11681179
1169 li a0, 0 // return UNW_ESUCCESS1180 li a0, 0 // return UNW_ESUCCESS
1170 ret // jump to ra1181 ret // jump to ra
1182
1183#elif defined(__s390x__)
1184
1185//
1186// extern int __unw_getcontext(unw_context_t* thread_state)
1187//
1188// On entry:
1189// thread_state pointer is in r2
1190//
1191DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext)
1192
1193 // Save GPRs
1194 stmg %r0, %r15, 16(%r2)
1195
1196 // Save PSWM
1197 epsw %r0, %r1
1198 stm %r0, %r1, 0(%r2)
1199
1200 // Store return address as PSWA
1201 stg %r14, 8(%r2)
1202
1203 // Save FPRs
1204 std %f0, 144(%r2)
1205 std %f1, 152(%r2)
1206 std %f2, 160(%r2)
1207 std %f3, 168(%r2)
1208 std %f4, 176(%r2)
1209 std %f5, 184(%r2)
1210 std %f6, 192(%r2)
1211 std %f7, 200(%r2)
1212 std %f8, 208(%r2)
1213 std %f9, 216(%r2)
1214 std %f10, 224(%r2)
1215 std %f11, 232(%r2)
1216 std %f12, 240(%r2)
1217 std %f13, 248(%r2)
1218 std %f14, 256(%r2)
1219 std %f15, 264(%r2)
1220
1221 // Return UNW_ESUCCESS
1222 lghi %r2, 0
1223 br %r14
1224
1171#endif1225#endif
11721226
1173 WEAK_ALIAS(__unw_getcontext, unw_getcontext)1227 WEAK_ALIAS(__unw_getcontext, unw_getcontext)
lib/libunwind/src/Unwind_AIXExtras.cpp created+63
...@@ -0,0 +1,63 @@
1//===--------------------- Unwind_AIXExtras.cpp -------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//
8//===----------------------------------------------------------------------===//
9
10// This file is only used for AIX.
11#if defined(_AIX)
12
13#include "config.h"
14#include "libunwind_ext.h"
15#include <sys/debug.h>
16
17namespace libunwind {
18// getFuncNameFromTBTable
19// Get the function name from its traceback table.
20char *getFuncNameFromTBTable(uintptr_t Pc, uint16_t &NameLen,
21 unw_word_t *Offset) {
22 uint32_t *p = reinterpret_cast<uint32_t *>(Pc);
23 *Offset = 0;
24
25 // Keep looking forward until a word of 0 is found. The traceback
26 // table starts at the following word.
27 while (*p)
28 p++;
29 tbtable *TBTable = reinterpret_cast<tbtable *>(p + 1);
30
31 if (!TBTable->tb.name_present)
32 return NULL;
33
34 // Get to the name of the function.
35 p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext);
36
37 // Skip field parminfo if it exists.
38 if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
39 p++;
40
41 // If the tb_offset field exisits, get the offset from the start of
42 // the function to pc. Skip the field.
43 if (TBTable->tb.has_tboff) {
44 unw_word_t StartIp =
45 reinterpret_cast<uintptr_t>(TBTable) - *p - sizeof(uint32_t);
46 *Offset = Pc - StartIp;
47 p++;
48 }
49
50 // Skip field hand_mask if it exists.
51 if (TBTable->tb.int_hndl)
52 p++;
53
54 // Skip fields ctl_info and ctl_info_disp if they exist.
55 if (TBTable->tb.has_ctl) {
56 p += 1 + *p;
57 }
58
59 NameLen = *(reinterpret_cast<uint16_t *>(p));
60 return reinterpret_cast<char *>(p) + sizeof(uint16_t);
61}
62} // namespace libunwind
63#endif // defined(_AIX)
lib/libunwind/src/assembly.h+48-1
...@@ -67,7 +67,8 @@...@@ -67,7 +67,8 @@
67#define SEPARATOR ;67#define SEPARATOR ;
68#endif68#endif
6969
70#if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1)70#if defined(__powerpc64__) && (!defined(_CALL_ELF) || _CALL_ELF == 1) && \
71 !defined(_AIX)
71#define PPC64_OPD1 .section .opd,"aw",@progbits SEPARATOR72#define PPC64_OPD1 .section .opd,"aw",@progbits SEPARATOR
72#define PPC64_OPD2 SEPARATOR \73#define PPC64_OPD2 SEPARATOR \
73 .p2align 3 SEPARATOR \74 .p2align 3 SEPARATOR \
...@@ -203,12 +204,57 @@...@@ -203,12 +204,57 @@
203204
204#elif defined(__sparc__)205#elif defined(__sparc__)
205206
207#elif defined(_AIX)
208
209#if defined(__powerpc64__)
210#define VBYTE_LEN 8
211#define CSECT_ALIGN 3
212#else
213#define VBYTE_LEN 4
214#define CSECT_ALIGN 2
215#endif
216
217// clang-format off
218#define DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(name, aliasname) \
219 .csect .text[PR], 2 SEPARATOR \
220 .csect .name[PR], 2 SEPARATOR \
221 .globl name[DS] SEPARATOR \
222 .globl .name[PR] SEPARATOR \
223 .align 4 SEPARATOR \
224 .csect name[DS], CSECT_ALIGN SEPARATOR \
225aliasname: \
226 .vbyte VBYTE_LEN, .name[PR] SEPARATOR \
227 .vbyte VBYTE_LEN, TOC[TC0] SEPARATOR \
228 .vbyte VBYTE_LEN, 0 SEPARATOR \
229 .weak aliasname SEPARATOR \
230 .weak .aliasname SEPARATOR \
231 .csect .name[PR], 2 SEPARATOR \
232.aliasname: \
233
234#define WEAK_ALIAS(name, aliasname)
235#define NO_EXEC_STACK_DIRECTIVE
236
237// clang-format on
206#else238#else
207239
208#error Unsupported target240#error Unsupported target
209241
210#endif242#endif
211243
244#if defined(_AIX)
245 // clang-format off
246#define DEFINE_LIBUNWIND_FUNCTION(name) \
247 .globl name[DS] SEPARATOR \
248 .globl .name SEPARATOR \
249 .align 4 SEPARATOR \
250 .csect name[DS], CSECT_ALIGN SEPARATOR \
251 .vbyte VBYTE_LEN, .name SEPARATOR \
252 .vbyte VBYTE_LEN, TOC[TC0] SEPARATOR \
253 .vbyte VBYTE_LEN, 0 SEPARATOR \
254 .csect .text[PR], 2 SEPARATOR \
255.name:
256 // clang-format on
257#else
212#define DEFINE_LIBUNWIND_FUNCTION(name) \258#define DEFINE_LIBUNWIND_FUNCTION(name) \
213 .globl SYMBOL_NAME(name) SEPARATOR \259 .globl SYMBOL_NAME(name) SEPARATOR \
214 HIDDEN_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \260 HIDDEN_SYMBOL(SYMBOL_NAME(name)) SEPARATOR \
...@@ -217,6 +263,7 @@...@@ -217,6 +263,7 @@
217 SYMBOL_NAME(name): \263 SYMBOL_NAME(name): \
218 PPC64_OPD2 \264 PPC64_OPD2 \
219 AARCH64_BTI265 AARCH64_BTI
266#endif
220267
221#if defined(__arm__)268#if defined(__arm__)
222#if !defined(__ARM_ARCH)269#if !defined(__ARM_ARCH)
lib/libunwind/src/cet_unwind.h+1-1
...@@ -36,6 +36,6 @@...@@ -36,6 +36,6 @@
36#endif36#endif
3737
38extern void *__libunwind_cet_get_registers(unw_cursor_t *);38extern void *__libunwind_cet_get_registers(unw_cursor_t *);
39extern void *__libunwind_cet_get_jump_target();39extern void *__libunwind_cet_get_jump_target(void);
4040
41#endif41#endif
lib/libunwind/src/config.h+9-6
...@@ -43,6 +43,9 @@...@@ -43,6 +43,9 @@
43 // For ARM EHABI, Bionic didn't implement dl_iterate_phdr until API 21. After43 // For ARM EHABI, Bionic didn't implement dl_iterate_phdr until API 21. After
44 // API 21, dl_iterate_phdr exists, but dl_unwind_find_exidx is much faster.44 // API 21, dl_iterate_phdr exists, but dl_unwind_find_exidx is much faster.
45 #define _LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX 145 #define _LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX 1
46#elif defined(_AIX)
47// The traceback table at the end of each function is used for unwinding.
48#define _LIBUNWIND_SUPPORT_TBTAB_UNWIND 1
46#else49#else
47 // Assume an ELF system with a dl_iterate_phdr function.50 // Assume an ELF system with a dl_iterate_phdr function.
48 #define _LIBUNWIND_USE_DL_ITERATE_PHDR 151 #define _LIBUNWIND_USE_DL_ITERATE_PHDR 1
...@@ -57,7 +60,7 @@...@@ -57,7 +60,7 @@
57 #define _LIBUNWIND_EXPORT60 #define _LIBUNWIND_EXPORT
58 #define _LIBUNWIND_HIDDEN61 #define _LIBUNWIND_HIDDEN
59#else62#else
60 #if !defined(__ELF__) && !defined(__MACH__)63 #if !defined(__ELF__) && !defined(__MACH__) && !defined(_AIX)
61 #define _LIBUNWIND_EXPORT __declspec(dllexport)64 #define _LIBUNWIND_EXPORT __declspec(dllexport)
62 #define _LIBUNWIND_HIDDEN65 #define _LIBUNWIND_HIDDEN
63 #else66 #else
...@@ -80,7 +83,7 @@...@@ -80,7 +83,7 @@
80 __asm__(".globl " SYMBOL_NAME(aliasname)); \83 __asm__(".globl " SYMBOL_NAME(aliasname)); \
81 __asm__(SYMBOL_NAME(aliasname) " = " SYMBOL_NAME(name)); \84 __asm__(SYMBOL_NAME(aliasname) " = " SYMBOL_NAME(name)); \
82 _LIBUNWIND_ALIAS_VISIBILITY(SYMBOL_NAME(aliasname))85 _LIBUNWIND_ALIAS_VISIBILITY(SYMBOL_NAME(aliasname))
83#elif defined(__ELF__)86#elif defined(__ELF__) || defined(_AIX)
84#define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \87#define _LIBUNWIND_WEAK_ALIAS(name, aliasname) \
85 extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \88 extern "C" _LIBUNWIND_EXPORT __typeof(name) aliasname \
86 __attribute__((weak, alias(#name)));89 __attribute__((weak, alias(#name)));
...@@ -112,7 +115,7 @@...@@ -112,7 +115,7 @@
112#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || \115#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || \
113 (!defined(__APPLE__) && defined(__arm__)) || defined(__aarch64__) || \116 (!defined(__APPLE__) && defined(__arm__)) || defined(__aarch64__) || \
114 defined(__mips__) || defined(__riscv) || defined(__hexagon__) || \117 defined(__mips__) || defined(__riscv) || defined(__hexagon__) || \
115 defined(__sparc__)118 defined(__sparc__) || defined(__s390x__)
116#if !defined(_LIBUNWIND_BUILD_SJLJ_APIS)119#if !defined(_LIBUNWIND_BUILD_SJLJ_APIS)
117#define _LIBUNWIND_BUILD_ZERO_COST_APIS120#define _LIBUNWIND_BUILD_ZERO_COST_APIS
118#endif121#endif
...@@ -188,9 +191,9 @@...@@ -188,9 +191,9 @@
188 #ifdef __cplusplus191 #ifdef __cplusplus
189 extern "C" {192 extern "C" {
190 #endif193 #endif
191 extern bool logAPIs();194 extern bool logAPIs(void);
192 extern bool logUnwinding();195 extern bool logUnwinding(void);
193 extern bool logDWARF();196 extern bool logDWARF(void);
194 #ifdef __cplusplus197 #ifdef __cplusplus
195 }198 }
196 #endif199 #endif
lib/libunwind/src/libunwind.cpp+12
...@@ -75,6 +75,8 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor,...@@ -75,6 +75,8 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor,
75# define REGISTER_KIND Registers_riscv75# define REGISTER_KIND Registers_riscv
76#elif defined(__ve__)76#elif defined(__ve__)
77# define REGISTER_KIND Registers_ve77# define REGISTER_KIND Registers_ve
78#elif defined(__s390x__)
79# define REGISTER_KIND Registers_s390x
78#else80#else
79# error Architecture not supported81# error Architecture not supported
80#endif82#endif
...@@ -247,6 +249,16 @@ _LIBUNWIND_HIDDEN int __unw_is_signal_frame(unw_cursor_t *cursor) {...@@ -247,6 +249,16 @@ _LIBUNWIND_HIDDEN int __unw_is_signal_frame(unw_cursor_t *cursor) {
247}249}
248_LIBUNWIND_WEAK_ALIAS(__unw_is_signal_frame, unw_is_signal_frame)250_LIBUNWIND_WEAK_ALIAS(__unw_is_signal_frame, unw_is_signal_frame)
249251
252#ifdef _AIX
253_LIBUNWIND_EXPORT uintptr_t __unw_get_data_rel_base(unw_cursor_t *cursor) {
254 _LIBUNWIND_TRACE_API("unw_get_data_rel_base(cursor=%p)",
255 static_cast<void *>(cursor));
256 AbstractUnwindCursor *co = reinterpret_cast<AbstractUnwindCursor *>(cursor);
257 return co->getDataRelBase();
258}
259_LIBUNWIND_WEAK_ALIAS(__unw_get_data_rel_base, unw_get_data_rel_base)
260#endif
261
250#ifdef __arm__262#ifdef __arm__
251// Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD263// Save VFP registers d0-d15 using FSTMIADX instead of FSTMIADD
252_LIBUNWIND_HIDDEN void __unw_save_vfp_as_X(unw_cursor_t *cursor) {264_LIBUNWIND_HIDDEN void __unw_save_vfp_as_X(unw_cursor_t *cursor) {
lib/libunwind/src/libunwind_ext.h+4
...@@ -43,6 +43,10 @@ extern int __unw_is_fpreg(unw_cursor_t *, unw_regnum_t);...@@ -43,6 +43,10 @@ extern int __unw_is_fpreg(unw_cursor_t *, unw_regnum_t);
43extern int __unw_is_signal_frame(unw_cursor_t *);43extern int __unw_is_signal_frame(unw_cursor_t *);
44extern int __unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *);44extern int __unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *);
4545
46#if defined(_AIX)
47extern uintptr_t __unw_get_data_rel_base(unw_cursor_t *);
48#endif
49
46// SPI50// SPI
47extern void __unw_iterate_dwarf_unwind_cache(void (*func)(51extern void __unw_iterate_dwarf_unwind_cache(void (*func)(
48 unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh));52 unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh));
src/libunwind.zig+13-11
...@@ -33,17 +33,6 @@ pub fn buildStaticLib(comp: *Compilation) !void {...@@ -33,17 +33,6 @@ pub fn buildStaticLib(comp: *Compilation) !void {
33 .directory = null, // Put it in the cache directory.33 .directory = null, // Put it in the cache directory.
34 .basename = basename,34 .basename = basename,
35 };35 };
36 const unwind_src_list = [_][]const u8{
37 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "libunwind.cpp",
38 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-EHABI.cpp",
39 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-seh.cpp",
40 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindLevel1.c",
41 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindLevel1-gcc-ext.c",
42 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-sjlj.c",
43 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersRestore.S",
44 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersSave.S",
45 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "gcc_personality_v0.c",
46 };
47 var c_source_files: [unwind_src_list.len]Compilation.CSourceFile = undefined;36 var c_source_files: [unwind_src_list.len]Compilation.CSourceFile = undefined;
48 for (unwind_src_list) |unwind_src, i| {37 for (unwind_src_list) |unwind_src, i| {
49 var cflags = std.ArrayList([]const u8).init(arena);38 var cflags = std.ArrayList([]const u8).init(arena);
...@@ -150,3 +139,16 @@ pub fn buildStaticLib(comp: *Compilation) !void {...@@ -150,3 +139,16 @@ pub fn buildStaticLib(comp: *Compilation) !void {
150 .lock = sub_compilation.bin_file.toOwnedLock(),139 .lock = sub_compilation.bin_file.toOwnedLock(),
151 };140 };
152}141}
142
143const unwind_src_list = [_][]const u8{
144 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "libunwind.cpp",
145 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-EHABI.cpp",
146 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-seh.cpp",
147 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindLevel1.c",
148 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindLevel1-gcc-ext.c",
149 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-sjlj.c",
150 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersRestore.S",
151 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersSave.S",
152 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind_AIXExtras.cpp",
153 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "gcc_personality_v0.c",
154};