| author | |
| committer | |
| log | 1e7083d09cc77663560b4c971421bff06f2c6c12 |
| tree | 25c94010aaf26a67b0a85989ae5c4b53eb8f7f5d |
| parent | e41b58ddc3e20144d30bba8c1387df5aa5fd6c5e |
21 files changed, 728 insertions(+), 396 deletions(-)
lib/libcxx/include/__config-2| ... | ... | @@ -10,8 +10,6 @@ |
| 10 | 10 | #ifndef _LIBCPP___CONFIG |
| 11 | 11 | #define _LIBCPP___CONFIG |
| 12 | 12 | |
| 13 | #include <__config_site> | |
| 14 | ||
| 15 | 13 | #if defined(_MSC_VER) && !defined(__clang__) |
| 16 | 14 | # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
| 17 | 15 | # define _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER |
lib/libunwind/include/__libunwind_config.h+12| ... | ... | @@ -30,6 +30,7 @@ |
| 30 | 30 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 64 |
| 31 | 31 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_VE 143 |
| 32 | 32 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X 83 |
| 33 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH 64 | |
| 33 | 34 | |
| 34 | 35 | #if defined(_LIBUNWIND_IS_NATIVE_ONLY) |
| 35 | 36 | # if defined(__linux__) |
| ... | ... | @@ -166,6 +167,16 @@ |
| 166 | 167 | # define _LIBUNWIND_CONTEXT_SIZE 34 |
| 167 | 168 | # define _LIBUNWIND_CURSOR_SIZE 46 |
| 168 | 169 | # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_S390X |
| 170 | #elif defined(__loongarch__) | |
| 171 | #define _LIBUNWIND_TARGET_LOONGARCH 1 | |
| 172 | #if __loongarch_grlen == 64 | |
| 173 | #define _LIBUNWIND_CONTEXT_SIZE 65 | |
| 174 | #define _LIBUNWIND_CURSOR_SIZE 77 | |
| 175 | #else | |
| 176 | #error "Unsupported LoongArch ABI" | |
| 177 | #endif | |
| 178 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER \ | |
| 179 | _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH | |
| 169 | 180 | # else |
| 170 | 181 | # error "Unsupported architecture." |
| 171 | 182 | # endif |
| ... | ... | @@ -185,6 +196,7 @@ |
| 185 | 196 | # define _LIBUNWIND_TARGET_RISCV 1 |
| 186 | 197 | # define _LIBUNWIND_TARGET_VE 1 |
| 187 | 198 | # define _LIBUNWIND_TARGET_S390X 1 |
| 199 | #define _LIBUNWIND_TARGET_LOONGARCH 1 | |
| 188 | 200 | # define _LIBUNWIND_CONTEXT_SIZE 167 |
| 189 | 201 | # define _LIBUNWIND_CURSOR_SIZE 179 |
| 190 | 202 | # define _LIBUNWIND_HIGHEST_DWARF_REGISTER 287 |
lib/libunwind/include/libunwind.h+78| ... | ... | @@ -1023,6 +1023,16 @@ enum { |
| 1023 | 1023 | UNW_RISCV_F29 = 61, |
| 1024 | 1024 | UNW_RISCV_F30 = 62, |
| 1025 | 1025 | UNW_RISCV_F31 = 63, |
| 1026 | // 65-95 -- Reserved for future standard extensions | |
| 1027 | // 96-127 -- v0-v31 (Vector registers) | |
| 1028 | // 128-3071 -- Reserved for future standard extensions | |
| 1029 | // 3072-4095 -- Reserved for custom extensions | |
| 1030 | // 4096-8191 -- CSRs | |
| 1031 | // | |
| 1032 | // VLENB CSR number: 0xC22 -- defined by section 3 of v-spec: | |
| 1033 | // https://github.com/riscv/riscv-v-spec/blob/master/v-spec.adoc#3-vector-extension-programmers-model | |
| 1034 | // VLENB DWARF number: 0x1000 + 0xC22 | |
| 1035 | UNW_RISCV_VLENB = 0x1C22, | |
| 1026 | 1036 | }; |
| 1027 | 1037 | |
| 1028 | 1038 | // VE register numbers |
| ... | ... | @@ -1219,4 +1229,72 @@ enum { |
| 1219 | 1229 | // 68-83 Vector Registers %v16-%v31 |
| 1220 | 1230 | }; |
| 1221 | 1231 | |
| 1232 | // LoongArch registers. | |
| 1233 | enum { | |
| 1234 | UNW_LOONGARCH_R0 = 0, | |
| 1235 | UNW_LOONGARCH_R1 = 1, | |
| 1236 | UNW_LOONGARCH_R2 = 2, | |
| 1237 | UNW_LOONGARCH_R3 = 3, | |
| 1238 | UNW_LOONGARCH_R4 = 4, | |
| 1239 | UNW_LOONGARCH_R5 = 5, | |
| 1240 | UNW_LOONGARCH_R6 = 6, | |
| 1241 | UNW_LOONGARCH_R7 = 7, | |
| 1242 | UNW_LOONGARCH_R8 = 8, | |
| 1243 | UNW_LOONGARCH_R9 = 9, | |
| 1244 | UNW_LOONGARCH_R10 = 10, | |
| 1245 | UNW_LOONGARCH_R11 = 11, | |
| 1246 | UNW_LOONGARCH_R12 = 12, | |
| 1247 | UNW_LOONGARCH_R13 = 13, | |
| 1248 | UNW_LOONGARCH_R14 = 14, | |
| 1249 | UNW_LOONGARCH_R15 = 15, | |
| 1250 | UNW_LOONGARCH_R16 = 16, | |
| 1251 | UNW_LOONGARCH_R17 = 17, | |
| 1252 | UNW_LOONGARCH_R18 = 18, | |
| 1253 | UNW_LOONGARCH_R19 = 19, | |
| 1254 | UNW_LOONGARCH_R20 = 20, | |
| 1255 | UNW_LOONGARCH_R21 = 21, | |
| 1256 | UNW_LOONGARCH_R22 = 22, | |
| 1257 | UNW_LOONGARCH_R23 = 23, | |
| 1258 | UNW_LOONGARCH_R24 = 24, | |
| 1259 | UNW_LOONGARCH_R25 = 25, | |
| 1260 | UNW_LOONGARCH_R26 = 26, | |
| 1261 | UNW_LOONGARCH_R27 = 27, | |
| 1262 | UNW_LOONGARCH_R28 = 28, | |
| 1263 | UNW_LOONGARCH_R29 = 29, | |
| 1264 | UNW_LOONGARCH_R30 = 30, | |
| 1265 | UNW_LOONGARCH_R31 = 31, | |
| 1266 | UNW_LOONGARCH_F0 = 32, | |
| 1267 | UNW_LOONGARCH_F1 = 33, | |
| 1268 | UNW_LOONGARCH_F2 = 34, | |
| 1269 | UNW_LOONGARCH_F3 = 35, | |
| 1270 | UNW_LOONGARCH_F4 = 36, | |
| 1271 | UNW_LOONGARCH_F5 = 37, | |
| 1272 | UNW_LOONGARCH_F6 = 38, | |
| 1273 | UNW_LOONGARCH_F7 = 39, | |
| 1274 | UNW_LOONGARCH_F8 = 40, | |
| 1275 | UNW_LOONGARCH_F9 = 41, | |
| 1276 | UNW_LOONGARCH_F10 = 42, | |
| 1277 | UNW_LOONGARCH_F11 = 43, | |
| 1278 | UNW_LOONGARCH_F12 = 44, | |
| 1279 | UNW_LOONGARCH_F13 = 45, | |
| 1280 | UNW_LOONGARCH_F14 = 46, | |
| 1281 | UNW_LOONGARCH_F15 = 47, | |
| 1282 | UNW_LOONGARCH_F16 = 48, | |
| 1283 | UNW_LOONGARCH_F17 = 49, | |
| 1284 | UNW_LOONGARCH_F18 = 50, | |
| 1285 | UNW_LOONGARCH_F19 = 51, | |
| 1286 | UNW_LOONGARCH_F20 = 52, | |
| 1287 | UNW_LOONGARCH_F21 = 53, | |
| 1288 | UNW_LOONGARCH_F22 = 54, | |
| 1289 | UNW_LOONGARCH_F23 = 55, | |
| 1290 | UNW_LOONGARCH_F24 = 56, | |
| 1291 | UNW_LOONGARCH_F25 = 57, | |
| 1292 | UNW_LOONGARCH_F26 = 58, | |
| 1293 | UNW_LOONGARCH_F27 = 59, | |
| 1294 | UNW_LOONGARCH_F28 = 60, | |
| 1295 | UNW_LOONGARCH_F29 = 61, | |
| 1296 | UNW_LOONGARCH_F30 = 62, | |
| 1297 | UNW_LOONGARCH_F31 = 63, | |
| 1298 | }; | |
| 1299 | ||
| 1222 | 1300 | #endif |
lib/libunwind/include/mach-o/compact_unwind_encoding.h+3-3| ... | ... | @@ -33,7 +33,7 @@ |
| 33 | 33 | |
| 34 | 34 | |
| 35 | 35 | // |
| 36 | // The compact unwind endoding is a 32-bit value which encoded in an | |
| 36 | // The compact unwind encoding is a 32-bit value which encoded in an | |
| 37 | 37 | // architecture specific way, which registers to restore from where, and how |
| 38 | 38 | // to unwind out of the function. |
| 39 | 39 | // |
| ... | ... | @@ -116,7 +116,7 @@ enum { |
| 116 | 116 | // on the stack immediately after the return address. The stack_size/4 is |
| 117 | 117 | // encoded in the UNWIND_X86_FRAMELESS_STACK_SIZE (max stack size is 1024). |
| 118 | 118 | // The number of registers saved is encoded in UNWIND_X86_FRAMELESS_STACK_REG_COUNT. |
| 119 | // UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION constains which registers were | |
| 119 | // UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION contains which registers were | |
| 120 | 120 | // saved and their order. |
| 121 | 121 | // UNWIND_X86_MODE_STACK_IND: |
| 122 | 122 | // A "frameless" (EBP not used as frame pointer) function large constant |
| ... | ... | @@ -250,7 +250,7 @@ enum { |
| 250 | 250 | // on the stack immediately after the return address. The stack_size/8 is |
| 251 | 251 | // encoded in the UNWIND_X86_64_FRAMELESS_STACK_SIZE (max stack size is 2048). |
| 252 | 252 | // The number of registers saved is encoded in UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT. |
| 253 | // UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION constains which registers were | |
| 253 | // UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION contains which registers were | |
| 254 | 254 | // saved and their order. |
| 255 | 255 | // UNWIND_X86_64_MODE_STACK_IND: |
| 256 | 256 | // A "frameless" (RBP not used as frame pointer) function large constant |
lib/libunwind/include/unwind.h+1-1| ... | ... | @@ -93,7 +93,7 @@ extern void _Unwind_SjLj_Unregister(_Unwind_FunctionContext_t fc); |
| 93 | 93 | #endif |
| 94 | 94 | |
| 95 | 95 | // |
| 96 | // The following are semi-suppoted extensions to the C++ ABI | |
| 96 | // The following are semi-supported extensions to the C++ ABI | |
| 97 | 97 | // |
| 98 | 98 | |
| 99 | 99 | // |
lib/libunwind/src/AddressSpace.hpp+53-25| ... | ... | @@ -246,7 +246,7 @@ inline uint64_t LocalAddressSpace::getULEB128(pint_t &addr, pint_t end) { |
| 246 | 246 | inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { |
| 247 | 247 | const uint8_t *p = (uint8_t *)addr; |
| 248 | 248 | const uint8_t *pend = (uint8_t *)end; |
| 249 | int64_t result = 0; | |
| 249 | uint64_t result = 0; | |
| 250 | 250 | int bit = 0; |
| 251 | 251 | uint8_t byte; |
| 252 | 252 | do { |
| ... | ... | @@ -260,7 +260,7 @@ inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { |
| 260 | 260 | if ((byte & 0x40) != 0 && bit < 64) |
| 261 | 261 | result |= (-1ULL) << bit; |
| 262 | 262 | addr = (pint_t) p; |
| 263 | return result; | |
| 263 | return (int64_t)result; | |
| 264 | 264 | } |
| 265 | 265 | |
| 266 | 266 | inline LocalAddressSpace::pint_t |
| ... | ... | @@ -373,28 +373,6 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, |
| 373 | 373 | typedef ElfW(Addr) Elf_Addr; |
| 374 | 374 | #endif |
| 375 | 375 | |
| 376 | static Elf_Addr calculateImageBase(struct dl_phdr_info *pinfo) { | |
| 377 | Elf_Addr image_base = pinfo->dlpi_addr; | |
| 378 | #if defined(__ANDROID__) && __ANDROID_API__ < 18 | |
| 379 | if (image_base == 0) { | |
| 380 | // Normally, an image base of 0 indicates a non-PIE executable. On | |
| 381 | // versions of Android prior to API 18, the dynamic linker reported a | |
| 382 | // dlpi_addr of 0 for PIE executables. Compute the true image base | |
| 383 | // using the PT_PHDR segment. | |
| 384 | // See https://github.com/android/ndk/issues/505. | |
| 385 | for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { | |
| 386 | const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; | |
| 387 | if (phdr->p_type == PT_PHDR) { | |
| 388 | image_base = reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) - | |
| 389 | phdr->p_vaddr; | |
| 390 | break; | |
| 391 | } | |
| 392 | } | |
| 393 | } | |
| 394 | #endif | |
| 395 | return image_base; | |
| 396 | } | |
| 397 | ||
| 398 | 376 | struct _LIBUNWIND_HIDDEN dl_iterate_cb_data { |
| 399 | 377 | LocalAddressSpace *addressSpace; |
| 400 | 378 | UnwindInfoSections *sects; |
| ... | ... | @@ -468,7 +446,7 @@ static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, |
| 468 | 446 | (void)pinfo_size; |
| 469 | 447 | #endif |
| 470 | 448 | |
| 471 | Elf_Addr image_base = calculateImageBase(pinfo); | |
| 449 | Elf_Addr image_base = pinfo->dlpi_addr; | |
| 472 | 450 | |
| 473 | 451 | // Most shared objects seen in this callback function likely don't contain the |
| 474 | 452 | // target address, so optimize for that. Scan for a matching PT_LOAD segment |
| ... | ... | @@ -601,6 +579,56 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, |
| 601 | 579 | if (info.arm_section && info.arm_section_length) |
| 602 | 580 | return true; |
| 603 | 581 | #elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) |
| 582 | // Use DLFO_STRUCT_HAS_EH_DBASE to determine the existence of | |
| 583 | // `_dl_find_object`. Use _LIBUNWIND_SUPPORT_DWARF_INDEX, because libunwind | |
| 584 | // support for _dl_find_object on other unwind formats is not implemented, | |
| 585 | // yet. | |
| 586 | #if defined(DLFO_STRUCT_HAS_EH_DBASE) & defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) | |
| 587 | // We expect `_dl_find_object` to return PT_GNU_EH_FRAME. | |
| 588 | #if DLFO_EH_SEGMENT_TYPE != PT_GNU_EH_FRAME | |
| 589 | #error _dl_find_object retrieves an unexpected section type | |
| 590 | #endif | |
| 591 | // We look-up `dl_find_object` dynamically at runtime to ensure backwards | |
| 592 | // compatibility with earlier version of glibc not yet providing it. On older | |
| 593 | // systems, we gracefully fallback to `dl_iterate_phdr`. Cache the pointer | |
| 594 | // so we only look it up once. Do manual lock to avoid _cxa_guard_acquire. | |
| 595 | static decltype(_dl_find_object) *dlFindObject; | |
| 596 | static bool dlFindObjectChecked = false; | |
| 597 | if (!dlFindObjectChecked) { | |
| 598 | dlFindObject = reinterpret_cast<decltype(_dl_find_object) *>( | |
| 599 | dlsym(RTLD_DEFAULT, "_dl_find_object")); | |
| 600 | dlFindObjectChecked = true; | |
| 601 | } | |
| 602 | // Try to find the unwind info using `dl_find_object` | |
| 603 | dl_find_object findResult; | |
| 604 | if (dlFindObject && dlFindObject((void *)targetAddr, &findResult) == 0) { | |
| 605 | if (findResult.dlfo_eh_frame == nullptr) { | |
| 606 | // Found an entry for `targetAddr`, but there is no unwind info. | |
| 607 | return false; | |
| 608 | } | |
| 609 | info.dso_base = reinterpret_cast<uintptr_t>(findResult.dlfo_map_start); | |
| 610 | info.text_segment_length = static_cast<size_t>( | |
| 611 | (char *)findResult.dlfo_map_end - (char *)findResult.dlfo_map_start); | |
| 612 | ||
| 613 | // Record the start of PT_GNU_EH_FRAME. | |
| 614 | info.dwarf_index_section = | |
| 615 | reinterpret_cast<uintptr_t>(findResult.dlfo_eh_frame); | |
| 616 | // `_dl_find_object` does not give us the size of PT_GNU_EH_FRAME. | |
| 617 | // Setting length to `SIZE_MAX` effectively disables all range checks. | |
| 618 | info.dwarf_index_section_length = SIZE_MAX; | |
| 619 | EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo; | |
| 620 | if (!EHHeaderParser<LocalAddressSpace>::decodeEHHdr( | |
| 621 | *this, info.dwarf_index_section, info.dwarf_index_section_length, | |
| 622 | hdrInfo)) { | |
| 623 | return false; | |
| 624 | } | |
| 625 | // Record the start of the FDE and use SIZE_MAX to indicate that we do | |
| 626 | // not know the end address. | |
| 627 | info.dwarf_section = hdrInfo.eh_frame_ptr; | |
| 628 | info.dwarf_section_length = SIZE_MAX; | |
| 629 | return true; | |
| 630 | } | |
| 631 | #endif | |
| 604 | 632 | dl_iterate_cb_data cb_data = {this, &info, targetAddr}; |
| 605 | 633 | int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data); |
| 606 | 634 | return static_cast<bool>(found); |
lib/libunwind/src/CompactUnwinder.hpp+1| ... | ... | @@ -19,6 +19,7 @@ |
| 19 | 19 | #include <mach-o/compact_unwind_encoding.h> |
| 20 | 20 | |
| 21 | 21 | #include "Registers.hpp" |
| 22 | #include "libunwind_ext.h" | |
| 22 | 23 | |
| 23 | 24 | #define EXTRACT_BITS(value, mask) \ |
| 24 | 25 | ((value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask))) - 1)) |
lib/libunwind/src/DwarfInstructions.hpp+41-9| ... | ... | @@ -16,16 +16,17 @@ |
| 16 | 16 | #include <stdio.h> |
| 17 | 17 | #include <stdlib.h> |
| 18 | 18 | |
| 19 | #include "dwarf2.h" | |
| 20 | #include "Registers.hpp" | |
| 21 | 19 | #include "DwarfParser.hpp" |
| 20 | #include "Registers.hpp" | |
| 22 | 21 | #include "config.h" |
| 22 | #include "dwarf2.h" | |
| 23 | #include "libunwind_ext.h" | |
| 23 | 24 | |
| 24 | 25 | |
| 25 | 26 | namespace libunwind { |
| 26 | 27 | |
| 27 | 28 | |
| 28 | /// DwarfInstructions maps abtract DWARF unwind instructions to a particular | |
| 29 | /// DwarfInstructions maps abstract DWARF unwind instructions to a particular | |
| 29 | 30 | /// architecture |
| 30 | 31 | template <typename A, typename R> |
| 31 | 32 | class DwarfInstructions { |
| ... | ... | @@ -34,7 +35,7 @@ public: |
| 34 | 35 | typedef typename A::sint_t sint_t; |
| 35 | 36 | |
| 36 | 37 | static int stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart, |
| 37 | R &registers, bool &isSignalFrame); | |
| 38 | R &registers, bool &isSignalFrame, bool stage2); | |
| 38 | 39 | |
| 39 | 40 | private: |
| 40 | 41 | |
| ... | ... | @@ -189,7 +190,7 @@ bool DwarfInstructions<A, R>::getRA_SIGN_STATE(A &addressSpace, R registers, |
| 189 | 190 | template <typename A, typename R> |
| 190 | 191 | int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, |
| 191 | 192 | pint_t fdeStart, R &registers, |
| 192 | bool &isSignalFrame) { | |
| 193 | bool &isSignalFrame, bool stage2) { | |
| 193 | 194 | FDE_Info fdeInfo; |
| 194 | 195 | CIE_Info cieInfo; |
| 195 | 196 | if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo, |
| ... | ... | @@ -200,7 +201,38 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, |
| 200 | 201 | // get pointer to cfa (architecture specific) |
| 201 | 202 | pint_t cfa = getCFA(addressSpace, prolog, registers); |
| 202 | 203 | |
| 203 | // restore registers that DWARF says were saved | |
| 204 | (void)stage2; | |
| 205 | // __unw_step_stage2 is not used for cross unwinding, so we use | |
| 206 | // __aarch64__ rather than LIBUNWIND_TARGET_AARCH64 to make sure we are | |
| 207 | // building for AArch64 natively. | |
| 208 | #if defined(__aarch64__) | |
| 209 | if (stage2 && cieInfo.mteTaggedFrame) { | |
| 210 | pint_t sp = registers.getSP(); | |
| 211 | pint_t p = sp; | |
| 212 | // AArch64 doesn't require the value of SP to be 16-byte aligned at | |
| 213 | // all times, only at memory accesses and public interfaces [1]. Thus, | |
| 214 | // a signal could arrive at a point where SP is not aligned properly. | |
| 215 | // In that case, the kernel fixes up [2] the signal frame, but we | |
| 216 | // still have a misaligned SP in the previous frame. If that signal | |
| 217 | // handler caused stack unwinding, we would have an unaligned SP. | |
| 218 | // We do not need to fix up the CFA, as that is the SP at a "public | |
| 219 | // interface". | |
| 220 | // [1]: | |
| 221 | // https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#622the-stack | |
| 222 | // [2]: | |
| 223 | // https://github.com/torvalds/linux/blob/1930a6e739c4b4a654a69164dbe39e554d228915/arch/arm64/kernel/signal.c#L718 | |
| 224 | p &= ~0xfULL; | |
| 225 | // CFA is the bottom of the current stack frame. | |
| 226 | for (; p < cfa; p += 16) { | |
| 227 | __asm__ __volatile__(".arch_extension memtag\n" | |
| 228 | "stg %[Ptr], [%[Ptr]]\n" | |
| 229 | : | |
| 230 | : [Ptr] "r"(p) | |
| 231 | : "memory"); | |
| 232 | } | |
| 233 | } | |
| 234 | #endif | |
| 235 | // restore registers that DWARF says were saved | |
| 204 | 236 | R newRegisters = registers; |
| 205 | 237 | |
| 206 | 238 | // Typically, the CFA is the stack pointer at the call site in |
| ... | ... | @@ -241,7 +273,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, |
| 241 | 273 | return UNW_EBADREG; |
| 242 | 274 | } else if (i == (int)cieInfo.returnAddressRegister) { |
| 243 | 275 | // Leaf function keeps the return address in register and there is no |
| 244 | // explicit intructions how to restore it. | |
| 276 | // explicit instructions how to restore it. | |
| 245 | 277 | returnAddress = registers.getRegister(cieInfo.returnAddressRegister); |
| 246 | 278 | } |
| 247 | 279 | } |
| ... | ... | @@ -331,7 +363,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, |
| 331 | 363 | #endif |
| 332 | 364 | |
| 333 | 365 | // Return address is address after call site instruction, so setting IP to |
| 334 | // that does simualates a return. | |
| 366 | // that does simulates a return. | |
| 335 | 367 | newRegisters.setIP(returnAddress); |
| 336 | 368 | |
| 337 | 369 | // Simulate the step by replacing the register set with the new ones. |
| ... | ... | @@ -635,7 +667,7 @@ DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace, |
| 635 | 667 | svalue = (sint_t)*sp; |
| 636 | 668 | *sp = (pint_t)(svalue >> value); |
| 637 | 669 | if (log) |
| 638 | fprintf(stderr, "shift left arithmetric\n"); | |
| 670 | fprintf(stderr, "shift left arithmetic\n"); | |
| 639 | 671 | break; |
| 640 | 672 | |
| 641 | 673 | case DW_OP_xor: |
lib/libunwind/src/DwarfParser.hpp+7-2| ... | ... | @@ -51,6 +51,7 @@ public: |
| 51 | 51 | uint8_t returnAddressRegister; |
| 52 | 52 | #if defined(_LIBUNWIND_TARGET_AARCH64) |
| 53 | 53 | bool addressesSignedWithBKey; |
| 54 | bool mteTaggedFrame; | |
| 54 | 55 | #endif |
| 55 | 56 | }; |
| 56 | 57 | |
| ... | ... | @@ -325,6 +326,7 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie, |
| 325 | 326 | cieInfo->fdesHaveAugmentationData = false; |
| 326 | 327 | #if defined(_LIBUNWIND_TARGET_AARCH64) |
| 327 | 328 | cieInfo->addressesSignedWithBKey = false; |
| 329 | cieInfo->mteTaggedFrame = false; | |
| 328 | 330 | #endif |
| 329 | 331 | cieInfo->cieStart = cie; |
| 330 | 332 | pint_t p = cie; |
| ... | ... | @@ -353,7 +355,7 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie, |
| 353 | 355 | while (addressSpace.get8(p) != 0) |
| 354 | 356 | ++p; |
| 355 | 357 | ++p; |
| 356 | // parse code aligment factor | |
| 358 | // parse code alignment factor | |
| 357 | 359 | cieInfo->codeAlignFactor = (uint32_t)addressSpace.getULEB128(p, cieContentEnd); |
| 358 | 360 | // parse data alignment factor |
| 359 | 361 | cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd); |
| ... | ... | @@ -394,6 +396,9 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie, |
| 394 | 396 | case 'B': |
| 395 | 397 | cieInfo->addressesSignedWithBKey = true; |
| 396 | 398 | break; |
| 399 | case 'G': | |
| 400 | cieInfo->mteTaggedFrame = true; | |
| 401 | break; | |
| 397 | 402 | #endif |
| 398 | 403 | default: |
| 399 | 404 | // ignore unknown letters |
| ... | ... | @@ -407,7 +412,7 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie, |
| 407 | 412 | } |
| 408 | 413 | |
| 409 | 414 | |
| 410 | /// "run" the DWARF instructions and create the abstact PrologInfo for an FDE | |
| 415 | /// "run" the DWARF instructions and create the abstract PrologInfo for an FDE | |
| 411 | 416 | template <typename A> |
| 412 | 417 | bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, |
| 413 | 418 | const FDE_Info &fdeInfo, |
lib/libunwind/src/Registers.hpp+276-1| ... | ... | @@ -40,6 +40,7 @@ enum { |
| 40 | 40 | REGISTERS_RISCV, |
| 41 | 41 | REGISTERS_VE, |
| 42 | 42 | REGISTERS_S390X, |
| 43 | REGISTERS_LOONGARCH, | |
| 43 | 44 | }; |
| 44 | 45 | |
| 45 | 46 | #if defined(_LIBUNWIND_TARGET_I386) |
| ... | ... | @@ -4003,7 +4004,7 @@ typedef float fp_t; |
| 4003 | 4004 | # error "Unsupported __riscv_flen" |
| 4004 | 4005 | # endif |
| 4005 | 4006 | # else |
| 4006 | // This is just for supressing undeclared error of fp_t. | |
| 4007 | // This is just for suppressing undeclared error of fp_t. | |
| 4007 | 4008 | typedef double fp_t; |
| 4008 | 4009 | # endif |
| 4009 | 4010 | # else |
| ... | ... | @@ -4084,6 +4085,8 @@ inline bool Registers_riscv::validRegister(int regNum) const { |
| 4084 | 4085 | return true; |
| 4085 | 4086 | if (regNum < 0) |
| 4086 | 4087 | return false; |
| 4088 | if (regNum == UNW_RISCV_VLENB) | |
| 4089 | return true; | |
| 4087 | 4090 | if (regNum > UNW_RISCV_F31) |
| 4088 | 4091 | return false; |
| 4089 | 4092 | return true; |
| ... | ... | @@ -4098,6 +4101,11 @@ inline reg_t Registers_riscv::getRegister(int regNum) const { |
| 4098 | 4101 | return 0; |
| 4099 | 4102 | if ((regNum > 0) && (regNum < 32)) |
| 4100 | 4103 | return _registers[regNum]; |
| 4104 | if (regNum == UNW_RISCV_VLENB) { | |
| 4105 | reg_t vlenb; | |
| 4106 | __asm__("csrr %0, 0xC22" : "=r"(vlenb)); | |
| 4107 | return vlenb; | |
| 4108 | } | |
| 4101 | 4109 | _LIBUNWIND_ABORT("unsupported riscv register"); |
| 4102 | 4110 | } |
| 4103 | 4111 | |
| ... | ... | @@ -4249,6 +4257,8 @@ inline const char *Registers_riscv::getRegisterName(int regNum) { |
| 4249 | 4257 | return "ft10"; |
| 4250 | 4258 | case UNW_RISCV_F31: |
| 4251 | 4259 | return "ft11"; |
| 4260 | case UNW_RISCV_VLENB: | |
| 4261 | return "vlenb"; | |
| 4252 | 4262 | default: |
| 4253 | 4263 | return "unknown register"; |
| 4254 | 4264 | } |
| ... | ... | @@ -5031,6 +5041,271 @@ inline const char *Registers_s390x::getRegisterName(int regNum) { |
| 5031 | 5041 | } |
| 5032 | 5042 | #endif // _LIBUNWIND_TARGET_S390X |
| 5033 | 5043 | |
| 5044 | #if defined(_LIBUNWIND_TARGET_LOONGARCH) | |
| 5045 | /// Registers_loongarch holds the register state of a thread in a 64-bit | |
| 5046 | /// LoongArch process. | |
| 5047 | class _LIBUNWIND_HIDDEN Registers_loongarch { | |
| 5048 | public: | |
| 5049 | Registers_loongarch(); | |
| 5050 | Registers_loongarch(const void *registers); | |
| 5051 | ||
| 5052 | bool validRegister(int num) const; | |
| 5053 | uint64_t getRegister(int num) const; | |
| 5054 | void setRegister(int num, uint64_t value); | |
| 5055 | bool validFloatRegister(int num) const; | |
| 5056 | double getFloatRegister(int num) const; | |
| 5057 | void setFloatRegister(int num, double value); | |
| 5058 | bool validVectorRegister(int num) const; | |
| 5059 | v128 getVectorRegister(int num) const; | |
| 5060 | void setVectorRegister(int num, v128 value); | |
| 5061 | static const char *getRegisterName(int num); | |
| 5062 | void jumpto(); | |
| 5063 | static constexpr int lastDwarfRegNum() { | |
| 5064 | return _LIBUNWIND_HIGHEST_DWARF_REGISTER_LOONGARCH; | |
| 5065 | } | |
| 5066 | static int getArch() { return REGISTERS_LOONGARCH; } | |
| 5067 | ||
| 5068 | uint64_t getSP() const { return _registers.__r[3]; } | |
| 5069 | void setSP(uint64_t value) { _registers.__r[3] = value; } | |
| 5070 | uint64_t getIP() const { return _registers.__pc; } | |
| 5071 | void setIP(uint64_t value) { _registers.__pc = value; } | |
| 5072 | ||
| 5073 | private: | |
| 5074 | struct loongarch_thread_state_t { | |
| 5075 | uint64_t __r[32]; | |
| 5076 | uint64_t __pc; | |
| 5077 | }; | |
| 5078 | ||
| 5079 | loongarch_thread_state_t _registers; | |
| 5080 | #if __loongarch_frlen == 64 | |
| 5081 | double _floats[32]; | |
| 5082 | #endif | |
| 5083 | }; | |
| 5084 | ||
| 5085 | inline Registers_loongarch::Registers_loongarch(const void *registers) { | |
| 5086 | static_assert((check_fit<Registers_loongarch, unw_context_t>::does_fit), | |
| 5087 | "loongarch registers do not fit into unw_context_t"); | |
| 5088 | memcpy(&_registers, registers, sizeof(_registers)); | |
| 5089 | static_assert(sizeof(_registers) == 0x108, | |
| 5090 | "expected float registers to be at offset 264"); | |
| 5091 | #if __loongarch_frlen == 64 | |
| 5092 | memcpy(_floats, static_cast<const uint8_t *>(registers) + sizeof(_registers), | |
| 5093 | sizeof(_floats)); | |
| 5094 | #endif | |
| 5095 | } | |
| 5096 | ||
| 5097 | inline Registers_loongarch::Registers_loongarch() { | |
| 5098 | memset(&_registers, 0, sizeof(_registers)); | |
| 5099 | #if __loongarch_frlen == 64 | |
| 5100 | memset(&_floats, 0, sizeof(_floats)); | |
| 5101 | #endif | |
| 5102 | } | |
| 5103 | ||
| 5104 | inline bool Registers_loongarch::validRegister(int regNum) const { | |
| 5105 | if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) | |
| 5106 | return true; | |
| 5107 | if (regNum < 0 || regNum > UNW_LOONGARCH_F31) | |
| 5108 | return false; | |
| 5109 | return true; | |
| 5110 | } | |
| 5111 | ||
| 5112 | inline uint64_t Registers_loongarch::getRegister(int regNum) const { | |
| 5113 | if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31) | |
| 5114 | return _registers.__r[regNum - UNW_LOONGARCH_R0]; | |
| 5115 | ||
| 5116 | if (regNum == UNW_REG_IP) | |
| 5117 | return _registers.__pc; | |
| 5118 | if (regNum == UNW_REG_SP) | |
| 5119 | return _registers.__r[3]; | |
| 5120 | _LIBUNWIND_ABORT("unsupported loongarch register"); | |
| 5121 | } | |
| 5122 | ||
| 5123 | inline void Registers_loongarch::setRegister(int regNum, uint64_t value) { | |
| 5124 | if (regNum >= UNW_LOONGARCH_R0 && regNum <= UNW_LOONGARCH_R31) | |
| 5125 | _registers.__r[regNum - UNW_LOONGARCH_R0] = value; | |
| 5126 | else if (regNum == UNW_REG_IP) | |
| 5127 | _registers.__pc = value; | |
| 5128 | else if (regNum == UNW_REG_SP) | |
| 5129 | _registers.__r[3] = value; | |
| 5130 | else | |
| 5131 | _LIBUNWIND_ABORT("unsupported loongarch register"); | |
| 5132 | } | |
| 5133 | ||
| 5134 | inline const char *Registers_loongarch::getRegisterName(int regNum) { | |
| 5135 | switch (regNum) { | |
| 5136 | case UNW_REG_IP: | |
| 5137 | return "$pc"; | |
| 5138 | case UNW_REG_SP: | |
| 5139 | return "$sp"; | |
| 5140 | case UNW_LOONGARCH_R0: | |
| 5141 | return "$r0"; | |
| 5142 | case UNW_LOONGARCH_R1: | |
| 5143 | return "$r1"; | |
| 5144 | case UNW_LOONGARCH_R2: | |
| 5145 | return "$r2"; | |
| 5146 | case UNW_LOONGARCH_R3: | |
| 5147 | return "$r3"; | |
| 5148 | case UNW_LOONGARCH_R4: | |
| 5149 | return "$r4"; | |
| 5150 | case UNW_LOONGARCH_R5: | |
| 5151 | return "$r5"; | |
| 5152 | case UNW_LOONGARCH_R6: | |
| 5153 | return "$r6"; | |
| 5154 | case UNW_LOONGARCH_R7: | |
| 5155 | return "$r7"; | |
| 5156 | case UNW_LOONGARCH_R8: | |
| 5157 | return "$r8"; | |
| 5158 | case UNW_LOONGARCH_R9: | |
| 5159 | return "$r9"; | |
| 5160 | case UNW_LOONGARCH_R10: | |
| 5161 | return "$r10"; | |
| 5162 | case UNW_LOONGARCH_R11: | |
| 5163 | return "$r11"; | |
| 5164 | case UNW_LOONGARCH_R12: | |
| 5165 | return "$r12"; | |
| 5166 | case UNW_LOONGARCH_R13: | |
| 5167 | return "$r13"; | |
| 5168 | case UNW_LOONGARCH_R14: | |
| 5169 | return "$r14"; | |
| 5170 | case UNW_LOONGARCH_R15: | |
| 5171 | return "$r15"; | |
| 5172 | case UNW_LOONGARCH_R16: | |
| 5173 | return "$r16"; | |
| 5174 | case UNW_LOONGARCH_R17: | |
| 5175 | return "$r17"; | |
| 5176 | case UNW_LOONGARCH_R18: | |
| 5177 | return "$r18"; | |
| 5178 | case UNW_LOONGARCH_R19: | |
| 5179 | return "$r19"; | |
| 5180 | case UNW_LOONGARCH_R20: | |
| 5181 | return "$r20"; | |
| 5182 | case UNW_LOONGARCH_R21: | |
| 5183 | return "$r21"; | |
| 5184 | case UNW_LOONGARCH_R22: | |
| 5185 | return "$r22"; | |
| 5186 | case UNW_LOONGARCH_R23: | |
| 5187 | return "$r23"; | |
| 5188 | case UNW_LOONGARCH_R24: | |
| 5189 | return "$r24"; | |
| 5190 | case UNW_LOONGARCH_R25: | |
| 5191 | return "$r25"; | |
| 5192 | case UNW_LOONGARCH_R26: | |
| 5193 | return "$r26"; | |
| 5194 | case UNW_LOONGARCH_R27: | |
| 5195 | return "$r27"; | |
| 5196 | case UNW_LOONGARCH_R28: | |
| 5197 | return "$r28"; | |
| 5198 | case UNW_LOONGARCH_R29: | |
| 5199 | return "$r29"; | |
| 5200 | case UNW_LOONGARCH_R30: | |
| 5201 | return "$r30"; | |
| 5202 | case UNW_LOONGARCH_R31: | |
| 5203 | return "$r31"; | |
| 5204 | case UNW_LOONGARCH_F0: | |
| 5205 | return "$f0"; | |
| 5206 | case UNW_LOONGARCH_F1: | |
| 5207 | return "$f1"; | |
| 5208 | case UNW_LOONGARCH_F2: | |
| 5209 | return "$f2"; | |
| 5210 | case UNW_LOONGARCH_F3: | |
| 5211 | return "$f3"; | |
| 5212 | case UNW_LOONGARCH_F4: | |
| 5213 | return "$f4"; | |
| 5214 | case UNW_LOONGARCH_F5: | |
| 5215 | return "$f5"; | |
| 5216 | case UNW_LOONGARCH_F6: | |
| 5217 | return "$f6"; | |
| 5218 | case UNW_LOONGARCH_F7: | |
| 5219 | return "$f7"; | |
| 5220 | case UNW_LOONGARCH_F8: | |
| 5221 | return "$f8"; | |
| 5222 | case UNW_LOONGARCH_F9: | |
| 5223 | return "$f9"; | |
| 5224 | case UNW_LOONGARCH_F10: | |
| 5225 | return "$f10"; | |
| 5226 | case UNW_LOONGARCH_F11: | |
| 5227 | return "$f11"; | |
| 5228 | case UNW_LOONGARCH_F12: | |
| 5229 | return "$f12"; | |
| 5230 | case UNW_LOONGARCH_F13: | |
| 5231 | return "$f13"; | |
| 5232 | case UNW_LOONGARCH_F14: | |
| 5233 | return "$f14"; | |
| 5234 | case UNW_LOONGARCH_F15: | |
| 5235 | return "$f15"; | |
| 5236 | case UNW_LOONGARCH_F16: | |
| 5237 | return "$f16"; | |
| 5238 | case UNW_LOONGARCH_F17: | |
| 5239 | return "$f17"; | |
| 5240 | case UNW_LOONGARCH_F18: | |
| 5241 | return "$f18"; | |
| 5242 | case UNW_LOONGARCH_F19: | |
| 5243 | return "$f19"; | |
| 5244 | case UNW_LOONGARCH_F20: | |
| 5245 | return "$f20"; | |
| 5246 | case UNW_LOONGARCH_F21: | |
| 5247 | return "$f21"; | |
| 5248 | case UNW_LOONGARCH_F22: | |
| 5249 | return "$f22"; | |
| 5250 | case UNW_LOONGARCH_F23: | |
| 5251 | return "$f23"; | |
| 5252 | case UNW_LOONGARCH_F24: | |
| 5253 | return "$f24"; | |
| 5254 | case UNW_LOONGARCH_F25: | |
| 5255 | return "$f25"; | |
| 5256 | case UNW_LOONGARCH_F26: | |
| 5257 | return "$f26"; | |
| 5258 | case UNW_LOONGARCH_F27: | |
| 5259 | return "$f27"; | |
| 5260 | case UNW_LOONGARCH_F28: | |
| 5261 | return "$f28"; | |
| 5262 | case UNW_LOONGARCH_F29: | |
| 5263 | return "$f29"; | |
| 5264 | case UNW_LOONGARCH_F30: | |
| 5265 | return "$f30"; | |
| 5266 | case UNW_LOONGARCH_F31: | |
| 5267 | return "$f31"; | |
| 5268 | default: | |
| 5269 | return "unknown register"; | |
| 5270 | } | |
| 5271 | } | |
| 5272 | ||
| 5273 | inline bool Registers_loongarch::validFloatRegister(int regNum) const { | |
| 5274 | if (regNum < UNW_LOONGARCH_F0 || regNum > UNW_LOONGARCH_F31) | |
| 5275 | return false; | |
| 5276 | return true; | |
| 5277 | } | |
| 5278 | ||
| 5279 | inline double Registers_loongarch::getFloatRegister(int regNum) const { | |
| 5280 | #if __loongarch_frlen == 64 | |
| 5281 | assert(validFloatRegister(regNum)); | |
| 5282 | return _floats[regNum - UNW_LOONGARCH_F0]; | |
| 5283 | #else | |
| 5284 | _LIBUNWIND_ABORT("libunwind not built with float support"); | |
| 5285 | #endif | |
| 5286 | } | |
| 5287 | ||
| 5288 | inline void Registers_loongarch::setFloatRegister(int regNum, double value) { | |
| 5289 | #if __loongarch_frlen == 64 | |
| 5290 | assert(validFloatRegister(regNum)); | |
| 5291 | _floats[regNum - UNW_LOONGARCH_F0] = value; | |
| 5292 | #else | |
| 5293 | _LIBUNWIND_ABORT("libunwind not built with float support"); | |
| 5294 | #endif | |
| 5295 | } | |
| 5296 | ||
| 5297 | inline bool Registers_loongarch::validVectorRegister(int) const { | |
| 5298 | return false; | |
| 5299 | } | |
| 5300 | ||
| 5301 | inline v128 Registers_loongarch::getVectorRegister(int) const { | |
| 5302 | _LIBUNWIND_ABORT("loongarch vector support not implemented"); | |
| 5303 | } | |
| 5304 | ||
| 5305 | inline void Registers_loongarch::setVectorRegister(int, v128) { | |
| 5306 | _LIBUNWIND_ABORT("loongarch vector support not implemented"); | |
| 5307 | } | |
| 5308 | #endif //_LIBUNWIND_TARGET_LOONGARCH | |
| 5034 | 5309 | |
| 5035 | 5310 | } // namespace libunwind |
| 5036 | 5311 |
lib/libunwind/src/Unwind-EHABI.cpp+2-2| ... | ... | @@ -235,7 +235,7 @@ decode_eht_entry(const uint32_t* data, size_t* off, size_t* len) { |
| 235 | 235 | } else { |
| 236 | 236 | // 6.3: ARM Compact Model |
| 237 | 237 | // |
| 238 | // EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeded | |
| 238 | // EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeed | |
| 239 | 239 | // by format: |
| 240 | 240 | Descriptor::Format format = |
| 241 | 241 | static_cast<Descriptor::Format>((*data & 0x0f000000) >> 24); |
| ... | ... | @@ -845,7 +845,7 @@ _LIBUNWIND_EXPORT void _Unwind_Complete(_Unwind_Exception* exception_object) { |
| 845 | 845 | /// may force a jump to a landing pad in that function, the landing |
| 846 | 846 | /// pad code may then call _Unwind_Resume() to continue with the |
| 847 | 847 | /// unwinding. Note: the call to _Unwind_Resume() is from compiler |
| 848 | /// geneated user code. All other _Unwind_* routines are called | |
| 848 | /// generated user code. All other _Unwind_* routines are called | |
| 849 | 849 | /// by the C++ runtime __cxa_* routines. |
| 850 | 850 | /// |
| 851 | 851 | /// Note: re-throwing an exception (as opposed to continuing the unwind) |
lib/libunwind/src/Unwind-seh.cpp+3-3| ... | ... | @@ -137,7 +137,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, |
| 137 | 137 | // If we were called by __libunwind_seh_personality(), indicate that |
| 138 | 138 | // a handler was found; otherwise, initiate phase 2 by unwinding. |
| 139 | 139 | if (ours && ms_exc->NumberParameters > 1) |
| 140 | return 4 /* ExecptionExecuteHandler in mingw */; | |
| 140 | return 4 /* ExceptionExecuteHandler in mingw */; | |
| 141 | 141 | // This should never happen in phase 2. |
| 142 | 142 | if (IS_UNWINDING(ms_exc->ExceptionFlags)) |
| 143 | 143 | _LIBUNWIND_ABORT("Personality indicated exception handler in phase 2!"); |
| ... | ... | @@ -155,7 +155,7 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, |
| 155 | 155 | // a handler was found; otherwise, it's time to initiate a collided |
| 156 | 156 | // unwind to the target. |
| 157 | 157 | if (ours && !IS_UNWINDING(ms_exc->ExceptionFlags) && ms_exc->NumberParameters > 1) |
| 158 | return 4 /* ExecptionExecuteHandler in mingw */; | |
| 158 | return 4 /* ExceptionExecuteHandler in mingw */; | |
| 159 | 159 | // This should never happen in phase 1. |
| 160 | 160 | if (!IS_UNWINDING(ms_exc->ExceptionFlags)) |
| 161 | 161 | _LIBUNWIND_ABORT("Personality installed context during phase 1!"); |
| ... | ... | @@ -354,7 +354,7 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) { |
| 354 | 354 | /// may force a jump to a landing pad in that function; the landing |
| 355 | 355 | /// pad code may then call \c _Unwind_Resume() to continue with the |
| 356 | 356 | /// unwinding. Note: the call to \c _Unwind_Resume() is from compiler |
| 357 | /// geneated user code. All other \c _Unwind_* routines are called | |
| 357 | /// generated user code. All other \c _Unwind_* routines are called | |
| 358 | 358 | /// by the C++ runtime \c __cxa_* routines. |
| 359 | 359 | /// |
| 360 | 360 | /// Note: re-throwing an exception (as opposed to continuing the unwind) |
lib/libunwind/src/Unwind-sjlj.c+3-3| ... | ... | @@ -33,7 +33,7 @@ struct _Unwind_FunctionContext { |
| 33 | 33 | struct _Unwind_FunctionContext *prev; |
| 34 | 34 | |
| 35 | 35 | #if defined(__ve__) |
| 36 | // VE requires to store 64 bit pointers in the buffer for SjLj execption. | |
| 36 | // VE requires to store 64 bit pointers in the buffer for SjLj exception. | |
| 37 | 37 | // We expand the size of values defined here. This size must be matched |
| 38 | 38 | // to the size returned by TargetMachine::getSjLjDataSize(). |
| 39 | 39 | |
| ... | ... | @@ -357,7 +357,7 @@ _Unwind_SjLj_RaiseException(struct _Unwind_Exception *exception_object) { |
| 357 | 357 | /// may force a jump to a landing pad in that function, the landing |
| 358 | 358 | /// pad code may then call _Unwind_Resume() to continue with the |
| 359 | 359 | /// unwinding. Note: the call to _Unwind_Resume() is from compiler |
| 360 | /// geneated user code. All other _Unwind_* routines are called | |
| 360 | /// generated user code. All other _Unwind_* routines are called | |
| 361 | 361 | /// by the C++ runtime __cxa_* routines. |
| 362 | 362 | /// |
| 363 | 363 | /// Re-throwing an exception is implemented by having the code call |
| ... | ... | @@ -394,7 +394,7 @@ _Unwind_SjLj_Resume_or_Rethrow(struct _Unwind_Exception *exception_object) { |
| 394 | 394 | // std::terminate() |
| 395 | 395 | } |
| 396 | 396 | |
| 397 | // Call through to _Unwind_Resume() which distiguishes between forced and | |
| 397 | // Call through to _Unwind_Resume() which distinguishes between forced and | |
| 398 | 398 | // regular exceptions. |
| 399 | 399 | _Unwind_SjLj_Resume(exception_object); |
| 400 | 400 | _LIBUNWIND_ABORT("__Unwind_SjLj_Resume_or_Rethrow() called " |
lib/libunwind/src/UnwindCursor.hpp+51-31| ... | ... | @@ -38,6 +38,17 @@ |
| 38 | 38 | #define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1 |
| 39 | 39 | #endif |
| 40 | 40 | |
| 41 | #include "AddressSpace.hpp" | |
| 42 | #include "CompactUnwinder.hpp" | |
| 43 | #include "config.h" | |
| 44 | #include "DwarfInstructions.hpp" | |
| 45 | #include "EHHeaderParser.hpp" | |
| 46 | #include "libunwind.h" | |
| 47 | #include "libunwind_ext.h" | |
| 48 | #include "Registers.hpp" | |
| 49 | #include "RWMutex.hpp" | |
| 50 | #include "Unwind-EHABI.h" | |
| 51 | ||
| 41 | 52 | #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) |
| 42 | 53 | // Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and |
| 43 | 54 | // earlier) SDKs. |
| ... | ... | @@ -75,18 +86,6 @@ extern "C" _Unwind_Reason_Code __libunwind_seh_personality( |
| 75 | 86 | |
| 76 | 87 | #endif |
| 77 | 88 | |
| 78 | #include "config.h" | |
| 79 | ||
| 80 | #include "AddressSpace.hpp" | |
| 81 | #include "CompactUnwinder.hpp" | |
| 82 | #include "config.h" | |
| 83 | #include "DwarfInstructions.hpp" | |
| 84 | #include "EHHeaderParser.hpp" | |
| 85 | #include "libunwind.h" | |
| 86 | #include "Registers.hpp" | |
| 87 | #include "RWMutex.hpp" | |
| 88 | #include "Unwind-EHABI.h" | |
| 89 | ||
| 90 | 89 | namespace libunwind { |
| 91 | 90 | |
| 92 | 91 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
| ... | ... | @@ -443,7 +442,7 @@ public: |
| 443 | 442 | virtual void setFloatReg(int, unw_fpreg_t) { |
| 444 | 443 | _LIBUNWIND_ABORT("setFloatReg not implemented"); |
| 445 | 444 | } |
| 446 | virtual int step() { _LIBUNWIND_ABORT("step not implemented"); } | |
| 445 | virtual int step(bool = false) { _LIBUNWIND_ABORT("step not implemented"); } | |
| 447 | 446 | virtual void getInfo(unw_proc_info_t *) { |
| 448 | 447 | _LIBUNWIND_ABORT("getInfo not implemented"); |
| 449 | 448 | } |
| ... | ... | @@ -495,7 +494,7 @@ public: |
| 495 | 494 | virtual bool validFloatReg(int); |
| 496 | 495 | virtual unw_fpreg_t getFloatReg(int); |
| 497 | 496 | virtual void setFloatReg(int, unw_fpreg_t); |
| 498 | virtual int step(); | |
| 497 | virtual int step(bool = false); | |
| 499 | 498 | virtual void getInfo(unw_proc_info_t *); |
| 500 | 499 | virtual void jumpto(); |
| 501 | 500 | virtual bool isSignalFrame(); |
| ... | ... | @@ -510,7 +509,7 @@ public: |
| 510 | 509 | void setDispatcherContext(DISPATCHER_CONTEXT *disp) { _dispContext = *disp; } |
| 511 | 510 | |
| 512 | 511 | // libunwind does not and should not depend on C++ library which means that we |
| 513 | // need our own defition of inline placement new. | |
| 512 | // need our own definition of inline placement new. | |
| 514 | 513 | static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; } |
| 515 | 514 | |
| 516 | 515 | private: |
| ... | ... | @@ -926,7 +925,7 @@ public: |
| 926 | 925 | virtual bool validFloatReg(int); |
| 927 | 926 | virtual unw_fpreg_t getFloatReg(int); |
| 928 | 927 | virtual void setFloatReg(int, unw_fpreg_t); |
| 929 | virtual int step(); | |
| 928 | virtual int step(bool stage2 = false); | |
| 930 | 929 | virtual void getInfo(unw_proc_info_t *); |
| 931 | 930 | virtual void jumpto(); |
| 932 | 931 | virtual bool isSignalFrame(); |
| ... | ... | @@ -946,7 +945,7 @@ public: |
| 946 | 945 | #endif |
| 947 | 946 | |
| 948 | 947 | // libunwind does not and should not depend on C++ library which means that we |
| 949 | // need our own defition of inline placement new. | |
| 948 | // need our own definition of inline placement new. | |
| 950 | 949 | static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; } |
| 951 | 950 | |
| 952 | 951 | private: |
| ... | ... | @@ -1000,22 +999,21 @@ private: |
| 1000 | 999 | pint_t pc, uintptr_t dso_base); |
| 1001 | 1000 | bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections &sects, |
| 1002 | 1001 | uint32_t fdeSectionOffsetHint=0); |
| 1003 | int stepWithDwarfFDE() { | |
| 1004 | return DwarfInstructions<A, R>::stepWithDwarf(_addressSpace, | |
| 1005 | (pint_t)this->getReg(UNW_REG_IP), | |
| 1006 | (pint_t)_info.unwind_info, | |
| 1007 | _registers, _isSignalFrame); | |
| 1002 | int stepWithDwarfFDE(bool stage2) { | |
| 1003 | return DwarfInstructions<A, R>::stepWithDwarf( | |
| 1004 | _addressSpace, (pint_t)this->getReg(UNW_REG_IP), | |
| 1005 | (pint_t)_info.unwind_info, _registers, _isSignalFrame, stage2); | |
| 1008 | 1006 | } |
| 1009 | 1007 | #endif |
| 1010 | 1008 | |
| 1011 | 1009 | #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) |
| 1012 | 1010 | bool getInfoFromCompactEncodingSection(pint_t pc, |
| 1013 | 1011 | const UnwindInfoSections &sects); |
| 1014 | int stepWithCompactEncoding() { | |
| 1015 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | |
| 1012 | int stepWithCompactEncoding(bool stage2 = false) { | |
| 1013 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | |
| 1016 | 1014 | if ( compactSaysUseDwarf() ) |
| 1017 | return stepWithDwarfFDE(); | |
| 1018 | #endif | |
| 1015 | return stepWithDwarfFDE(stage2); | |
| 1016 | #endif | |
| 1019 | 1017 | R dummy; |
| 1020 | 1018 | return stepWithCompactEncoding(dummy); |
| 1021 | 1019 | } |
| ... | ... | @@ -1066,6 +1064,10 @@ private: |
| 1066 | 1064 | } |
| 1067 | 1065 | #endif |
| 1068 | 1066 | |
| 1067 | #if defined(_LIBUNWIND_TARGET_LOONGARCH) | |
| 1068 | int stepWithCompactEncoding(Registers_loongarch &) { return UNW_EINVAL; } | |
| 1069 | #endif | |
| 1070 | ||
| 1069 | 1071 | #if defined(_LIBUNWIND_TARGET_SPARC) |
| 1070 | 1072 | int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; } |
| 1071 | 1073 | #endif |
| ... | ... | @@ -1142,6 +1144,12 @@ private: |
| 1142 | 1144 | } |
| 1143 | 1145 | #endif |
| 1144 | 1146 | |
| 1147 | #if defined(_LIBUNWIND_TARGET_LOONGARCH) | |
| 1148 | bool compactSaysUseDwarf(Registers_loongarch &, uint32_t *) const { | |
| 1149 | return true; | |
| 1150 | } | |
| 1151 | #endif | |
| 1152 | ||
| 1145 | 1153 | #if defined(_LIBUNWIND_TARGET_SPARC) |
| 1146 | 1154 | bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; } |
| 1147 | 1155 | #endif |
| ... | ... | @@ -1226,6 +1234,12 @@ private: |
| 1226 | 1234 | } |
| 1227 | 1235 | #endif |
| 1228 | 1236 | |
| 1237 | #if defined(_LIBUNWIND_TARGET_LOONGARCH) | |
| 1238 | compact_unwind_encoding_t dwarfEncoding(Registers_loongarch &) const { | |
| 1239 | return 0; | |
| 1240 | } | |
| 1241 | #endif | |
| 1242 | ||
| 1229 | 1243 | #if defined(_LIBUNWIND_TARGET_SPARC) |
| 1230 | 1244 | compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; } |
| 1231 | 1245 | #endif |
| ... | ... | @@ -2106,6 +2120,11 @@ bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R &registers) { |
| 2106 | 2120 | // using dlopen(). |
| 2107 | 2121 | const char libcxxabi[] = "libc++abi.a(libc++abi.so.1)"; |
| 2108 | 2122 | void *libHandle; |
| 2123 | // The AIX dlopen() sets errno to 0 when it is successful, which | |
| 2124 | // clobbers the value of errno from the user code. This is an AIX | |
| 2125 | // bug because according to POSIX it should not set errno to 0. To | |
| 2126 | // workaround before AIX fixes the bug, errno is saved and restored. | |
| 2127 | int saveErrno = errno; | |
| 2109 | 2128 | libHandle = dlopen(libcxxabi, RTLD_MEMBER | RTLD_NOW); |
| 2110 | 2129 | if (libHandle == NULL) { |
| 2111 | 2130 | _LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n", |
| ... | ... | @@ -2119,6 +2138,7 @@ bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R &registers) { |
| 2119 | 2138 | assert(0 && "dlsym() failed"); |
| 2120 | 2139 | } |
| 2121 | 2140 | dlclose(libHandle); |
| 2141 | errno = saveErrno; | |
| 2122 | 2142 | } |
| 2123 | 2143 | } |
| 2124 | 2144 | xlcPersonalityV0InitLock.unlock(); |
| ... | ... | @@ -2455,7 +2475,7 @@ int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable, |
| 2455 | 2475 | reinterpret_cast<void *>(pc)); |
| 2456 | 2476 | |
| 2457 | 2477 | // The return address is the address after call site instruction, so |
| 2458 | // setting IP to that simualates a return. | |
| 2478 | // setting IP to that simulates a return. | |
| 2459 | 2479 | newRegisters.setIP(reinterpret_cast<uintptr_t>(returnAddress)); |
| 2460 | 2480 | |
| 2461 | 2481 | // Simulate the step by replacing the register set with the new ones. |
| ... | ... | @@ -2791,8 +2811,8 @@ int UnwindCursor<A, R>::stepThroughSigReturn(Registers_s390x &) { |
| 2791 | 2811 | #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && |
| 2792 | 2812 | // defined(_LIBUNWIND_TARGET_S390X) |
| 2793 | 2813 | |
| 2794 | template <typename A, typename R> | |
| 2795 | int UnwindCursor<A, R>::step() { | |
| 2814 | template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) { | |
| 2815 | (void)stage2; | |
| 2796 | 2816 | // Bottom of stack is defined is when unwind info cannot be found. |
| 2797 | 2817 | if (_unwindInfoMissing) |
| 2798 | 2818 | return UNW_STEP_END; |
| ... | ... | @@ -2806,13 +2826,13 @@ int UnwindCursor<A, R>::step() { |
| 2806 | 2826 | #endif |
| 2807 | 2827 | { |
| 2808 | 2828 | #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) |
| 2809 | result = this->stepWithCompactEncoding(); | |
| 2829 | result = this->stepWithCompactEncoding(stage2); | |
| 2810 | 2830 | #elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) |
| 2811 | 2831 | result = this->stepWithSEHData(); |
| 2812 | 2832 | #elif defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND) |
| 2813 | 2833 | result = this->stepWithTBTableData(); |
| 2814 | 2834 | #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
| 2815 | result = this->stepWithDwarfFDE(); | |
| 2835 | result = this->stepWithDwarfFDE(stage2); | |
| 2816 | 2836 | #elif defined(_LIBUNWIND_ARM_EHABI) |
| 2817 | 2837 | result = this->stepWithEHABI(); |
| 2818 | 2838 | #else |
lib/libunwind/src/UnwindLevel1-gcc-ext.c+32-1| ... | ... | @@ -22,6 +22,10 @@ |
| 22 | 22 | #include "Unwind-EHABI.h" |
| 23 | 23 | #include "unwind.h" |
| 24 | 24 | |
| 25 | #if defined(_AIX) | |
| 26 | #include <sys/debug.h> | |
| 27 | #endif | |
| 28 | ||
| 25 | 29 | #if defined(_LIBUNWIND_BUILD_ZERO_COST_APIS) |
| 26 | 30 | |
| 27 | 31 | #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) |
| ... | ... | @@ -48,7 +52,7 @@ _Unwind_Resume_or_Rethrow(_Unwind_Exception *exception_object) { |
| 48 | 52 | // std::terminate(). |
| 49 | 53 | } |
| 50 | 54 | |
| 51 | // Call through to _Unwind_Resume() which distiguishes between forced and | |
| 55 | // Call through to _Unwind_Resume() which distinguishes between forced and | |
| 52 | 56 | // regular exceptions. |
| 53 | 57 | _Unwind_Resume(exception_object); |
| 54 | 58 | _LIBUNWIND_ABORT("_Unwind_Resume_or_Rethrow() called _Unwind_RaiseException()" |
| ... | ... | @@ -82,6 +86,32 @@ _Unwind_GetTextRelBase(struct _Unwind_Context *context) { |
| 82 | 86 | /// specified code address "pc". |
| 83 | 87 | _LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) { |
| 84 | 88 | _LIBUNWIND_TRACE_API("_Unwind_FindEnclosingFunction(pc=%p)", pc); |
| 89 | #if defined(_AIX) | |
| 90 | if (pc == NULL) | |
| 91 | return NULL; | |
| 92 | ||
| 93 | // Get the start address of the enclosing function from the function's | |
| 94 | // traceback table. | |
| 95 | uint32_t *p = (uint32_t *)pc; | |
| 96 | ||
| 97 | // Keep looking forward until a word of 0 is found. The traceback | |
| 98 | // table starts at the following word. | |
| 99 | while (*p) | |
| 100 | ++p; | |
| 101 | struct tbtable *TBTable = (struct tbtable *)(p + 1); | |
| 102 | ||
| 103 | // Get the address of the traceback table extension. | |
| 104 | p = (uint32_t *)&TBTable->tb_ext; | |
| 105 | ||
| 106 | // Skip field parminfo if it exists. | |
| 107 | if (TBTable->tb.fixedparms || TBTable->tb.floatparms) | |
| 108 | ++p; | |
| 109 | ||
| 110 | if (TBTable->tb.has_tboff) | |
| 111 | // *p contains the offset from the function start to traceback table. | |
| 112 | return (void *)((uintptr_t)TBTable - *p - sizeof(uint32_t)); | |
| 113 | return NULL; | |
| 114 | #else | |
| 85 | 115 | // This is slow, but works. |
| 86 | 116 | // We create an unwind cursor then alter the IP to be pc |
| 87 | 117 | unw_cursor_t cursor; |
| ... | ... | @@ -94,6 +124,7 @@ _LIBUNWIND_EXPORT void *_Unwind_FindEnclosingFunction(void *pc) { |
| 94 | 124 | return (void *)(intptr_t) info.start_ip; |
| 95 | 125 | else |
| 96 | 126 | return NULL; |
| 127 | #endif | |
| 97 | 128 | } |
| 98 | 129 | |
| 99 | 130 | /// Walk every frame and call trace function at each one. If trace function |
lib/libunwind/src/UnwindLevel1.c+52-32| ... | ... | @@ -41,7 +41,7 @@ |
| 41 | 41 | // In exception handing, some stack frames will be skipped before jumping to |
| 42 | 42 | // landing pad and we must adjust CET shadow stack accordingly. |
| 43 | 43 | // _LIBUNWIND_POP_CET_SSP is used to adjust CET shadow stack pointer and we |
| 44 | // directly jump to __libunwind_Registerts_x86/x86_64_jumpto instead of using | |
| 44 | // directly jump to __libunwind_Registers_x86/x86_64_jumpto instead of using | |
| 45 | 45 | // a regular function call to avoid pushing to CET shadow stack again. |
| 46 | 46 | #if !defined(_LIBUNWIND_USE_CET) |
| 47 | 47 | #define __unw_phase2_resume(cursor, fn) \ |
| ... | ... | @@ -50,6 +50,7 @@ |
| 50 | 50 | __unw_resume((cursor)); \ |
| 51 | 51 | } while (0) |
| 52 | 52 | #elif defined(_LIBUNWIND_TARGET_I386) |
| 53 | #define __cet_ss_step_size 4 | |
| 53 | 54 | #define __unw_phase2_resume(cursor, fn) \ |
| 54 | 55 | do { \ |
| 55 | 56 | _LIBUNWIND_POP_CET_SSP((fn)); \ |
| ... | ... | @@ -61,6 +62,7 @@ |
| 61 | 62 | "d"(cetJumpAddress)); \ |
| 62 | 63 | } while (0) |
| 63 | 64 | #elif defined(_LIBUNWIND_TARGET_X86_64) |
| 65 | #define __cet_ss_step_size 8 | |
| 64 | 66 | #define __unw_phase2_resume(cursor, fn) \ |
| 65 | 67 | do { \ |
| 66 | 68 | _LIBUNWIND_POP_CET_SSP((fn)); \ |
| ... | ... | @@ -82,13 +84,13 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 82 | 84 | int stepResult = __unw_step(cursor); |
| 83 | 85 | if (stepResult == 0) { |
| 84 | 86 | _LIBUNWIND_TRACE_UNWINDING( |
| 85 | "unwind_phase1(ex_ojb=%p): __unw_step() reached " | |
| 87 | "unwind_phase1(ex_obj=%p): __unw_step() reached " | |
| 86 | 88 | "bottom => _URC_END_OF_STACK", |
| 87 | 89 | (void *)exception_object); |
| 88 | 90 | return _URC_END_OF_STACK; |
| 89 | 91 | } else if (stepResult < 0) { |
| 90 | 92 | _LIBUNWIND_TRACE_UNWINDING( |
| 91 | "unwind_phase1(ex_ojb=%p): __unw_step failed => " | |
| 93 | "unwind_phase1(ex_obj=%p): __unw_step failed => " | |
| 92 | 94 | "_URC_FATAL_PHASE1_ERROR", |
| 93 | 95 | (void *)exception_object); |
| 94 | 96 | return _URC_FATAL_PHASE1_ERROR; |
| ... | ... | @@ -99,7 +101,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 99 | 101 | unw_word_t sp; |
| 100 | 102 | if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { |
| 101 | 103 | _LIBUNWIND_TRACE_UNWINDING( |
| 102 | "unwind_phase1(ex_ojb=%p): __unw_get_proc_info " | |
| 104 | "unwind_phase1(ex_obj=%p): __unw_get_proc_info " | |
| 103 | 105 | "failed => _URC_FATAL_PHASE1_ERROR", |
| 104 | 106 | (void *)exception_object); |
| 105 | 107 | return _URC_FATAL_PHASE1_ERROR; |
| ... | ... | @@ -118,7 +120,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 118 | 120 | unw_word_t pc; |
| 119 | 121 | __unw_get_reg(cursor, UNW_REG_IP, &pc); |
| 120 | 122 | _LIBUNWIND_TRACE_UNWINDING( |
| 121 | "unwind_phase1(ex_ojb=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR | |
| 123 | "unwind_phase1(ex_obj=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR | |
| 122 | 124 | ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR "", |
| 123 | 125 | (void *)exception_object, pc, frameInfo.start_ip, functionName, |
| 124 | 126 | frameInfo.lsda, frameInfo.handler); |
| ... | ... | @@ -131,7 +133,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 131 | 133 | _Unwind_Personality_Fn p = |
| 132 | 134 | (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler); |
| 133 | 135 | _LIBUNWIND_TRACE_UNWINDING( |
| 134 | "unwind_phase1(ex_ojb=%p): calling personality function %p", | |
| 136 | "unwind_phase1(ex_obj=%p): calling personality function %p", | |
| 135 | 137 | (void *)exception_object, (void *)(uintptr_t)p); |
| 136 | 138 | _Unwind_Reason_Code personalityResult = |
| 137 | 139 | (*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class, |
| ... | ... | @@ -143,13 +145,13 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 143 | 145 | __unw_get_reg(cursor, UNW_REG_SP, &sp); |
| 144 | 146 | exception_object->private_2 = (uintptr_t)sp; |
| 145 | 147 | _LIBUNWIND_TRACE_UNWINDING( |
| 146 | "unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND", | |
| 148 | "unwind_phase1(ex_obj=%p): _URC_HANDLER_FOUND", | |
| 147 | 149 | (void *)exception_object); |
| 148 | 150 | return _URC_NO_REASON; |
| 149 | 151 | |
| 150 | 152 | case _URC_CONTINUE_UNWIND: |
| 151 | 153 | _LIBUNWIND_TRACE_UNWINDING( |
| 152 | "unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND", | |
| 154 | "unwind_phase1(ex_obj=%p): _URC_CONTINUE_UNWIND", | |
| 153 | 155 | (void *)exception_object); |
| 154 | 156 | // continue unwinding |
| 155 | 157 | break; |
| ... | ... | @@ -157,7 +159,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 157 | 159 | default: |
| 158 | 160 | // something went wrong |
| 159 | 161 | _LIBUNWIND_TRACE_UNWINDING( |
| 160 | "unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR", | |
| 162 | "unwind_phase1(ex_obj=%p): _URC_FATAL_PHASE1_ERROR", | |
| 161 | 163 | (void *)exception_object); |
| 162 | 164 | return _URC_FATAL_PHASE1_ERROR; |
| 163 | 165 | } |
| ... | ... | @@ -165,33 +167,36 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 165 | 167 | } |
| 166 | 168 | return _URC_NO_REASON; |
| 167 | 169 | } |
| 168 | ||
| 170 | extern int __unw_step_stage2(unw_cursor_t *); | |
| 169 | 171 | |
| 170 | 172 | static _Unwind_Reason_Code |
| 171 | 173 | unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) { |
| 172 | 174 | __unw_init_local(cursor, uc); |
| 173 | 175 | |
| 174 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)", | |
| 176 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p)", | |
| 175 | 177 | (void *)exception_object); |
| 176 | 178 | |
| 177 | 179 | // uc is initialized by __unw_getcontext in the parent frame. The first stack |
| 178 | 180 | // frame walked is unwind_phase2. |
| 179 | 181 | unsigned framesWalked = 1; |
| 182 | #ifdef _LIBUNWIND_USE_CET | |
| 183 | unsigned long shadowStackTop = _get_ssp(); | |
| 184 | #endif | |
| 180 | 185 | // Walk each frame until we reach where search phase said to stop. |
| 181 | 186 | while (true) { |
| 182 | 187 | |
| 183 | 188 | // Ask libunwind to get next frame (skip over first which is |
| 184 | 189 | // _Unwind_RaiseException). |
| 185 | int stepResult = __unw_step(cursor); | |
| 190 | int stepResult = __unw_step_stage2(cursor); | |
| 186 | 191 | if (stepResult == 0) { |
| 187 | 192 | _LIBUNWIND_TRACE_UNWINDING( |
| 188 | "unwind_phase2(ex_ojb=%p): __unw_step() reached " | |
| 193 | "unwind_phase2(ex_obj=%p): __unw_step_stage2() reached " | |
| 189 | 194 | "bottom => _URC_END_OF_STACK", |
| 190 | 195 | (void *)exception_object); |
| 191 | 196 | return _URC_END_OF_STACK; |
| 192 | 197 | } else if (stepResult < 0) { |
| 193 | 198 | _LIBUNWIND_TRACE_UNWINDING( |
| 194 | "unwind_phase2(ex_ojb=%p): __unw_step failed => " | |
| 199 | "unwind_phase2(ex_obj=%p): __unw_step_stage2 failed => " | |
| 195 | 200 | "_URC_FATAL_PHASE1_ERROR", |
| 196 | 201 | (void *)exception_object); |
| 197 | 202 | return _URC_FATAL_PHASE2_ERROR; |
| ... | ... | @@ -203,7 +208,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 203 | 208 | __unw_get_reg(cursor, UNW_REG_SP, &sp); |
| 204 | 209 | if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { |
| 205 | 210 | _LIBUNWIND_TRACE_UNWINDING( |
| 206 | "unwind_phase2(ex_ojb=%p): __unw_get_proc_info " | |
| 211 | "unwind_phase2(ex_obj=%p): __unw_get_proc_info " | |
| 207 | 212 | "failed => _URC_FATAL_PHASE1_ERROR", |
| 208 | 213 | (void *)exception_object); |
| 209 | 214 | return _URC_FATAL_PHASE2_ERROR; |
| ... | ... | @@ -219,7 +224,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 219 | 224 | &offset) != UNW_ESUCCESS) || |
| 220 | 225 | (frameInfo.start_ip + offset > frameInfo.end_ip)) |
| 221 | 226 | functionName = ".anonymous."; |
| 222 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIxPTR | |
| 227 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p): start_ip=0x%" PRIxPTR | |
| 223 | 228 | ", func=%s, sp=0x%" PRIxPTR ", lsda=0x%" PRIxPTR |
| 224 | 229 | ", personality=0x%" PRIxPTR, |
| 225 | 230 | (void *)exception_object, frameInfo.start_ip, |
| ... | ... | @@ -228,6 +233,20 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 228 | 233 | } |
| 229 | 234 | #endif |
| 230 | 235 | |
| 236 | // In CET enabled environment, we check return address stored in normal stack | |
| 237 | // against return address stored in CET shadow stack, if the 2 addresses don't | |
| 238 | // match, it means return address in normal stack has been corrupted, we return | |
| 239 | // _URC_FATAL_PHASE2_ERROR. | |
| 240 | #ifdef _LIBUNWIND_USE_CET | |
| 241 | if (shadowStackTop != 0) { | |
| 242 | unw_word_t retInNormalStack; | |
| 243 | __unw_get_reg(cursor, UNW_REG_IP, &retInNormalStack); | |
| 244 | unsigned long retInShadowStack = *( | |
| 245 | unsigned long *)(shadowStackTop + __cet_ss_step_size * framesWalked); | |
| 246 | if (retInNormalStack != retInShadowStack) | |
| 247 | return _URC_FATAL_PHASE2_ERROR; | |
| 248 | } | |
| 249 | #endif | |
| 231 | 250 | ++framesWalked; |
| 232 | 251 | // If there is a personality routine, tell it we are unwinding. |
| 233 | 252 | if (frameInfo.handler != 0) { |
| ... | ... | @@ -245,7 +264,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 245 | 264 | case _URC_CONTINUE_UNWIND: |
| 246 | 265 | // Continue unwinding |
| 247 | 266 | _LIBUNWIND_TRACE_UNWINDING( |
| 248 | "unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND", | |
| 267 | "unwind_phase2(ex_obj=%p): _URC_CONTINUE_UNWIND", | |
| 249 | 268 | (void *)exception_object); |
| 250 | 269 | if (sp == exception_object->private_2) { |
| 251 | 270 | // Phase 1 said we would stop at this frame, but we did not... |
| ... | ... | @@ -255,7 +274,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 255 | 274 | break; |
| 256 | 275 | case _URC_INSTALL_CONTEXT: |
| 257 | 276 | _LIBUNWIND_TRACE_UNWINDING( |
| 258 | "unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT", | |
| 277 | "unwind_phase2(ex_obj=%p): _URC_INSTALL_CONTEXT", | |
| 259 | 278 | (void *)exception_object); |
| 260 | 279 | // Personality routine says to transfer control to landing pad. |
| 261 | 280 | // We may get control back if landing pad calls _Unwind_Resume(). |
| ... | ... | @@ -263,7 +282,7 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 263 | 282 | unw_word_t pc; |
| 264 | 283 | __unw_get_reg(cursor, UNW_REG_IP, &pc); |
| 265 | 284 | __unw_get_reg(cursor, UNW_REG_SP, &sp); |
| 266 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering " | |
| 285 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_obj=%p): re-entering " | |
| 267 | 286 | "user code with ip=0x%" PRIxPTR |
| 268 | 287 | ", sp=0x%" PRIxPTR, |
| 269 | 288 | (void *)exception_object, pc, sp); |
| ... | ... | @@ -296,14 +315,15 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, |
| 296 | 315 | // frame walked is unwind_phase2_forced. |
| 297 | 316 | unsigned framesWalked = 1; |
| 298 | 317 | // Walk each frame until we reach where search phase said to stop |
| 299 | while (__unw_step(cursor) > 0) { | |
| 318 | while (__unw_step_stage2(cursor) > 0) { | |
| 300 | 319 | |
| 301 | 320 | // Update info about this frame. |
| 302 | 321 | unw_proc_info_t frameInfo; |
| 303 | 322 | if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) { |
| 304 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_step " | |
| 305 | "failed => _URC_END_OF_STACK", | |
| 306 | (void *)exception_object); | |
| 323 | _LIBUNWIND_TRACE_UNWINDING( | |
| 324 | "unwind_phase2_forced(ex_obj=%p): __unw_step_stage2 " | |
| 325 | "failed => _URC_END_OF_STACK", | |
| 326 | (void *)exception_object); | |
| 307 | 327 | return _URC_FATAL_PHASE2_ERROR; |
| 308 | 328 | } |
| 309 | 329 | |
| ... | ... | @@ -318,7 +338,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, |
| 318 | 338 | (frameInfo.start_ip + offset > frameInfo.end_ip)) |
| 319 | 339 | functionName = ".anonymous."; |
| 320 | 340 | _LIBUNWIND_TRACE_UNWINDING( |
| 321 | "unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIxPTR | |
| 341 | "unwind_phase2_forced(ex_obj=%p): start_ip=0x%" PRIxPTR | |
| 322 | 342 | ", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR, |
| 323 | 343 | (void *)exception_object, frameInfo.start_ip, functionName, |
| 324 | 344 | frameInfo.lsda, frameInfo.handler); |
| ... | ... | @@ -332,11 +352,11 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, |
| 332 | 352 | (*stop)(1, action, exception_object->exception_class, exception_object, |
| 333 | 353 | (struct _Unwind_Context *)(cursor), stop_parameter); |
| 334 | 354 | _LIBUNWIND_TRACE_UNWINDING( |
| 335 | "unwind_phase2_forced(ex_ojb=%p): stop function returned %d", | |
| 355 | "unwind_phase2_forced(ex_obj=%p): stop function returned %d", | |
| 336 | 356 | (void *)exception_object, stopResult); |
| 337 | 357 | if (stopResult != _URC_NO_REASON) { |
| 338 | 358 | _LIBUNWIND_TRACE_UNWINDING( |
| 339 | "unwind_phase2_forced(ex_ojb=%p): stopped by stop function", | |
| 359 | "unwind_phase2_forced(ex_obj=%p): stopped by stop function", | |
| 340 | 360 | (void *)exception_object); |
| 341 | 361 | return _URC_FATAL_PHASE2_ERROR; |
| 342 | 362 | } |
| ... | ... | @@ -347,21 +367,21 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, |
| 347 | 367 | _Unwind_Personality_Fn p = |
| 348 | 368 | (_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler); |
| 349 | 369 | _LIBUNWIND_TRACE_UNWINDING( |
| 350 | "unwind_phase2_forced(ex_ojb=%p): calling personality function %p", | |
| 370 | "unwind_phase2_forced(ex_obj=%p): calling personality function %p", | |
| 351 | 371 | (void *)exception_object, (void *)(uintptr_t)p); |
| 352 | 372 | _Unwind_Reason_Code personalityResult = |
| 353 | 373 | (*p)(1, action, exception_object->exception_class, exception_object, |
| 354 | 374 | (struct _Unwind_Context *)(cursor)); |
| 355 | 375 | switch (personalityResult) { |
| 356 | 376 | case _URC_CONTINUE_UNWIND: |
| 357 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " | |
| 377 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): " | |
| 358 | 378 | "personality returned " |
| 359 | 379 | "_URC_CONTINUE_UNWIND", |
| 360 | 380 | (void *)exception_object); |
| 361 | 381 | // Destructors called, continue unwinding |
| 362 | 382 | break; |
| 363 | 383 | case _URC_INSTALL_CONTEXT: |
| 364 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " | |
| 384 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): " | |
| 365 | 385 | "personality returned " |
| 366 | 386 | "_URC_INSTALL_CONTEXT", |
| 367 | 387 | (void *)exception_object); |
| ... | ... | @@ -370,7 +390,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, |
| 370 | 390 | break; |
| 371 | 391 | default: |
| 372 | 392 | // Personality routine returned an unknown result code. |
| 373 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " | |
| 393 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): " | |
| 374 | 394 | "personality returned %d, " |
| 375 | 395 | "_URC_FATAL_PHASE2_ERROR", |
| 376 | 396 | (void *)exception_object, personalityResult); |
| ... | ... | @@ -381,7 +401,7 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, |
| 381 | 401 | |
| 382 | 402 | // Call stop function one last time and tell it we've reached the end |
| 383 | 403 | // of the stack. |
| 384 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop " | |
| 404 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_obj=%p): calling stop " | |
| 385 | 405 | "function with _UA_END_OF_STACK", |
| 386 | 406 | (void *)exception_object); |
| 387 | 407 | _Unwind_Action lastAction = |
| ... | ... | @@ -425,7 +445,7 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) { |
| 425 | 445 | /// may force a jump to a landing pad in that function, the landing |
| 426 | 446 | /// pad code may then call _Unwind_Resume() to continue with the |
| 427 | 447 | /// unwinding. Note: the call to _Unwind_Resume() is from compiler |
| 428 | /// geneated user code. All other _Unwind_* routines are called | |
| 448 | /// generated user code. All other _Unwind_* routines are called | |
| 429 | 449 | /// by the C++ runtime __cxa_* routines. |
| 430 | 450 | /// |
| 431 | 451 | /// Note: re-throwing an exception (as opposed to continuing the unwind) |
lib/libunwind/src/UnwindRegistersRestore.S+55-136| ... | ... | @@ -8,6 +8,12 @@ |
| 8 | 8 | |
| 9 | 9 | #include "assembly.h" |
| 10 | 10 | |
| 11 | #define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 | |
| 12 | #define FROM_16_TO_31 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 | |
| 13 | ||
| 14 | #define FROM_0_TO_31 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 | |
| 15 | #define FROM_32_TO_63 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63 | |
| 16 | ||
| 11 | 17 | #if defined(_AIX) |
| 12 | 18 | .toc |
| 13 | 19 | #else |
| ... | ... | @@ -441,7 +447,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) |
| 441 | 447 | // thread_state pointer is in r3 |
| 442 | 448 | // |
| 443 | 449 | |
| 444 | // restore integral registerrs | |
| 450 | // restore integral registers | |
| 445 | 451 | // skip r0 for now |
| 446 | 452 | // skip r1 for now |
| 447 | 453 | lwz 2, 16(3) |
| ... | ... | @@ -1026,38 +1032,9 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv) |
| 1026 | 1032 | .set noreorder |
| 1027 | 1033 | .set nomacro |
| 1028 | 1034 | #ifdef __mips_hard_float |
| 1029 | ldc1 $f0, (8 * 35)($4) | |
| 1030 | ldc1 $f1, (8 * 36)($4) | |
| 1031 | ldc1 $f2, (8 * 37)($4) | |
| 1032 | ldc1 $f3, (8 * 38)($4) | |
| 1033 | ldc1 $f4, (8 * 39)($4) | |
| 1034 | ldc1 $f5, (8 * 40)($4) | |
| 1035 | ldc1 $f6, (8 * 41)($4) | |
| 1036 | ldc1 $f7, (8 * 42)($4) | |
| 1037 | ldc1 $f8, (8 * 43)($4) | |
| 1038 | ldc1 $f9, (8 * 44)($4) | |
| 1039 | ldc1 $f10, (8 * 45)($4) | |
| 1040 | ldc1 $f11, (8 * 46)($4) | |
| 1041 | ldc1 $f12, (8 * 47)($4) | |
| 1042 | ldc1 $f13, (8 * 48)($4) | |
| 1043 | ldc1 $f14, (8 * 49)($4) | |
| 1044 | ldc1 $f15, (8 * 50)($4) | |
| 1045 | ldc1 $f16, (8 * 51)($4) | |
| 1046 | ldc1 $f17, (8 * 52)($4) | |
| 1047 | ldc1 $f18, (8 * 53)($4) | |
| 1048 | ldc1 $f19, (8 * 54)($4) | |
| 1049 | ldc1 $f20, (8 * 55)($4) | |
| 1050 | ldc1 $f21, (8 * 56)($4) | |
| 1051 | ldc1 $f22, (8 * 57)($4) | |
| 1052 | ldc1 $f23, (8 * 58)($4) | |
| 1053 | ldc1 $f24, (8 * 59)($4) | |
| 1054 | ldc1 $f25, (8 * 60)($4) | |
| 1055 | ldc1 $f26, (8 * 61)($4) | |
| 1056 | ldc1 $f27, (8 * 62)($4) | |
| 1057 | ldc1 $f28, (8 * 63)($4) | |
| 1058 | ldc1 $f29, (8 * 64)($4) | |
| 1059 | ldc1 $f30, (8 * 65)($4) | |
| 1060 | ldc1 $f31, (8 * 66)($4) | |
| 1035 | .irp i,FROM_0_TO_31 | |
| 1036 | ldc1 $f\i, (280+8*\i)($4) | |
| 1037 | .endr | |
| 1061 | 1038 | #endif |
| 1062 | 1039 | // restore hi and lo |
| 1063 | 1040 | ld $8, (8 * 33)($4) |
| ... | ... | @@ -1069,32 +1046,9 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind21Registers_mips_newabi6jumptoEv) |
| 1069 | 1046 | ld $2, (8 * 2)($4) |
| 1070 | 1047 | ld $3, (8 * 3)($4) |
| 1071 | 1048 | // skip a0 for now |
| 1072 | ld $5, (8 * 5)($4) | |
| 1073 | ld $6, (8 * 6)($4) | |
| 1074 | ld $7, (8 * 7)($4) | |
| 1075 | ld $8, (8 * 8)($4) | |
| 1076 | ld $9, (8 * 9)($4) | |
| 1077 | ld $10, (8 * 10)($4) | |
| 1078 | ld $11, (8 * 11)($4) | |
| 1079 | ld $12, (8 * 12)($4) | |
| 1080 | ld $13, (8 * 13)($4) | |
| 1081 | ld $14, (8 * 14)($4) | |
| 1082 | ld $15, (8 * 15)($4) | |
| 1083 | ld $16, (8 * 16)($4) | |
| 1084 | ld $17, (8 * 17)($4) | |
| 1085 | ld $18, (8 * 18)($4) | |
| 1086 | ld $19, (8 * 19)($4) | |
| 1087 | ld $20, (8 * 20)($4) | |
| 1088 | ld $21, (8 * 21)($4) | |
| 1089 | ld $22, (8 * 22)($4) | |
| 1090 | ld $23, (8 * 23)($4) | |
| 1091 | ld $24, (8 * 24)($4) | |
| 1092 | ld $25, (8 * 25)($4) | |
| 1093 | ld $26, (8 * 26)($4) | |
| 1094 | ld $27, (8 * 27)($4) | |
| 1095 | ld $28, (8 * 28)($4) | |
| 1096 | ld $29, (8 * 29)($4) | |
| 1097 | ld $30, (8 * 30)($4) | |
| 1049 | .irp i,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 | |
| 1050 | ld $\i, (8 * \i)($4) | |
| 1051 | .endr | |
| 1098 | 1052 | // load new pc into ra |
| 1099 | 1053 | ld $31, (8 * 32)($4) |
| 1100 | 1054 | // jump to ra, load a0 in the delay slot |
| ... | ... | @@ -1182,72 +1136,20 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_sparc6jumptoEv) |
| 1182 | 1136 | .p2align 2 |
| 1183 | 1137 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv) |
| 1184 | 1138 | # if defined(__riscv_flen) |
| 1185 | FLOAD f0, (RISCV_FOFFSET + RISCV_FSIZE * 0)(a0) | |
| 1186 | FLOAD f1, (RISCV_FOFFSET + RISCV_FSIZE * 1)(a0) | |
| 1187 | FLOAD f2, (RISCV_FOFFSET + RISCV_FSIZE * 2)(a0) | |
| 1188 | FLOAD f3, (RISCV_FOFFSET + RISCV_FSIZE * 3)(a0) | |
| 1189 | FLOAD f4, (RISCV_FOFFSET + RISCV_FSIZE * 4)(a0) | |
| 1190 | FLOAD f5, (RISCV_FOFFSET + RISCV_FSIZE * 5)(a0) | |
| 1191 | FLOAD f6, (RISCV_FOFFSET + RISCV_FSIZE * 6)(a0) | |
| 1192 | FLOAD f7, (RISCV_FOFFSET + RISCV_FSIZE * 7)(a0) | |
| 1193 | FLOAD f8, (RISCV_FOFFSET + RISCV_FSIZE * 8)(a0) | |
| 1194 | FLOAD f9, (RISCV_FOFFSET + RISCV_FSIZE * 9)(a0) | |
| 1195 | FLOAD f10, (RISCV_FOFFSET + RISCV_FSIZE * 10)(a0) | |
| 1196 | FLOAD f11, (RISCV_FOFFSET + RISCV_FSIZE * 11)(a0) | |
| 1197 | FLOAD f12, (RISCV_FOFFSET + RISCV_FSIZE * 12)(a0) | |
| 1198 | FLOAD f13, (RISCV_FOFFSET + RISCV_FSIZE * 13)(a0) | |
| 1199 | FLOAD f14, (RISCV_FOFFSET + RISCV_FSIZE * 14)(a0) | |
| 1200 | FLOAD f15, (RISCV_FOFFSET + RISCV_FSIZE * 15)(a0) | |
| 1201 | FLOAD f16, (RISCV_FOFFSET + RISCV_FSIZE * 16)(a0) | |
| 1202 | FLOAD f17, (RISCV_FOFFSET + RISCV_FSIZE * 17)(a0) | |
| 1203 | FLOAD f18, (RISCV_FOFFSET + RISCV_FSIZE * 18)(a0) | |
| 1204 | FLOAD f19, (RISCV_FOFFSET + RISCV_FSIZE * 19)(a0) | |
| 1205 | FLOAD f20, (RISCV_FOFFSET + RISCV_FSIZE * 20)(a0) | |
| 1206 | FLOAD f21, (RISCV_FOFFSET + RISCV_FSIZE * 21)(a0) | |
| 1207 | FLOAD f22, (RISCV_FOFFSET + RISCV_FSIZE * 22)(a0) | |
| 1208 | FLOAD f23, (RISCV_FOFFSET + RISCV_FSIZE * 23)(a0) | |
| 1209 | FLOAD f24, (RISCV_FOFFSET + RISCV_FSIZE * 24)(a0) | |
| 1210 | FLOAD f25, (RISCV_FOFFSET + RISCV_FSIZE * 25)(a0) | |
| 1211 | FLOAD f26, (RISCV_FOFFSET + RISCV_FSIZE * 26)(a0) | |
| 1212 | FLOAD f27, (RISCV_FOFFSET + RISCV_FSIZE * 27)(a0) | |
| 1213 | FLOAD f28, (RISCV_FOFFSET + RISCV_FSIZE * 28)(a0) | |
| 1214 | FLOAD f29, (RISCV_FOFFSET + RISCV_FSIZE * 29)(a0) | |
| 1215 | FLOAD f30, (RISCV_FOFFSET + RISCV_FSIZE * 30)(a0) | |
| 1216 | FLOAD f31, (RISCV_FOFFSET + RISCV_FSIZE * 31)(a0) | |
| 1139 | .irp i,FROM_0_TO_31 | |
| 1140 | FLOAD f\i, (RISCV_FOFFSET + RISCV_FSIZE * \i)(a0) | |
| 1141 | .endr | |
| 1217 | 1142 | # endif |
| 1218 | 1143 | |
| 1219 | 1144 | // x0 is zero |
| 1220 | 1145 | ILOAD x1, (RISCV_ISIZE * 0)(a0) // restore pc into ra |
| 1221 | ILOAD x2, (RISCV_ISIZE * 2)(a0) | |
| 1222 | ILOAD x3, (RISCV_ISIZE * 3)(a0) | |
| 1223 | ILOAD x4, (RISCV_ISIZE * 4)(a0) | |
| 1224 | ILOAD x5, (RISCV_ISIZE * 5)(a0) | |
| 1225 | ILOAD x6, (RISCV_ISIZE * 6)(a0) | |
| 1226 | ILOAD x7, (RISCV_ISIZE * 7)(a0) | |
| 1227 | ILOAD x8, (RISCV_ISIZE * 8)(a0) | |
| 1228 | ILOAD x9, (RISCV_ISIZE * 9)(a0) | |
| 1146 | .irp i,2,3,4,5,6,7,8,9 | |
| 1147 | ILOAD x\i, (RISCV_ISIZE * \i)(a0) | |
| 1148 | .endr | |
| 1229 | 1149 | // skip a0 for now |
| 1230 | ILOAD x11, (RISCV_ISIZE * 11)(a0) | |
| 1231 | ILOAD x12, (RISCV_ISIZE * 12)(a0) | |
| 1232 | ILOAD x13, (RISCV_ISIZE * 13)(a0) | |
| 1233 | ILOAD x14, (RISCV_ISIZE * 14)(a0) | |
| 1234 | ILOAD x15, (RISCV_ISIZE * 15)(a0) | |
| 1235 | ILOAD x16, (RISCV_ISIZE * 16)(a0) | |
| 1236 | ILOAD x17, (RISCV_ISIZE * 17)(a0) | |
| 1237 | ILOAD x18, (RISCV_ISIZE * 18)(a0) | |
| 1238 | ILOAD x19, (RISCV_ISIZE * 19)(a0) | |
| 1239 | ILOAD x20, (RISCV_ISIZE * 20)(a0) | |
| 1240 | ILOAD x21, (RISCV_ISIZE * 21)(a0) | |
| 1241 | ILOAD x22, (RISCV_ISIZE * 22)(a0) | |
| 1242 | ILOAD x23, (RISCV_ISIZE * 23)(a0) | |
| 1243 | ILOAD x24, (RISCV_ISIZE * 24)(a0) | |
| 1244 | ILOAD x25, (RISCV_ISIZE * 25)(a0) | |
| 1245 | ILOAD x26, (RISCV_ISIZE * 26)(a0) | |
| 1246 | ILOAD x27, (RISCV_ISIZE * 27)(a0) | |
| 1247 | ILOAD x28, (RISCV_ISIZE * 28)(a0) | |
| 1248 | ILOAD x29, (RISCV_ISIZE * 29)(a0) | |
| 1249 | ILOAD x30, (RISCV_ISIZE * 30)(a0) | |
| 1250 | ILOAD x31, (RISCV_ISIZE * 31)(a0) | |
| 1150 | .irp i,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 | |
| 1151 | ILOAD x\i, (RISCV_ISIZE * \i)(a0) | |
| 1152 | .endr | |
| 1251 | 1153 | ILOAD x10, (RISCV_ISIZE * 10)(a0) // restore a0 |
| 1252 | 1154 | |
| 1253 | 1155 | ret // jump to ra |
| ... | ... | @@ -1266,22 +1168,9 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_s390x6jumptoEv) |
| 1266 | 1168 | lg %r1, 8(%r2) |
| 1267 | 1169 | |
| 1268 | 1170 | // 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) | |
| 1171 | .irp i,FROM_0_TO_15 | |
| 1172 | ld %f\i, (144+8*\i)(%r2) | |
| 1173 | .endr | |
| 1285 | 1174 | |
| 1286 | 1175 | // Restore GPRs - skipping %r0 and %r1 |
| 1287 | 1176 | lmg %r2, %r15, 32(%r2) |
| ... | ... | @@ -1289,6 +1178,36 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_s390x6jumptoEv) |
| 1289 | 1178 | // Return to PSWA (was loaded into %r1 above) |
| 1290 | 1179 | br %r1 |
| 1291 | 1180 | |
| 1181 | #elif defined(__loongarch__) && __loongarch_grlen == 64 | |
| 1182 | ||
| 1183 | // | |
| 1184 | // void libunwind::Registers_loongarch::jumpto() | |
| 1185 | // | |
| 1186 | // On entry: | |
| 1187 | // thread_state pointer is in $a0($r4) | |
| 1188 | // | |
| 1189 | .p2align 2 | |
| 1190 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind19Registers_loongarch6jumptoEv) | |
| 1191 | # if __loongarch_frlen == 64 | |
| 1192 | .irp i,FROM_0_TO_31 | |
| 1193 | fld.d $f\i, $a0, (8 * 33 + 8 * \i) | |
| 1194 | .endr | |
| 1195 | # endif | |
| 1196 | ||
| 1197 | // $r0 is zero | |
| 1198 | .irp i,1,2,3 | |
| 1199 | ld.d $r\i, $a0, (8 * \i) | |
| 1200 | .endr | |
| 1201 | // skip $a0 for now | |
| 1202 | .irp i,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 | |
| 1203 | ld.d $r\i, $a0, (8 * \i) | |
| 1204 | .endr | |
| 1205 | ||
| 1206 | ld.d $r4, $a0, (8 * 4) // restore $a0 last | |
| 1207 | ld.d $r1, $a0, (8 * 32) // load new pc into $ra | |
| 1208 | ||
| 1209 | jr $ra | |
| 1210 | ||
| 1292 | 1211 | #endif |
| 1293 | 1212 | |
| 1294 | 1213 | #endif /* !defined(__USING_SJLJ_EXCEPTIONS__) */ |
lib/libunwind/src/UnwindRegistersSave.S+44-142| ... | ... | @@ -8,6 +8,12 @@ |
| 8 | 8 | |
| 9 | 9 | #include "assembly.h" |
| 10 | 10 | |
| 11 | #define FROM_0_TO_15 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 | |
| 12 | #define FROM_16_TO_31 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 | |
| 13 | ||
| 14 | #define FROM_0_TO_31 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 | |
| 15 | #define FROM_32_TO_63 32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63 | |
| 16 | ||
| 11 | 17 | #if defined(_AIX) |
| 12 | 18 | .toc |
| 13 | 19 | #else |
| ... | ... | @@ -244,37 +250,9 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 244 | 250 | .set noat |
| 245 | 251 | .set noreorder |
| 246 | 252 | .set nomacro |
| 247 | sd $1, (8 * 1)($4) | |
| 248 | sd $2, (8 * 2)($4) | |
| 249 | sd $3, (8 * 3)($4) | |
| 250 | sd $4, (8 * 4)($4) | |
| 251 | sd $5, (8 * 5)($4) | |
| 252 | sd $6, (8 * 6)($4) | |
| 253 | sd $7, (8 * 7)($4) | |
| 254 | sd $8, (8 * 8)($4) | |
| 255 | sd $9, (8 * 9)($4) | |
| 256 | sd $10, (8 * 10)($4) | |
| 257 | sd $11, (8 * 11)($4) | |
| 258 | sd $12, (8 * 12)($4) | |
| 259 | sd $13, (8 * 13)($4) | |
| 260 | sd $14, (8 * 14)($4) | |
| 261 | sd $15, (8 * 15)($4) | |
| 262 | sd $16, (8 * 16)($4) | |
| 263 | sd $17, (8 * 17)($4) | |
| 264 | sd $18, (8 * 18)($4) | |
| 265 | sd $19, (8 * 19)($4) | |
| 266 | sd $20, (8 * 20)($4) | |
| 267 | sd $21, (8 * 21)($4) | |
| 268 | sd $22, (8 * 22)($4) | |
| 269 | sd $23, (8 * 23)($4) | |
| 270 | sd $24, (8 * 24)($4) | |
| 271 | sd $25, (8 * 25)($4) | |
| 272 | sd $26, (8 * 26)($4) | |
| 273 | sd $27, (8 * 27)($4) | |
| 274 | sd $28, (8 * 28)($4) | |
| 275 | sd $29, (8 * 29)($4) | |
| 276 | sd $30, (8 * 30)($4) | |
| 277 | sd $31, (8 * 31)($4) | |
| 253 | .irp i,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 | |
| 254 | sd $\i, (8 * \i)($4) | |
| 255 | .endr | |
| 278 | 256 | # Store return address to pc |
| 279 | 257 | sd $31, (8 * 32)($4) |
| 280 | 258 | # hi and lo |
| ... | ... | @@ -283,38 +261,9 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 283 | 261 | mflo $8 |
| 284 | 262 | sd $8, (8 * 34)($4) |
| 285 | 263 | #ifdef __mips_hard_float |
| 286 | sdc1 $f0, (8 * 35)($4) | |
| 287 | sdc1 $f1, (8 * 36)($4) | |
| 288 | sdc1 $f2, (8 * 37)($4) | |
| 289 | sdc1 $f3, (8 * 38)($4) | |
| 290 | sdc1 $f4, (8 * 39)($4) | |
| 291 | sdc1 $f5, (8 * 40)($4) | |
| 292 | sdc1 $f6, (8 * 41)($4) | |
| 293 | sdc1 $f7, (8 * 42)($4) | |
| 294 | sdc1 $f8, (8 * 43)($4) | |
| 295 | sdc1 $f9, (8 * 44)($4) | |
| 296 | sdc1 $f10, (8 * 45)($4) | |
| 297 | sdc1 $f11, (8 * 46)($4) | |
| 298 | sdc1 $f12, (8 * 47)($4) | |
| 299 | sdc1 $f13, (8 * 48)($4) | |
| 300 | sdc1 $f14, (8 * 49)($4) | |
| 301 | sdc1 $f15, (8 * 50)($4) | |
| 302 | sdc1 $f16, (8 * 51)($4) | |
| 303 | sdc1 $f17, (8 * 52)($4) | |
| 304 | sdc1 $f18, (8 * 53)($4) | |
| 305 | sdc1 $f19, (8 * 54)($4) | |
| 306 | sdc1 $f20, (8 * 55)($4) | |
| 307 | sdc1 $f21, (8 * 56)($4) | |
| 308 | sdc1 $f22, (8 * 57)($4) | |
| 309 | sdc1 $f23, (8 * 58)($4) | |
| 310 | sdc1 $f24, (8 * 59)($4) | |
| 311 | sdc1 $f25, (8 * 60)($4) | |
| 312 | sdc1 $f26, (8 * 61)($4) | |
| 313 | sdc1 $f27, (8 * 62)($4) | |
| 314 | sdc1 $f28, (8 * 63)($4) | |
| 315 | sdc1 $f29, (8 * 64)($4) | |
| 316 | sdc1 $f30, (8 * 65)($4) | |
| 317 | sdc1 $f31, (8 * 66)($4) | |
| 264 | .irp i,FROM_0_TO_31 | |
| 265 | sdc1 $f\i, (280+8*\i)($4) | |
| 266 | .endr | |
| 318 | 267 | #endif |
| 319 | 268 | jr	$31 |
| 320 | 269 | # return UNW_ESUCCESS |
| ... | ... | @@ -1110,71 +1059,14 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 1110 | 1059 | # |
| 1111 | 1060 | DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 1112 | 1061 | ISTORE x1, (RISCV_ISIZE * 0)(a0) // store ra as pc |
| 1113 | ISTORE x1, (RISCV_ISIZE * 1)(a0) | |
| 1114 | ISTORE x2, (RISCV_ISIZE * 2)(a0) | |
| 1115 | ISTORE x3, (RISCV_ISIZE * 3)(a0) | |
| 1116 | ISTORE x4, (RISCV_ISIZE * 4)(a0) | |
| 1117 | ISTORE x5, (RISCV_ISIZE * 5)(a0) | |
| 1118 | ISTORE x6, (RISCV_ISIZE * 6)(a0) | |
| 1119 | ISTORE x7, (RISCV_ISIZE * 7)(a0) | |
| 1120 | ISTORE x8, (RISCV_ISIZE * 8)(a0) | |
| 1121 | ISTORE x9, (RISCV_ISIZE * 9)(a0) | |
| 1122 | ISTORE x10, (RISCV_ISIZE * 10)(a0) | |
| 1123 | ISTORE x11, (RISCV_ISIZE * 11)(a0) | |
| 1124 | ISTORE x12, (RISCV_ISIZE * 12)(a0) | |
| 1125 | ISTORE x13, (RISCV_ISIZE * 13)(a0) | |
| 1126 | ISTORE x14, (RISCV_ISIZE * 14)(a0) | |
| 1127 | ISTORE x15, (RISCV_ISIZE * 15)(a0) | |
| 1128 | ISTORE x16, (RISCV_ISIZE * 16)(a0) | |
| 1129 | ISTORE x17, (RISCV_ISIZE * 17)(a0) | |
| 1130 | ISTORE x18, (RISCV_ISIZE * 18)(a0) | |
| 1131 | ISTORE x19, (RISCV_ISIZE * 19)(a0) | |
| 1132 | ISTORE x20, (RISCV_ISIZE * 20)(a0) | |
| 1133 | ISTORE x21, (RISCV_ISIZE * 21)(a0) | |
| 1134 | ISTORE x22, (RISCV_ISIZE * 22)(a0) | |
| 1135 | ISTORE x23, (RISCV_ISIZE * 23)(a0) | |
| 1136 | ISTORE x24, (RISCV_ISIZE * 24)(a0) | |
| 1137 | ISTORE x25, (RISCV_ISIZE * 25)(a0) | |
| 1138 | ISTORE x26, (RISCV_ISIZE * 26)(a0) | |
| 1139 | ISTORE x27, (RISCV_ISIZE * 27)(a0) | |
| 1140 | ISTORE x28, (RISCV_ISIZE * 28)(a0) | |
| 1141 | ISTORE x29, (RISCV_ISIZE * 29)(a0) | |
| 1142 | ISTORE x30, (RISCV_ISIZE * 30)(a0) | |
| 1143 | ISTORE x31, (RISCV_ISIZE * 31)(a0) | |
| 1062 | .irp i,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 | |
| 1063 | ISTORE x\i, (RISCV_ISIZE * \i)(a0) | |
| 1064 | .endr | |
| 1144 | 1065 | |
| 1145 | 1066 | # if defined(__riscv_flen) |
| 1146 | FSTORE f0, (RISCV_FOFFSET + RISCV_FSIZE * 0)(a0) | |
| 1147 | FSTORE f1, (RISCV_FOFFSET + RISCV_FSIZE * 1)(a0) | |
| 1148 | FSTORE f2, (RISCV_FOFFSET + RISCV_FSIZE * 2)(a0) | |
| 1149 | FSTORE f3, (RISCV_FOFFSET + RISCV_FSIZE * 3)(a0) | |
| 1150 | FSTORE f4, (RISCV_FOFFSET + RISCV_FSIZE * 4)(a0) | |
| 1151 | FSTORE f5, (RISCV_FOFFSET + RISCV_FSIZE * 5)(a0) | |
| 1152 | FSTORE f6, (RISCV_FOFFSET + RISCV_FSIZE * 6)(a0) | |
| 1153 | FSTORE f7, (RISCV_FOFFSET + RISCV_FSIZE * 7)(a0) | |
| 1154 | FSTORE f8, (RISCV_FOFFSET + RISCV_FSIZE * 8)(a0) | |
| 1155 | FSTORE f9, (RISCV_FOFFSET + RISCV_FSIZE * 9)(a0) | |
| 1156 | FSTORE f10, (RISCV_FOFFSET + RISCV_FSIZE * 10)(a0) | |
| 1157 | FSTORE f11, (RISCV_FOFFSET + RISCV_FSIZE * 11)(a0) | |
| 1158 | FSTORE f12, (RISCV_FOFFSET + RISCV_FSIZE * 12)(a0) | |
| 1159 | FSTORE f13, (RISCV_FOFFSET + RISCV_FSIZE * 13)(a0) | |
| 1160 | FSTORE f14, (RISCV_FOFFSET + RISCV_FSIZE * 14)(a0) | |
| 1161 | FSTORE f15, (RISCV_FOFFSET + RISCV_FSIZE * 15)(a0) | |
| 1162 | FSTORE f16, (RISCV_FOFFSET + RISCV_FSIZE * 16)(a0) | |
| 1163 | FSTORE f17, (RISCV_FOFFSET + RISCV_FSIZE * 17)(a0) | |
| 1164 | FSTORE f18, (RISCV_FOFFSET + RISCV_FSIZE * 18)(a0) | |
| 1165 | FSTORE f19, (RISCV_FOFFSET + RISCV_FSIZE * 19)(a0) | |
| 1166 | FSTORE f20, (RISCV_FOFFSET + RISCV_FSIZE * 20)(a0) | |
| 1167 | FSTORE f21, (RISCV_FOFFSET + RISCV_FSIZE * 21)(a0) | |
| 1168 | FSTORE f22, (RISCV_FOFFSET + RISCV_FSIZE * 22)(a0) | |
| 1169 | FSTORE f23, (RISCV_FOFFSET + RISCV_FSIZE * 23)(a0) | |
| 1170 | FSTORE f24, (RISCV_FOFFSET + RISCV_FSIZE * 24)(a0) | |
| 1171 | FSTORE f25, (RISCV_FOFFSET + RISCV_FSIZE * 25)(a0) | |
| 1172 | FSTORE f26, (RISCV_FOFFSET + RISCV_FSIZE * 26)(a0) | |
| 1173 | FSTORE f27, (RISCV_FOFFSET + RISCV_FSIZE * 27)(a0) | |
| 1174 | FSTORE f28, (RISCV_FOFFSET + RISCV_FSIZE * 28)(a0) | |
| 1175 | FSTORE f29, (RISCV_FOFFSET + RISCV_FSIZE * 29)(a0) | |
| 1176 | FSTORE f30, (RISCV_FOFFSET + RISCV_FSIZE * 30)(a0) | |
| 1177 | FSTORE f31, (RISCV_FOFFSET + RISCV_FSIZE * 31)(a0) | |
| 1067 | .irp i,FROM_0_TO_31 | |
| 1068 | FSTORE f\i, (RISCV_FOFFSET + RISCV_FSIZE * \i)(a0) | |
| 1069 | .endr | |
| 1178 | 1070 | # endif |
| 1179 | 1071 | |
| 1180 | 1072 | li a0, 0 // return UNW_ESUCCESS |
| ... | ... | @@ -1201,27 +1093,37 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 1201 | 1093 | stg %r14, 8(%r2) |
| 1202 | 1094 | |
| 1203 | 1095 | // 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) | |
| 1096 | .irp i,FROM_0_TO_15 | |
| 1097 | std %f\i, (144+8*\i)(%r2) | |
| 1098 | .endr | |
| 1220 | 1099 | |
| 1221 | 1100 | // Return UNW_ESUCCESS |
| 1222 | 1101 | lghi %r2, 0 |
| 1223 | 1102 | br %r14 |
| 1224 | 1103 | |
| 1104 | #elif defined(__loongarch__) && __loongarch_grlen == 64 | |
| 1105 | ||
| 1106 | # | |
| 1107 | # extern int __unw_getcontext(unw_context_t* thread_state) | |
| 1108 | # | |
| 1109 | # On entry: | |
| 1110 | # thread_state pointer is in $a0($r4) | |
| 1111 | # | |
| 1112 | DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) | |
| 1113 | .irp i,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 | |
| 1114 | st.d $r\i, $a0, (8*\i) | |
| 1115 | .endr | |
| 1116 | st.d $r1, $a0, (8 * 32) // store $ra to pc | |
| 1117 | ||
| 1118 | # if __loongarch_frlen == 64 | |
| 1119 | .irp i,FROM_0_TO_31 | |
| 1120 | fst.d $f\i, $a0, (8 * 33 + 8 * \i) | |
| 1121 | .endr | |
| 1122 | # endif | |
| 1123 | ||
| 1124 | move $a0, $zero // UNW_ESUCCESS | |
| 1125 | jr $ra | |
| 1126 | ||
| 1225 | 1127 | #endif |
| 1226 | 1128 | |
| 1227 | 1129 | WEAK_ALIAS(__unw_getcontext, unw_getcontext) |
lib/libunwind/src/Unwind_AIXExtras.cpp+1-1| ... | ... | @@ -38,7 +38,7 @@ char *getFuncNameFromTBTable(uintptr_t Pc, uint16_t &NameLen, |
| 38 | 38 | if (TBTable->tb.fixedparms || TBTable->tb.floatparms) |
| 39 | 39 | p++; |
| 40 | 40 | |
| 41 | // If the tb_offset field exisits, get the offset from the start of | |
| 41 | // If the tb_offset field exists, get the offset from the start of | |
| 42 | 42 | // the function to pc. Skip the field. |
| 43 | 43 | if (TBTable->tb.has_tboff) { |
| 44 | 44 | unw_word_t StartIp = |
lib/libunwind/src/config.h+1-1| ... | ... | @@ -115,7 +115,7 @@ |
| 115 | 115 | #if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || \ |
| 116 | 116 | (!defined(__APPLE__) && defined(__arm__)) || defined(__aarch64__) || \ |
| 117 | 117 | defined(__mips__) || defined(__riscv) || defined(__hexagon__) || \ |
| 118 | defined(__sparc__) || defined(__s390x__) | |
| 118 | defined(__sparc__) || defined(__s390x__) || defined(__loongarch__) | |
| 119 | 119 | #if !defined(_LIBUNWIND_BUILD_SJLJ_APIS) |
| 120 | 120 | #define _LIBUNWIND_BUILD_ZERO_COST_APIS |
| 121 | 121 | #endif |
lib/libunwind/src/libunwind.cpp+12-1| ... | ... | @@ -77,6 +77,8 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor, |
| 77 | 77 | # define REGISTER_KIND Registers_ve |
| 78 | 78 | #elif defined(__s390x__) |
| 79 | 79 | # define REGISTER_KIND Registers_s390x |
| 80 | #elif defined(__loongarch__) && __loongarch_grlen == 64 | |
| 81 | #define REGISTER_KIND Registers_loongarch | |
| 80 | 82 | #else |
| 81 | 83 | # error Architecture not supported |
| 82 | 84 | #endif |
| ... | ... | @@ -117,7 +119,7 @@ _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum, |
| 117 | 119 | AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; |
| 118 | 120 | if (co->validReg(regNum)) { |
| 119 | 121 | co->setReg(regNum, (pint_t)value); |
| 120 | // specical case altering IP to re-find info (being called by personality | |
| 122 | // special case altering IP to re-find info (being called by personality | |
| 121 | 123 | // function) |
| 122 | 124 | if (regNum == UNW_REG_IP) { |
| 123 | 125 | unw_proc_info_t info; |
| ... | ... | @@ -181,6 +183,15 @@ _LIBUNWIND_HIDDEN int __unw_step(unw_cursor_t *cursor) { |
| 181 | 183 | } |
| 182 | 184 | _LIBUNWIND_WEAK_ALIAS(__unw_step, unw_step) |
| 183 | 185 | |
| 186 | // Move cursor to next frame and for stage2 of unwinding. | |
| 187 | // This resets MTE tags of tagged frames to zero. | |
| 188 | extern "C" _LIBUNWIND_HIDDEN int __unw_step_stage2(unw_cursor_t *cursor) { | |
| 189 | _LIBUNWIND_TRACE_API("__unw_step_stage2(cursor=%p)", | |
| 190 | static_cast<void *>(cursor)); | |
| 191 | AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor; | |
| 192 | return co->step(true); | |
| 193 | } | |
| 194 | ||
| 184 | 195 | /// Get unwind info at cursor position in stack frame. |
| 185 | 196 | _LIBUNWIND_HIDDEN int __unw_get_proc_info(unw_cursor_t *cursor, |
| 186 | 197 | unw_proc_info_t *info) { |