| author | |
| committer | |
| log | 2f635c3ce9be74f9e9ffb71324f7ba51bd2987f4 |
| tree | f04b0f4fb7a0e5ce0e36829bfd9aaa032447ac2a |
| parent | c0d9578a84c95f66f34729f6c8842a98a995f223 |
release/15.x commit 134fd359a5d884f16662a9edd22ab24feeb1498c21 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__ |
| 11 | 11 | ||
| 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_EHABI | 16 | #define _LIBUNWIND_ARM_EHABI |
| 15 | #endif | 17 | #endif |
| 16 | 18 | ||
| ... | @@ -27,6 +29,7 @@ | ... | @@ -27,6 +29,7 @@ |
| 27 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON 34 | 29 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON 34 |
| 28 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 64 | 30 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 64 |
| 29 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE 143 | 31 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE 143 |
| 32 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X 83 | ||
| 30 | 33 | ||
| 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 67 | 161 | # define _LIBUNWIND_CONTEXT_SIZE 67 |
| 159 | # define _LIBUNWIND_CURSOR_SIZE 79 | 162 | # define _LIBUNWIND_CURSOR_SIZE 79 |
| 160 | # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE | 163 | # 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 | # else | 169 | # else |
| 162 | # error "Unsupported architecture." | 170 | # error "Unsupported architecture." |
| 163 | # endif | 171 | # endif |
| ... | @@ -176,6 +184,7 @@ | ... | @@ -176,6 +184,7 @@ |
| 176 | # define _LIBUNWIND_TARGET_HEXAGON 1 | 184 | # define _LIBUNWIND_TARGET_HEXAGON 1 |
| 177 | # define _LIBUNWIND_TARGET_RISCV 1 | 185 | # define _LIBUNWIND_TARGET_RISCV 1 |
| 178 | # define _LIBUNWIND_TARGET_VE 1 | 186 | # define _LIBUNWIND_TARGET_VE 1 |
| 187 | # define _LIBUNWIND_TARGET_S390X 1 | ||
| 179 | # define _LIBUNWIND_CONTEXT_SIZE 167 | 188 | # define _LIBUNWIND_CONTEXT_SIZE 167 |
| 180 | # define _LIBUNWIND_CURSOR_SIZE 179 | 189 | # define _LIBUNWIND_CURSOR_SIZE 179 |
| 181 | # define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287 | 190 | # 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; |
| 81 | 81 | ||
| 82 | typedef int unw_regnum_t; | 82 | typedef int unw_regnum_t; |
| 83 | typedef uintptr_t unw_word_t; | 83 | typedef uintptr_t unw_word_t; |
| 84 | #if defined(__arm__) && !defined(__ARM_DWARF_EH__) | 84 | #if defined(__arm__) && !defined(__ARM_DWARF_EH__) && !defined(__SEH__) |
| 85 | typedef uint64_t unw_fpreg_t; | 85 | typedef uint64_t unw_fpreg_t; |
| 86 | #else | 86 | #else |
| 87 | typedef double unw_fpreg_t; | 87 | typedef 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; |
| 120 | extern void unw_save_vfp_as_X(unw_cursor_t *) LIBUNWIND_AVAIL; | 120 | extern void unw_save_vfp_as_X(unw_cursor_t *) LIBUNWIND_AVAIL; |
| 121 | #endif | 121 | #endif |
| 122 | 122 | ||
| 123 | #ifdef _AIX | ||
| 124 | extern uintptr_t unw_get_data_rel_base(unw_cursor_t *) LIBUNWIND_AVAIL; | ||
| 125 | #endif | ||
| 123 | 126 | ||
| 124 | extern const char *unw_regname(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL; | 127 | extern const char *unw_regname(unw_cursor_t *, unw_regnum_t) LIBUNWIND_AVAIL; |
| 125 | extern int unw_get_proc_info(unw_cursor_t *, unw_proc_info_t *) LIBUNWIND_AVAIL; | 128 | extern 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 | }; |
| 1176 | 1179 | ||
| 1180 | // s390x register numbers | ||
| 1181 | enum { | ||
| 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 | #endif | 1222 | #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 *); |
| 160 | extern void *_Unwind_FindEnclosingFunction(void *pc); | 160 | extern void *_Unwind_FindEnclosingFunction(void *pc); |
| 161 | 161 | ||
| 162 | // Mac OS X does not support text-rel and data-rel addressing so these functions | 162 | // Mac OS X does not support text-rel and data-rel addressing so these functions |
| 163 | // are unimplemented | 163 | // are unimplemented. |
| 164 | extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context) | 164 | extern uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context) |
| 165 | LIBUNWIND_UNAVAIL; | 165 | LIBUNWIND_UNAVAIL; |
| 166 | extern uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context) | 166 | extern 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" |
| 25 | 25 | ||
| 26 | #ifndef _LIBUNWIND_USE_DLADDR | 26 | #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 1 | 28 | #define _LIBUNWIND_USE_DLADDR 1 |
| 29 | #else | 29 | #else |
| 30 | #define _LIBUNWIND_USE_DLADDR 0 | 30 | #define _LIBUNWIND_USE_DLADDR 0 |
| ... | @@ -45,6 +45,13 @@ struct EHABIIndexEntry { | ... | @@ -45,6 +45,13 @@ struct EHABIIndexEntry { |
| 45 | }; | 45 | }; |
| 46 | #endif | 46 | #endif |
| 47 | 47 | ||
| 48 | #if defined(_AIX) | ||
| 49 | namespace libunwind { | ||
| 50 | char *getFuncNameFromTBTable(uintptr_t pc, uint16_t &NameLen, | ||
| 51 | unw_word_t *offset); | ||
| 52 | } | ||
| 53 | #endif | ||
| 54 | |||
| 48 | #ifdef __APPLE__ | 55 | #ifdef __APPLE__ |
| 49 | 56 | ||
| 50 | struct dyld_unwind_sections | 57 | 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 | } |
| 549 | 557 | ||
| ... | @@ -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 | } |
| 598 | 611 | ||
| 599 | |||
| 600 | inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { | 612 | inline 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 | #else | 638 | #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 | }; |
| 76 | 80 | ||
| 77 | template <typename R> | 81 | template <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) | ||
| 174 | template <typename A, typename R> | ||
| 175 | bool 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 | ||
| 169 | 188 | ||
| 170 | template <typename A, typename R> | 189 | template <typename A, typename R> |
| 171 | int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, | 190 | 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,9 +213,10 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, |
| 194 | newRegisters.setSP(cfa); | 213 | newRegisters.setSP(cfa); |
| 195 | 214 | ||
| 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 assembles | 255 | // 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 | } |
| 63 | 64 |
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 | }; |
| 43 | 44 | ||
| 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; } |
| 74 | 77 | ||
| 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; } |
| 290 | 295 | ||
| 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; } |
| 607 | 614 | ||
| 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; } | ||
| 612 | 621 | ||
| 613 | private: | 622 | private: |
| 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; } |
| 1173 | 1184 | ||
| 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; } | ||
| 1178 | 1191 | ||
| 1179 | private: | 1192 | private: |
| 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; } |
| 1818 | 1833 | ||
| 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; } |
| 2108 | 2125 | ||
| 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; } |
| 2608 | 2627 | ||
| 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; } |
| 2805 | 2826 | ||
| 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; } |
| 3132 | 3155 | ||
| 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; } |
| 3427 | 3452 | ||
| 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; } |
| 3796 | 3823 | ||
| 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; } |
| 4009 | 4038 | ||
| 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; } |
| 4295 | 4326 | ||
| 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_VE | 4744 | #endif // _LIBUNWIND_TARGET_VE |
| 4714 | 4745 | ||
| 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. | ||
| 4749 | class _LIBUNWIND_HIDDEN Registers_s390x { | ||
| 4750 | public: | ||
| 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 | |||
| 4775 | private: | ||
| 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 | |||
| 4786 | inline 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 | |||
| 4793 | inline Registers_s390x::Registers_s390x() { | ||
| 4794 | memset(&_registers, 0, sizeof(_registers)); | ||
| 4795 | } | ||
| 4796 | |||
| 4797 | inline 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 | |||
| 4812 | inline 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 | |||
| 4828 | inline 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 | |||
| 4849 | inline bool Registers_s390x::validFloatRegister(int regNum) const { | ||
| 4850 | return regNum >= UNW_S390X_F0 && regNum <= UNW_S390X_F15; | ||
| 4851 | } | ||
| 4852 | |||
| 4853 | inline 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 | |||
| 4892 | inline 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 | |||
| 4947 | inline bool Registers_s390x::validVectorRegister(int /*regNum*/) const { | ||
| 4948 | return false; | ||
| 4949 | } | ||
| 4950 | |||
| 4951 | inline v128 Registers_s390x::getVectorRegister(int /*regNum*/) const { | ||
| 4952 | _LIBUNWIND_ABORT("s390x vector support not implemented"); | ||
| 4953 | } | ||
| 4954 | |||
| 4955 | inline void Registers_s390x::setVectorRegister(int /*regNum*/, v128 /*value*/) { | ||
| 4956 | _LIBUNWIND_ABORT("s390x vector support not implemented"); | ||
| 4957 | } | ||
| 4958 | |||
| 4959 | inline 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 libunwind | 5035 | } // namespace libunwind |
| 4716 | 5036 | ||
| 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 | #endif | 440 | #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) { |
| 1193 | extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code | 1193 | extern "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; |
| 109 | 109 | ||
| 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%" PRIx64 | 258 | "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 | #endif | 26 | #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 | ||
| 27 | 40 | ||
| 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 and | 42 | // 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 | #endif | 465 | #endif |
| 453 | 466 | ||
| 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 | #endif | 938 | #endif |
| 912 | 939 | ||
| 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 | #endif | 946 | #endif |
| 947 | |||
| 916 | // libunwind does not and should not depend on C++ library which means that we | 948 | // 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 | #endif | 970 | #endif |
| 939 | 971 | ||
| 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 | #endif | 1243 | #endif |
| 1206 | 1244 | ||
| 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) |
| 1208 | 1252 | ||
| 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) |
| 1222 | 1266 | ||
| 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) | ||
| 1223 | 1277 | ||
| 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 | #endif | 1285 | #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 | #endif | 1347 | #endif |
| 1294 | 1348 | ||
| 1349 | #ifdef _AIX | ||
| 1350 | template <typename A, typename R> | ||
| 1351 | uintptr_t UnwindCursor<A, R>::getDataRelBase() { | ||
| 1352 | return reinterpret_cast<uintptr_t>(_info.extra); | ||
| 1353 | } | ||
| 1354 | #endif | ||
| 1355 | |||
| 1295 | template <typename A, typename R> | 1356 | template <typename A, typename R> |
| 1296 | const char *UnwindCursor<A, R>::getRegisterName(int regNum) { | 1357 | const 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 | #endif | 1976 | #endif |
| 1920 | setLastPC(pc); | 1977 | setLastPC(pc); |
| 1921 | return true; | 1978 | return true; |
| 1922 | } | 1979 | } |
| 1923 | #endif | 1980 | #endif |
| 1924 | 1981 | ||
| 1982 | #if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND) | ||
| 1983 | // Masks for traceback table field xtbtable. | ||
| 1984 | enum 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 | |||
| 1990 | enum frameType : unw_word_t { | ||
| 1991 | frameWithXLEHStateTable = 0, | ||
| 1992 | frameWithEHInfo = 1 | ||
| 1993 | }; | ||
| 1994 | |||
| 1995 | extern "C" { | ||
| 1996 | typedef _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 | |||
| 2003 | static __xlcxx_personality_v0_t *xlcPersonalityV0; | ||
| 2004 | static RWMutex xlcPersonalityV0InitLock; | ||
| 2005 | |||
| 2006 | template <typename A, typename R> | ||
| 2007 | bool 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. | ||
| 2254 | template <typename A, typename R> | ||
| 2255 | int 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) | ||
| 1925 | 2483 | ||
| 1926 | template <typename A, typename R> | 2484 | template <typename A, typename R> |
| 1927 | void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { | 2485 | void 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 | #endif | 2488 | #endif |
| 1931 | 2489 | ||
| ... | @@ -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 return | 2506 | // 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 | ||
| 1952 | 2517 | ||
| 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 | #endif | 2548 | #endif |
| 1984 | 2549 | ||
| 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) |
| 2029 | 2600 | ||
| 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 | #endif | 2604 | #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 | } |
| 2038 | 2609 | ||
| 2039 | #if defined(_LIBUNWIND_TARGET_LINUX) && defined(_LIBUNWIND_TARGET_AARCH64) | 2610 | #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \ |
| 2611 | defined(_LIBUNWIND_TARGET_AARCH64) | ||
| 2040 | template <typename A, typename R> | 2612 | template <typename A, typename R> |
| 2041 | bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) { | 2613 | bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) { |
| 2042 | // Look for the sigreturn trampoline. The trampoline's body is two | 2614 | // 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.S | 2628 | // [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 #0x0 | 2642 | // 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 | } |
| 2067 | 2653 | ||
| 2068 | template <typename A, typename R> | 2654 | template <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) | ||
| 2690 | template <typename A, typename R> | ||
| 2691 | bool 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 | |||
| 2715 | template <typename A, typename R> | ||
| 2716 | int 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) | ||
| 2100 | 2793 | ||
| 2101 | template <typename A, typename R> | 2794 | template <typename A, typename R> |
| 2102 | int UnwindCursor<A, R>::step() { | 2795 | int UnwindCursor<A, R>::step() { |
| ... | @@ -2106,7 +2799,7 @@ int UnwindCursor<A, R>::step() { | ... | @@ -2106,7 +2799,7 @@ int UnwindCursor<A, R>::step() { |
| 2106 | 2799 | ||
| 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 | } else | 2805 | } 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_t | 60 | _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 | } |
| 66 | 70 | ||
| 67 | |||
| 68 | /// Called by personality handler during phase 2 to get base address for text | 71 | /// Called by personality handler during phase 2 to get base address for text |
| 69 | /// relative encodings. | 72 | /// relative encodings. |
| 70 | _LIBUNWIND_EXPORT uintptr_t | 73 | _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 using | 44 | // 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 | } |
| 490 | 496 |
lib/libunwind/src/UnwindRegistersRestore.S+138-61| ... | @@ -8,7 +8,11 @@ | ... | @@ -8,7 +8,11 @@ |
| 8 | 8 | ||
| 9 | #include "assembly.h" | 9 | #include "assembly.h" |
| 10 | 10 | ||
| 11 | #if defined(_AIX) | ||
| 12 | .toc | ||
| 13 | #else | ||
| 11 | .text | 14 | .text |
| 15 | #endif | ||
| 12 | 16 | ||
| 13 | #if !defined(__USING_SJLJ_EXCEPTIONS__) | 17 | #if !defined(__USING_SJLJ_EXCEPTIONS__) |
| 14 | 18 | ||
| ... | @@ -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) |
| 224 | 228 | ||
| 225 | // use VRSAVE to conditionally restore the remaining VS regs, | 229 | #define PPC64_CLVS_RESTORE(n) \ |
| 226 | // that are where the V regs are mapped | 230 | addi 4, 3, PPC64_OFFS_FP + n * 16 ;\ |
| 231 | lxvd2x n, 0, 4 | ||
| 227 | 232 | ||
| 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 VRsave | 236 | ld 5, PPC64_OFFS_VRSAVE(3) // test VRsave |
| 229 | cmpwi 5, 0 | 237 | cmpwi 5, 0 |
| 230 | beq Lnovec | 238 | beq Lnovec |
| 231 | 239 | ||
| 232 | // conditionally load VS | 240 | // 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) ;\ |
| 237 | Ldone##n: | 245 | Ldone##n: |
| 238 | 246 | ||
| 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)) ;\ |
| 241 | PPC64_CLVS_BOTTOM(n) | 249 | beq Ldone##n ;\ |
| 250 | PPC64_CLVS_RESTORE(n) ;\ | ||
| 251 | Ldone##n: | ||
| 252 | |||
| 253 | #else | ||
| 242 | 254 | ||
| 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) |
| 245 | PPC64_CLVS_BOTTOM(n) | 257 | |
| 258 | #endif // !defined(_AIX) | ||
| 246 | 259 | ||
| 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) |
| 319 | 332 | ||
| 320 | #if defined(__ALTIVEC__) | 333 | #if defined(__ALTIVEC__) |
| 321 | // restore vector registers if any are in use | 334 | |
| 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 VRsave | 345 | ld 5, PPC64_OFFS_VRSAVE(3) // test VRsave |
| 323 | cmpwi 5, 0 | 346 | cmpwi 5, 0 |
| 324 | beq Lnovec | 347 | beq Lnovec |
| 325 | 348 | ||
| 326 | subi 4, 1, 16 | 349 | #define PPC64_CLV_UNALIGNEDl(n) \ |
| 327 | // r4 is now a 16-byte aligned pointer into the red zone | 350 | andis. 0, 5, (1 PPC_LEFT_SHIFT(15-n)) ;\ |
| 328 | // the _vectorScalarRegisters may not be 16-byte aligned | 351 | beq Ldone##n ;\ |
| 329 | // so copy via red zone temp buffer | 352 | PPC64_CLV_UNALIGNED_RESTORE(n) ;\ |
| 353 | Ldone ## n: | ||
| 330 | 354 | ||
| 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 ;\ | ||
| 338 | Ldone ## n: | 359 | Ldone ## n: |
| 339 | 360 | ||
| 340 | #define PPC64_CLV_UNALIGNEDl(n) \ | 361 | #else |
| 341 | andis. 0, 5, (1 PPC_LEFT_SHIFT(15-n)) ;\ | 362 | |
| 342 | PPC64_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) | ||
| 343 | 367 | ||
| 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 |
| 346 | PPC64_CLV_UNALIGNED_BOTTOM(n) | 370 | // the _vectorScalarRegisters may not be 16-byte aligned |
| 371 | // so copy via red zone temp buffer | ||
| 347 | 372 | ||
| 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 0 | 413 | mtctr 0 |
| 389 | 414 | ||
| 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 | bctr | 432 | bctr |
| 396 | 433 | ||
| 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 | #endif | 512 | #endif |
| 476 | 513 | ||
| 477 | #if defined(__ALTIVEC__) | 514 | #if defined(__ALTIVEC__) |
| 478 | // restore vector registers if any are in use | 515 | |
| 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 VRsave | 530 | lwz 5, 156(3) // test VRsave |
| 480 | cmpwi 5, 0 | 531 | cmpwi 5, 0 |
| 481 | beq Lnovec | 532 | beq Lnovec |
| 482 | 533 | ||
| 483 | subi 4, 1, 16 | 534 | #define LOAD_VECTOR_UNALIGNEDl(_index) \ |
| 484 | rlwinm 4, 4, 0, 0, 27 // mask low 4-bits | 535 | andis. 0, 5, (1 PPC_LEFT_SHIFT(15-_index)) SEPARATOR \ |
| 485 | // r4 is now a 16-byte aligned pointer into the red zone | 536 | beq Ldone ## _index SEPARATOR \ |
| 486 | // the _vectorRegisters may not be 16-byte aligned so copy via red zone temp buffer | 537 | 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: |
| 502 | 539 | ||
| 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: |
| 516 | 545 | ||
| 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 | ||
| 517 | 557 | ||
| 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) |
| 1212 | 1252 | ||
| 1213 | ret // jump to ra | 1253 | ret // jump to ra |
| 1214 | 1254 | ||
| 1255 | #elif defined(__s390x__) | ||
| 1256 | |||
| 1257 | DEFINE_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 | #endif | 1292 | #endif |
| 1216 | 1293 | ||
| 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 @@ |
| 8 | 8 | ||
| 9 | #include "assembly.h" | 9 | #include "assembly.h" |
| 10 | 10 | ||
| 11 | #if defined(_AIX) | ||
| 12 | .toc | ||
| 13 | #else | ||
| 11 | .text | 14 | .text |
| 15 | #endif | ||
| 12 | 16 | ||
| 13 | #if !defined(__USING_SJLJ_EXCEPTIONS__) | 17 | #if !defined(__USING_SJLJ_EXCEPTIONS__) |
| 14 | 18 | ||
| ... | @@ -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 r3 | 339 | // thread_state pointer is in r3 |
| 336 | // | 340 | // |
| 341 | #if defined(_AIX) | ||
| 342 | DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(__unw_getcontext, unw_getcontext) | ||
| 343 | #else | ||
| 337 | DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) | 344 | DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 338 | 345 | #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 r3 | 575 | // thread_state pointer is in r3 |
| 569 | // | 576 | // |
| 577 | #if defined(_AIX) | ||
| 578 | DEFINE_LIBUNWIND_FUNCTION_AND_WEAK_ALIAS(__unw_getcontext, unw_getcontext) | ||
| 579 | #else | ||
| 570 | DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) | 580 | DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 581 | #endif | ||
| 571 | stw 0, 8(3) | 582 | stw 0, 8(3) |
| 572 | mflr 0 | 583 | mflr 0 |
| 573 | stw 0, 0(3) // store lr as ssr0 | 584 | 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) |
| 1168 | 1179 | ||
| 1169 | li a0, 0 // return UNW_ESUCCESS | 1180 | li a0, 0 // return UNW_ESUCCESS |
| 1170 | ret // jump to ra | 1181 | 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 | // | ||
| 1191 | DEFINE_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 | #endif | 1225 | #endif |
| 1172 | 1226 | ||
| 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 | |||
| 17 | namespace libunwind { | ||
| 18 | // getFuncNameFromTBTable | ||
| 19 | // Get the function name from its traceback table. | ||
| 20 | char *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 | #endif | 68 | #endif |
| 69 | 69 | ||
| 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 SEPARATOR | 72 | #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 @@ |
| 203 | 204 | ||
| 204 | #elif defined(__sparc__) | 205 | #elif defined(__sparc__) |
| 205 | 206 | ||
| 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 \ | ||
| 225 | aliasname: \ | ||
| 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 | #else | 238 | #else |
| 207 | 239 | ||
| 208 | #error Unsupported target | 240 | #error Unsupported target |
| 209 | 241 | ||
| 210 | #endif | 242 | #endif |
| 211 | 243 | ||
| 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_BTI | 265 | AARCH64_BTI |
| 266 | #endif | ||
| 220 | 267 | ||
| 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 | #endif | 36 | #endif |
| 37 | 37 | ||
| 38 | extern void *__libunwind_cet_get_registers(unw_cursor_t *); | 38 | extern void *__libunwind_cet_get_registers(unw_cursor_t *); |
| 39 | extern void *__libunwind_cet_get_jump_target(); | 39 | extern void *__libunwind_cet_get_jump_target(void); |
| 40 | 40 | ||
| 41 | #endif | 41 | #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. After | 43 | // 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 1 | 45 | #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 | #else | 49 | #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 1 | 51 | #define _LIBUNWIND_USE_DL_ITERATE_PHDR 1 |
| ... | @@ -57,7 +60,7 @@ | ... | @@ -57,7 +60,7 @@ |
| 57 | #define _LIBUNWIND_EXPORT | 60 | #define _LIBUNWIND_EXPORT |
| 58 | #define _LIBUNWIND_HIDDEN | 61 | #define _LIBUNWIND_HIDDEN |
| 59 | #else | 62 | #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_HIDDEN | 65 | #define _LIBUNWIND_HIDDEN |
| 63 | #else | 66 | #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_APIS | 120 | #define _LIBUNWIND_BUILD_ZERO_COST_APIS |
| 118 | #endif | 121 | #endif |
| ... | @@ -188,9 +191,9 @@ | ... | @@ -188,9 +191,9 @@ |
| 188 | #ifdef __cplusplus | 191 | #ifdef __cplusplus |
| 189 | extern "C" { | 192 | extern "C" { |
| 190 | #endif | 193 | #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 __cplusplus | 197 | #ifdef __cplusplus |
| 195 | } | 198 | } |
| 196 | #endif | 199 | #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_riscv | 75 | # define REGISTER_KIND Registers_riscv |
| 76 | #elif defined(__ve__) | 76 | #elif defined(__ve__) |
| 77 | # define REGISTER_KIND Registers_ve | 77 | # define REGISTER_KIND Registers_ve |
| 78 | #elif defined(__s390x__) | ||
| 79 | # define REGISTER_KIND Registers_s390x | ||
| 78 | #else | 80 | #else |
| 79 | # error Architecture not supported | 81 | # error Architecture not supported |
| 80 | #endif | 82 | #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) |
| 249 | 251 | ||
| 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 FSTMIADD | 263 | // 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); |
| 43 | extern int __unw_is_signal_frame(unw_cursor_t *); | 43 | extern int __unw_is_signal_frame(unw_cursor_t *); |
| 44 | extern int __unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *); | 44 | extern int __unw_get_proc_name(unw_cursor_t *, char *, size_t, unw_word_t *); |
| 45 | 45 | ||
| 46 | #if defined(_AIX) | ||
| 47 | extern uintptr_t __unw_get_data_rel_base(unw_cursor_t *); | ||
| 48 | #endif | ||
| 49 | |||
| 46 | // SPI | 50 | // SPI |
| 47 | extern void __unw_iterate_dwarf_unwind_cache(void (*func)( | 51 | extern 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 | |||
| 143 | const 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 | }; |