| author | |
| committer | |
| log | 372062b4fe148c17a42ff0938781748ca1dc8328 |
| tree | 099c03a994ffe8a502cbe82281b5ae15e738760c |
| parent | 42da1d385de8559710e04b5a05234f2dd8bb347e |
20 files changed, 804 insertions(+), 196 deletions(-)
lib/libunwind/include/__libunwind_config.h+8| ... | @@ -23,6 +23,7 @@ | ... | @@ -23,6 +23,7 @@ |
| 23 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K 32 | 23 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K 32 |
| 24 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS 65 | 24 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS 65 |
| 25 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC 31 | 25 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC 31 |
| 26 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON 34 | ||
| 26 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 64 | 27 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 64 |
| 27 | 28 | ||
| 28 | #if defined(_LIBUNWIND_IS_NATIVE_ONLY) | 29 | #if defined(_LIBUNWIND_IS_NATIVE_ONLY) |
| ... | @@ -82,6 +83,12 @@ | ... | @@ -82,6 +83,12 @@ |
| 82 | # define _LIBUNWIND_CONTEXT_SIZE 16 | 83 | # define _LIBUNWIND_CONTEXT_SIZE 16 |
| 83 | # define _LIBUNWIND_CURSOR_SIZE 24 | 84 | # define _LIBUNWIND_CURSOR_SIZE 24 |
| 84 | # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K | 85 | # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K |
| 86 | # elif defined(__hexagon__) | ||
| 87 | # define _LIBUNWIND_TARGET_HEXAGON 1 | ||
| 88 | // Values here change when : Registers.hpp - hexagon_thread_state_t change | ||
| 89 | # define _LIBUNWIND_CONTEXT_SIZE 18 | ||
| 90 | # define _LIBUNWIND_CURSOR_SIZE 24 | ||
| 91 | # define _LIBUNWIND_HIGHEST_DWARF_REGISTER _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON | ||
| 85 | # elif defined(__mips__) | 92 | # elif defined(__mips__) |
| 86 | # if defined(_ABIO32) && _MIPS_SIM == _ABIO32 | 93 | # if defined(_ABIO32) && _MIPS_SIM == _ABIO32 |
| 87 | # define _LIBUNWIND_TARGET_MIPS_O32 1 | 94 | # define _LIBUNWIND_TARGET_MIPS_O32 1 |
| ... | @@ -142,6 +149,7 @@ | ... | @@ -142,6 +149,7 @@ |
| 142 | # define _LIBUNWIND_TARGET_MIPS_O32 1 | 149 | # define _LIBUNWIND_TARGET_MIPS_O32 1 |
| 143 | # define _LIBUNWIND_TARGET_MIPS_NEWABI 1 | 150 | # define _LIBUNWIND_TARGET_MIPS_NEWABI 1 |
| 144 | # define _LIBUNWIND_TARGET_SPARC 1 | 151 | # define _LIBUNWIND_TARGET_SPARC 1 |
| 152 | # define _LIBUNWIND_TARGET_HEXAGON 1 | ||
| 145 | # define _LIBUNWIND_TARGET_RISCV 1 | 153 | # define _LIBUNWIND_TARGET_RISCV 1 |
| 146 | # define _LIBUNWIND_CONTEXT_SIZE 167 | 154 | # define _LIBUNWIND_CONTEXT_SIZE 167 |
| 147 | # define _LIBUNWIND_CURSOR_SIZE 179 | 155 | # define _LIBUNWIND_CURSOR_SIZE 179 |
lib/libunwind/include/libunwind.h+38| ... | @@ -832,6 +832,44 @@ enum { | ... | @@ -832,6 +832,44 @@ enum { |
| 832 | UNW_SPARC_I7 = 31, | 832 | UNW_SPARC_I7 = 31, |
| 833 | }; | 833 | }; |
| 834 | 834 | ||
| 835 | // Hexagon register numbers | ||
| 836 | enum { | ||
| 837 | UNW_HEXAGON_R0, | ||
| 838 | UNW_HEXAGON_R1, | ||
| 839 | UNW_HEXAGON_R2, | ||
| 840 | UNW_HEXAGON_R3, | ||
| 841 | UNW_HEXAGON_R4, | ||
| 842 | UNW_HEXAGON_R5, | ||
| 843 | UNW_HEXAGON_R6, | ||
| 844 | UNW_HEXAGON_R7, | ||
| 845 | UNW_HEXAGON_R8, | ||
| 846 | UNW_HEXAGON_R9, | ||
| 847 | UNW_HEXAGON_R10, | ||
| 848 | UNW_HEXAGON_R11, | ||
| 849 | UNW_HEXAGON_R12, | ||
| 850 | UNW_HEXAGON_R13, | ||
| 851 | UNW_HEXAGON_R14, | ||
| 852 | UNW_HEXAGON_R15, | ||
| 853 | UNW_HEXAGON_R16, | ||
| 854 | UNW_HEXAGON_R17, | ||
| 855 | UNW_HEXAGON_R18, | ||
| 856 | UNW_HEXAGON_R19, | ||
| 857 | UNW_HEXAGON_R20, | ||
| 858 | UNW_HEXAGON_R21, | ||
| 859 | UNW_HEXAGON_R22, | ||
| 860 | UNW_HEXAGON_R23, | ||
| 861 | UNW_HEXAGON_R24, | ||
| 862 | UNW_HEXAGON_R25, | ||
| 863 | UNW_HEXAGON_R26, | ||
| 864 | UNW_HEXAGON_R27, | ||
| 865 | UNW_HEXAGON_R28, | ||
| 866 | UNW_HEXAGON_R29, | ||
| 867 | UNW_HEXAGON_R30, | ||
| 868 | UNW_HEXAGON_R31, | ||
| 869 | UNW_HEXAGON_P3_0, | ||
| 870 | UNW_HEXAGON_PC, | ||
| 871 | }; | ||
| 872 | |||
| 835 | // RISC-V registers. These match the DWARF register numbers defined by section | 873 | // RISC-V registers. These match the DWARF register numbers defined by section |
| 836 | // 4 of the RISC-V ELF psABI specification, which can be found at: | 874 | // 4 of the RISC-V ELF psABI specification, which can be found at: |
| 837 | // | 875 | // |
lib/libunwind/include/unwind.h+8-13| ... | @@ -111,10 +111,9 @@ typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) | ... | @@ -111,10 +111,9 @@ typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) |
| 111 | _Unwind_Exception* exceptionObject, | 111 | _Unwind_Exception* exceptionObject, |
| 112 | struct _Unwind_Context* context); | 112 | struct _Unwind_Context* context); |
| 113 | 113 | ||
| 114 | typedef _Unwind_Reason_Code (*__personality_routine) | 114 | typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)( |
| 115 | (_Unwind_State state, | 115 | _Unwind_State state, _Unwind_Exception *exceptionObject, |
| 116 | _Unwind_Exception* exceptionObject, | 116 | struct _Unwind_Context *context); |
| 117 | struct _Unwind_Context* context); | ||
| 118 | #else | 117 | #else |
| 119 | struct _Unwind_Context; // opaque | 118 | struct _Unwind_Context; // opaque |
| 120 | struct _Unwind_Exception; // forward declaration | 119 | struct _Unwind_Exception; // forward declaration |
| ... | @@ -150,12 +149,9 @@ typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) | ... | @@ -150,12 +149,9 @@ typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) |
| 150 | struct _Unwind_Context* context, | 149 | struct _Unwind_Context* context, |
| 151 | void* stop_parameter ); | 150 | void* stop_parameter ); |
| 152 | 151 | ||
| 153 | typedef _Unwind_Reason_Code (*__personality_routine) | 152 | typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)( |
| 154 | (int version, | 153 | int version, _Unwind_Action actions, uint64_t exceptionClass, |
| 155 | _Unwind_Action actions, | 154 | _Unwind_Exception *exceptionObject, struct _Unwind_Context *context); |
| 156 | uint64_t exceptionClass, | ||
| 157 | _Unwind_Exception* exceptionObject, | ||
| 158 | struct _Unwind_Context* context); | ||
| 159 | #endif | 155 | #endif |
| 160 | 156 | ||
| 161 | #ifdef __cplusplus | 157 | #ifdef __cplusplus |
| ... | @@ -387,10 +383,9 @@ typedef struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT; | ... | @@ -387,10 +383,9 @@ typedef struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT; |
| 387 | #endif | 383 | #endif |
| 388 | // This is the common wrapper for GCC-style personality functions with SEH. | 384 | // This is the common wrapper for GCC-style personality functions with SEH. |
| 389 | extern EXCEPTION_DISPOSITION _GCC_specific_handler(EXCEPTION_RECORD *exc, | 385 | extern EXCEPTION_DISPOSITION _GCC_specific_handler(EXCEPTION_RECORD *exc, |
| 390 | void *frame, | 386 | void *frame, CONTEXT *ctx, |
| 391 | CONTEXT *ctx, | ||
| 392 | DISPATCHER_CONTEXT *disp, | 387 | DISPATCHER_CONTEXT *disp, |
| 393 | __personality_routine pers); | 388 | _Unwind_Personality_Fn pers); |
| 394 | #endif | 389 | #endif |
| 395 | 390 | ||
| 396 | #ifdef __cplusplus | 391 | #ifdef __cplusplus |
lib/libunwind/src/AddressSpace.hpp+159-103| ... | @@ -392,6 +392,164 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, | ... | @@ -392,6 +392,164 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, |
| 392 | return result; | 392 | return result; |
| 393 | } | 393 | } |
| 394 | 394 | ||
| 395 | #ifdef __APPLE__ | ||
| 396 | #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) | ||
| 397 | #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) | ||
| 398 | #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32) | ||
| 399 | #elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32) | ||
| 400 | #elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) | ||
| 401 | // Code inside findUnwindSections handles all these cases. | ||
| 402 | // | ||
| 403 | // Although the above ifdef chain is ugly, there doesn't seem to be a cleaner | ||
| 404 | // way to handle it. The generalized boolean expression is: | ||
| 405 | // | ||
| 406 | // A OR (B AND C) OR (D AND C) OR (B AND E) OR (F AND E) OR (D AND G) | ||
| 407 | // | ||
| 408 | // Running it through various boolean expression simplifiers gives expressions | ||
| 409 | // that don't help at all. | ||
| 410 | #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | ||
| 411 | |||
| 412 | #if !defined(Elf_Half) | ||
| 413 | typedef ElfW(Half) Elf_Half; | ||
| 414 | #endif | ||
| 415 | #if !defined(Elf_Phdr) | ||
| 416 | typedef ElfW(Phdr) Elf_Phdr; | ||
| 417 | #endif | ||
| 418 | #if !defined(Elf_Addr) | ||
| 419 | typedef ElfW(Addr) Elf_Addr; | ||
| 420 | #endif | ||
| 421 | |||
| 422 | static Elf_Addr calculateImageBase(struct dl_phdr_info *pinfo) { | ||
| 423 | Elf_Addr image_base = pinfo->dlpi_addr; | ||
| 424 | #if defined(__ANDROID__) && __ANDROID_API__ < 18 | ||
| 425 | if (image_base == 0) { | ||
| 426 | // Normally, an image base of 0 indicates a non-PIE executable. On | ||
| 427 | // versions of Android prior to API 18, the dynamic linker reported a | ||
| 428 | // dlpi_addr of 0 for PIE executables. Compute the true image base | ||
| 429 | // using the PT_PHDR segment. | ||
| 430 | // See https://github.com/android/ndk/issues/505. | ||
| 431 | for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { | ||
| 432 | const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; | ||
| 433 | if (phdr->p_type == PT_PHDR) { | ||
| 434 | image_base = reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) - | ||
| 435 | phdr->p_vaddr; | ||
| 436 | break; | ||
| 437 | } | ||
| 438 | } | ||
| 439 | } | ||
| 440 | #endif | ||
| 441 | return image_base; | ||
| 442 | } | ||
| 443 | |||
| 444 | struct _LIBUNWIND_HIDDEN dl_iterate_cb_data { | ||
| 445 | LocalAddressSpace *addressSpace; | ||
| 446 | UnwindInfoSections *sects; | ||
| 447 | uintptr_t targetAddr; | ||
| 448 | }; | ||
| 449 | |||
| 450 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | ||
| 451 | #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) | ||
| 452 | #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform." | ||
| 453 | #endif | ||
| 454 | |||
| 455 | #include "FrameHeaderCache.hpp" | ||
| 456 | |||
| 457 | // There should be just one of these per process. | ||
| 458 | static FrameHeaderCache ProcessFrameHeaderCache; | ||
| 459 | |||
| 460 | static bool checkAddrInSegment(const Elf_Phdr *phdr, size_t image_base, | ||
| 461 | dl_iterate_cb_data *cbdata) { | ||
| 462 | if (phdr->p_type == PT_LOAD) { | ||
| 463 | uintptr_t begin = image_base + phdr->p_vaddr; | ||
| 464 | uintptr_t end = begin + phdr->p_memsz; | ||
| 465 | if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) { | ||
| 466 | cbdata->sects->dso_base = begin; | ||
| 467 | cbdata->sects->dwarf_section_length = phdr->p_memsz; | ||
| 468 | return true; | ||
| 469 | } | ||
| 470 | } | ||
| 471 | return false; | ||
| 472 | } | ||
| 473 | |||
| 474 | int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, size_t pinfo_size, | ||
| 475 | void *data) { | ||
| 476 | auto cbdata = static_cast<dl_iterate_cb_data *>(data); | ||
| 477 | if (pinfo->dlpi_phnum == 0 || cbdata->targetAddr < pinfo->dlpi_addr) | ||
| 478 | return 0; | ||
| 479 | if (ProcessFrameHeaderCache.find(pinfo, pinfo_size, data)) | ||
| 480 | return 1; | ||
| 481 | |||
| 482 | Elf_Addr image_base = calculateImageBase(pinfo); | ||
| 483 | bool found_obj = false; | ||
| 484 | bool found_hdr = false; | ||
| 485 | |||
| 486 | // Third phdr is usually the executable phdr. | ||
| 487 | if (pinfo->dlpi_phnum > 2) | ||
| 488 | found_obj = checkAddrInSegment(&pinfo->dlpi_phdr[2], image_base, cbdata); | ||
| 489 | |||
| 490 | // PT_GNU_EH_FRAME is usually near the end. Iterate backward. We already know | ||
| 491 | // that there is one or more phdrs. | ||
| 492 | for (Elf_Half i = pinfo->dlpi_phnum; i > 0; i--) { | ||
| 493 | const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i - 1]; | ||
| 494 | if (!found_hdr && phdr->p_type == PT_GNU_EH_FRAME) { | ||
| 495 | EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo; | ||
| 496 | uintptr_t eh_frame_hdr_start = image_base + phdr->p_vaddr; | ||
| 497 | cbdata->sects->dwarf_index_section = eh_frame_hdr_start; | ||
| 498 | cbdata->sects->dwarf_index_section_length = phdr->p_memsz; | ||
| 499 | found_hdr = EHHeaderParser<LocalAddressSpace>::decodeEHHdr( | ||
| 500 | *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, | ||
| 501 | hdrInfo); | ||
| 502 | if (found_hdr) | ||
| 503 | cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; | ||
| 504 | } else if (!found_obj) { | ||
| 505 | found_obj = checkAddrInSegment(phdr, image_base, cbdata); | ||
| 506 | } | ||
| 507 | if (found_obj && found_hdr) { | ||
| 508 | ProcessFrameHeaderCache.add(cbdata->sects); | ||
| 509 | return 1; | ||
| 510 | } | ||
| 511 | } | ||
| 512 | cbdata->sects->dwarf_section_length = 0; | ||
| 513 | return 0; | ||
| 514 | } | ||
| 515 | |||
| 516 | #else // defined(LIBUNWIND_SUPPORT_DWARF_UNWIND) | ||
| 517 | // Given all the #ifdef's above, the code here is for | ||
| 518 | // defined(LIBUNWIND_ARM_EHABI) | ||
| 519 | |||
| 520 | int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, size_t, void *data) { | ||
| 521 | auto *cbdata = static_cast<dl_iterate_cb_data *>(data); | ||
| 522 | bool found_obj = false; | ||
| 523 | bool found_hdr = false; | ||
| 524 | |||
| 525 | assert(cbdata); | ||
| 526 | assert(cbdata->sects); | ||
| 527 | |||
| 528 | if (cbdata->targetAddr < pinfo->dlpi_addr) | ||
| 529 | return 0; | ||
| 530 | |||
| 531 | Elf_Addr image_base = calculateImageBase(pinfo); | ||
| 532 | |||
| 533 | for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { | ||
| 534 | const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; | ||
| 535 | if (phdr->p_type == PT_LOAD) { | ||
| 536 | uintptr_t begin = image_base + phdr->p_vaddr; | ||
| 537 | uintptr_t end = begin + phdr->p_memsz; | ||
| 538 | if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) | ||
| 539 | found_obj = true; | ||
| 540 | } else if (phdr->p_type == PT_ARM_EXIDX) { | ||
| 541 | uintptr_t exidx_start = image_base + phdr->p_vaddr; | ||
| 542 | cbdata->sects->arm_section = exidx_start; | ||
| 543 | cbdata->sects->arm_section_length = phdr->p_memsz; | ||
| 544 | found_hdr = true; | ||
| 545 | } | ||
| 546 | } | ||
| 547 | return found_obj && found_hdr; | ||
| 548 | } | ||
| 549 | #endif // defined(LIBUNWIND_SUPPORT_DWARF_UNWIND) | ||
| 550 | #endif // defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | ||
| 551 | |||
| 552 | |||
| 395 | inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, | 553 | inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, |
| 396 | UnwindInfoSections &info) { | 554 | UnwindInfoSections &info) { |
| 397 | #ifdef __APPLE__ | 555 | #ifdef __APPLE__ |
| ... | @@ -483,110 +641,8 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, | ... | @@ -483,110 +641,8 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, |
| 483 | if (info.arm_section && info.arm_section_length) | 641 | if (info.arm_section && info.arm_section_length) |
| 484 | return true; | 642 | return true; |
| 485 | #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | 643 | #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
| 486 | struct dl_iterate_cb_data { | ||
| 487 | LocalAddressSpace *addressSpace; | ||
| 488 | UnwindInfoSections *sects; | ||
| 489 | uintptr_t targetAddr; | ||
| 490 | }; | ||
| 491 | |||
| 492 | dl_iterate_cb_data cb_data = {this, &info, targetAddr}; | 644 | dl_iterate_cb_data cb_data = {this, &info, targetAddr}; |
| 493 | int found = dl_iterate_phdr( | 645 | int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data); |
| 494 | [](struct dl_phdr_info *pinfo, size_t, void *data) -> int { | ||
| 495 | auto cbdata = static_cast<dl_iterate_cb_data *>(data); | ||
| 496 | bool found_obj = false; | ||
| 497 | bool found_hdr = false; | ||
| 498 | |||
| 499 | assert(cbdata); | ||
| 500 | assert(cbdata->sects); | ||
| 501 | |||
| 502 | if (cbdata->targetAddr < pinfo->dlpi_addr) { | ||
| 503 | return false; | ||
| 504 | } | ||
| 505 | |||
| 506 | #if !defined(Elf_Half) | ||
| 507 | typedef ElfW(Half) Elf_Half; | ||
| 508 | #endif | ||
| 509 | #if !defined(Elf_Phdr) | ||
| 510 | typedef ElfW(Phdr) Elf_Phdr; | ||
| 511 | #endif | ||
| 512 | #if !defined(Elf_Addr) | ||
| 513 | typedef ElfW(Addr) Elf_Addr; | ||
| 514 | #endif | ||
| 515 | |||
| 516 | Elf_Addr image_base = pinfo->dlpi_addr; | ||
| 517 | |||
| 518 | #if defined(__ANDROID__) && __ANDROID_API__ < 18 | ||
| 519 | if (image_base == 0) { | ||
| 520 | // Normally, an image base of 0 indicates a non-PIE executable. On | ||
| 521 | // versions of Android prior to API 18, the dynamic linker reported a | ||
| 522 | // dlpi_addr of 0 for PIE executables. Compute the true image base | ||
| 523 | // using the PT_PHDR segment. | ||
| 524 | // See https://github.com/android/ndk/issues/505. | ||
| 525 | for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { | ||
| 526 | const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; | ||
| 527 | if (phdr->p_type == PT_PHDR) { | ||
| 528 | image_base = reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) - | ||
| 529 | phdr->p_vaddr; | ||
| 530 | break; | ||
| 531 | } | ||
| 532 | } | ||
| 533 | } | ||
| 534 | #endif | ||
| 535 | |||
| 536 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | ||
| 537 | #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) | ||
| 538 | #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform." | ||
| 539 | #endif | ||
| 540 | size_t object_length; | ||
| 541 | |||
| 542 | for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { | ||
| 543 | const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; | ||
| 544 | if (phdr->p_type == PT_LOAD) { | ||
| 545 | uintptr_t begin = image_base + phdr->p_vaddr; | ||
| 546 | uintptr_t end = begin + phdr->p_memsz; | ||
| 547 | if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) { | ||
| 548 | cbdata->sects->dso_base = begin; | ||
| 549 | object_length = phdr->p_memsz; | ||
| 550 | found_obj = true; | ||
| 551 | } | ||
| 552 | } else if (phdr->p_type == PT_GNU_EH_FRAME) { | ||
| 553 | EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo; | ||
| 554 | uintptr_t eh_frame_hdr_start = image_base + phdr->p_vaddr; | ||
| 555 | cbdata->sects->dwarf_index_section = eh_frame_hdr_start; | ||
| 556 | cbdata->sects->dwarf_index_section_length = phdr->p_memsz; | ||
| 557 | found_hdr = EHHeaderParser<LocalAddressSpace>::decodeEHHdr( | ||
| 558 | *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, | ||
| 559 | hdrInfo); | ||
| 560 | if (found_hdr) | ||
| 561 | cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; | ||
| 562 | } | ||
| 563 | } | ||
| 564 | |||
| 565 | if (found_obj && found_hdr) { | ||
| 566 | cbdata->sects->dwarf_section_length = object_length; | ||
| 567 | return true; | ||
| 568 | } else { | ||
| 569 | return false; | ||
| 570 | } | ||
| 571 | #else // defined(_LIBUNWIND_ARM_EHABI) | ||
| 572 | for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { | ||
| 573 | const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; | ||
| 574 | if (phdr->p_type == PT_LOAD) { | ||
| 575 | uintptr_t begin = image_base + phdr->p_vaddr; | ||
| 576 | uintptr_t end = begin + phdr->p_memsz; | ||
| 577 | if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) | ||
| 578 | found_obj = true; | ||
| 579 | } else if (phdr->p_type == PT_ARM_EXIDX) { | ||
| 580 | uintptr_t exidx_start = image_base + phdr->p_vaddr; | ||
| 581 | cbdata->sects->arm_section = exidx_start; | ||
| 582 | cbdata->sects->arm_section_length = phdr->p_memsz; | ||
| 583 | found_hdr = true; | ||
| 584 | } | ||
| 585 | } | ||
| 586 | return found_obj && found_hdr; | ||
| 587 | #endif | ||
| 588 | }, | ||
| 589 | &cb_data); | ||
| 590 | return static_cast<bool>(found); | 646 | return static_cast<bool>(found); |
| 591 | #endif | 647 | #endif |
| 592 | 648 |
lib/libunwind/src/DwarfParser.hpp+87-42| ... | @@ -77,6 +77,7 @@ public: | ... | @@ -77,6 +77,7 @@ public: |
| 77 | }; | 77 | }; |
| 78 | struct RegisterLocation { | 78 | struct RegisterLocation { |
| 79 | RegisterSavedWhere location; | 79 | RegisterSavedWhere location; |
| 80 | bool initialStateSaved; | ||
| 80 | int64_t value; | 81 | int64_t value; |
| 81 | }; | 82 | }; |
| 82 | /// Information about a frame layout and registers saved determined | 83 | /// Information about a frame layout and registers saved determined |
| ... | @@ -90,6 +91,40 @@ public: | ... | @@ -90,6 +91,40 @@ public: |
| 90 | bool registersInOtherRegisters; | 91 | bool registersInOtherRegisters; |
| 91 | bool sameValueUsed; | 92 | bool sameValueUsed; |
| 92 | RegisterLocation savedRegisters[kMaxRegisterNumber + 1]; | 93 | RegisterLocation savedRegisters[kMaxRegisterNumber + 1]; |
| 94 | enum class InitializeTime { kLazy, kNormal }; | ||
| 95 | |||
| 96 | // When saving registers, this data structure is lazily initialized. | ||
| 97 | PrologInfo(InitializeTime IT = InitializeTime::kNormal) { | ||
| 98 | if (IT == InitializeTime::kNormal) | ||
| 99 | memset(this, 0, sizeof(*this)); | ||
| 100 | } | ||
| 101 | void checkSaveRegister(uint64_t reg, PrologInfo &initialState) { | ||
| 102 | if (!savedRegisters[reg].initialStateSaved) { | ||
| 103 | initialState.savedRegisters[reg] = savedRegisters[reg]; | ||
| 104 | savedRegisters[reg].initialStateSaved = true; | ||
| 105 | } | ||
| 106 | } | ||
| 107 | void setRegister(uint64_t reg, RegisterSavedWhere newLocation, | ||
| 108 | int64_t newValue, PrologInfo &initialState) { | ||
| 109 | checkSaveRegister(reg, initialState); | ||
| 110 | savedRegisters[reg].location = newLocation; | ||
| 111 | savedRegisters[reg].value = newValue; | ||
| 112 | } | ||
| 113 | void setRegisterLocation(uint64_t reg, RegisterSavedWhere newLocation, | ||
| 114 | PrologInfo &initialState) { | ||
| 115 | checkSaveRegister(reg, initialState); | ||
| 116 | savedRegisters[reg].location = newLocation; | ||
| 117 | } | ||
| 118 | void setRegisterValue(uint64_t reg, int64_t newValue, | ||
| 119 | PrologInfo &initialState) { | ||
| 120 | checkSaveRegister(reg, initialState); | ||
| 121 | savedRegisters[reg].value = newValue; | ||
| 122 | } | ||
| 123 | void restoreRegisterToInitialState(uint64_t reg, PrologInfo &initialState) { | ||
| 124 | if (savedRegisters[reg].initialStateSaved) | ||
| 125 | savedRegisters[reg] = initialState.savedRegisters[reg]; | ||
| 126 | // else the register still holds its initial state | ||
| 127 | } | ||
| 93 | }; | 128 | }; |
| 94 | 129 | ||
| 95 | struct PrologInfoStackEntry { | 130 | struct PrologInfoStackEntry { |
| ... | @@ -355,18 +390,30 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, | ... | @@ -355,18 +390,30 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, |
| 355 | const FDE_Info &fdeInfo, | 390 | const FDE_Info &fdeInfo, |
| 356 | const CIE_Info &cieInfo, pint_t upToPC, | 391 | const CIE_Info &cieInfo, pint_t upToPC, |
| 357 | int arch, PrologInfo *results) { | 392 | int arch, PrologInfo *results) { |
| 358 | // clear results | ||
| 359 | memset(results, '\0', sizeof(PrologInfo)); | ||
| 360 | PrologInfoStackEntry *rememberStack = NULL; | 393 | PrologInfoStackEntry *rememberStack = NULL; |
| 361 | 394 | ||
| 362 | // parse CIE then FDE instructions | 395 | // parse CIE then FDE instructions |
| 363 | return parseInstructions(addressSpace, cieInfo.cieInstructions, | 396 | bool returnValue = |
| 364 | cieInfo.cieStart + cieInfo.cieLength, cieInfo, | 397 | parseInstructions(addressSpace, cieInfo.cieInstructions, |
| 365 | (pint_t)(-1), rememberStack, arch, results) && | 398 | cieInfo.cieStart + cieInfo.cieLength, cieInfo, |
| 366 | parseInstructions(addressSpace, fdeInfo.fdeInstructions, | 399 | (pint_t)(-1), rememberStack, arch, results) && |
| 367 | fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo, | 400 | parseInstructions(addressSpace, fdeInfo.fdeInstructions, |
| 368 | upToPC - fdeInfo.pcStart, rememberStack, arch, | 401 | fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo, |
| 369 | results); | 402 | upToPC - fdeInfo.pcStart, rememberStack, arch, results); |
| 403 | |||
| 404 | #if !defined(_LIBUNWIND_NO_HEAP) | ||
| 405 | // Clean up rememberStack. Even in the case where every DW_CFA_remember_state | ||
| 406 | // is paired with a DW_CFA_restore_state, parseInstructions can skip restore | ||
| 407 | // opcodes if it reaches the target PC and stops interpreting, so we have to | ||
| 408 | // make sure we don't leak memory. | ||
| 409 | while (rememberStack) { | ||
| 410 | PrologInfoStackEntry *next = rememberStack->next; | ||
| 411 | free(rememberStack); | ||
| 412 | rememberStack = next; | ||
| 413 | } | ||
| 414 | #endif | ||
| 415 | |||
| 416 | return returnValue; | ||
| 370 | } | 417 | } |
| 371 | 418 | ||
| 372 | /// "run" the DWARF instructions | 419 | /// "run" the DWARF instructions |
| ... | @@ -378,7 +425,9 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, | ... | @@ -378,7 +425,9 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 378 | int arch, PrologInfo *results) { | 425 | int arch, PrologInfo *results) { |
| 379 | pint_t p = instructions; | 426 | pint_t p = instructions; |
| 380 | pint_t codeOffset = 0; | 427 | pint_t codeOffset = 0; |
| 381 | PrologInfo initialState = *results; | 428 | // initialState initialized as registers in results are modified. Use |
| 429 | // PrologInfo accessor functions to avoid reading uninitialized data. | ||
| 430 | PrologInfo initialState(PrologInfo::InitializeTime::kLazy); | ||
| 382 | 431 | ||
| 383 | _LIBUNWIND_TRACE_DWARF("parseInstructions(instructions=0x%0" PRIx64 ")\n", | 432 | _LIBUNWIND_TRACE_DWARF("parseInstructions(instructions=0x%0" PRIx64 ")\n", |
| 384 | static_cast<uint64_t>(instructionsEnd)); | 433 | static_cast<uint64_t>(instructionsEnd)); |
| ... | @@ -431,8 +480,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, | ... | @@ -431,8 +480,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 431 | "malformed DW_CFA_offset_extended DWARF unwind, reg too big"); | 480 | "malformed DW_CFA_offset_extended DWARF unwind, reg too big"); |
| 432 | return false; | 481 | return false; |
| 433 | } | 482 | } |
| 434 | results->savedRegisters[reg].location = kRegisterInCFA; | 483 | results->setRegister(reg, kRegisterInCFA, offset, initialState); |
| 435 | results->savedRegisters[reg].value = offset; | ||
| 436 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", " | 484 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", " |
| 437 | "offset=%" PRId64 ")\n", | 485 | "offset=%" PRId64 ")\n", |
| 438 | reg, offset); | 486 | reg, offset); |
| ... | @@ -444,7 +492,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, | ... | @@ -444,7 +492,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 444 | "malformed DW_CFA_restore_extended DWARF unwind, reg too big"); | 492 | "malformed DW_CFA_restore_extended DWARF unwind, reg too big"); |
| 445 | return false; | 493 | return false; |
| 446 | } | 494 | } |
| 447 | results->savedRegisters[reg] = initialState.savedRegisters[reg]; | 495 | results->restoreRegisterToInitialState(reg, initialState); |
| 448 | _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg); | 496 | _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg); |
| 449 | break; | 497 | break; |
| 450 | case DW_CFA_undefined: | 498 | case DW_CFA_undefined: |
| ... | @@ -454,7 +502,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, | ... | @@ -454,7 +502,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 454 | "malformed DW_CFA_undefined DWARF unwind, reg too big"); | 502 | "malformed DW_CFA_undefined DWARF unwind, reg too big"); |
| 455 | return false; | 503 | return false; |
| 456 | } | 504 | } |
| 457 | results->savedRegisters[reg].location = kRegisterUnused; | 505 | results->setRegisterLocation(reg, kRegisterUnused, initialState); |
| 458 | _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg); | 506 | _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg); |
| 459 | break; | 507 | break; |
| 460 | case DW_CFA_same_value: | 508 | case DW_CFA_same_value: |
| ... | @@ -468,7 +516,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, | ... | @@ -468,7 +516,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 468 | // "same value" means register was stored in frame, but its current | 516 | // "same value" means register was stored in frame, but its current |
| 469 | // value has not changed, so no need to restore from frame. | 517 | // value has not changed, so no need to restore from frame. |
| 470 | // We model this as if the register was never saved. | 518 | // We model this as if the register was never saved. |
| 471 | results->savedRegisters[reg].location = kRegisterUnused; | 519 | results->setRegisterLocation(reg, kRegisterUnused, initialState); |
| 472 | // set flag to disable conversion to compact unwind | 520 | // set flag to disable conversion to compact unwind |
| 473 | results->sameValueUsed = true; | 521 | results->sameValueUsed = true; |
| 474 | _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg); | 522 | _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg); |
| ... | @@ -486,8 +534,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, | ... | @@ -486,8 +534,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 486 | "malformed DW_CFA_register DWARF unwind, reg2 too big"); | 534 | "malformed DW_CFA_register DWARF unwind, reg2 too big"); |
| 487 | return false; | 535 | return false; |
| 488 | } | 536 | } |
| 489 | results->savedRegisters[reg].location = kRegisterInRegister; | 537 | results->setRegister(reg, kRegisterInRegister, (int64_t)reg2, |
| 490 | results->savedRegisters[reg].value = (int64_t)reg2; | 538 | initialState); |
| 491 | // set flag to disable conversion to compact unwind | 539 | // set flag to disable conversion to compact unwind |
| 492 | results->registersInOtherRegisters = true; | 540 | results->registersInOtherRegisters = true; |
| 493 | _LIBUNWIND_TRACE_DWARF( | 541 | _LIBUNWIND_TRACE_DWARF( |
| ... | @@ -564,8 +612,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, | ... | @@ -564,8 +612,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 564 | "malformed DW_CFA_expression DWARF unwind, reg too big"); | 612 | "malformed DW_CFA_expression DWARF unwind, reg too big"); |
| 565 | return false; | 613 | return false; |
| 566 | } | 614 | } |
| 567 | results->savedRegisters[reg].location = kRegisterAtExpression; | 615 | results->setRegister(reg, kRegisterAtExpression, (int64_t)p, |
| 568 | results->savedRegisters[reg].value = (int64_t)p; | 616 | initialState); |
| 569 | length = addressSpace.getULEB128(p, instructionsEnd); | 617 | length = addressSpace.getULEB128(p, instructionsEnd); |
| 570 | assert(length < static_cast<pint_t>(~0) && "pointer overflow"); | 618 | assert(length < static_cast<pint_t>(~0) && "pointer overflow"); |
| 571 | p += static_cast<pint_t>(length); | 619 | p += static_cast<pint_t>(length); |
| ... | @@ -583,8 +631,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, | ... | @@ -583,8 +631,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 583 | } | 631 | } |
| 584 | offset = | 632 | offset = |
| 585 | addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; | 633 | addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; |
| 586 | results->savedRegisters[reg].location = kRegisterInCFA; | 634 | results->setRegister(reg, kRegisterInCFA, offset, initialState); |
| 587 | results->savedRegisters[reg].value = offset; | ||
| 588 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64 ", " | 635 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64 ", " |
| 589 | "offset=%" PRId64 ")\n", | 636 | "offset=%" PRId64 ")\n", |
| 590 | reg, offset); | 637 | reg, offset); |
| ... | @@ -622,8 +669,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, | ... | @@ -622,8 +669,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 622 | } | 669 | } |
| 623 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) | 670 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) |
| 624 | * cieInfo.dataAlignFactor; | 671 | * cieInfo.dataAlignFactor; |
| 625 | results->savedRegisters[reg].location = kRegisterOffsetFromCFA; | 672 | results->setRegister(reg, kRegisterOffsetFromCFA, offset, initialState); |
| 626 | results->savedRegisters[reg].value = offset; | ||
| 627 | _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64 ", " | 673 | _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64 ", " |
| 628 | "offset=%" PRId64 "\n", | 674 | "offset=%" PRId64 "\n", |
| 629 | reg, offset); | 675 | reg, offset); |
| ... | @@ -637,8 +683,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, | ... | @@ -637,8 +683,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 637 | } | 683 | } |
| 638 | offset = | 684 | offset = |
| 639 | addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; | 685 | addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; |
| 640 | results->savedRegisters[reg].location = kRegisterOffsetFromCFA; | 686 | results->setRegister(reg, kRegisterOffsetFromCFA, offset, initialState); |
| 641 | results->savedRegisters[reg].value = offset; | ||
| 642 | _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64 ", " | 687 | _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64 ", " |
| 643 | "offset=%" PRId64 "\n", | 688 | "offset=%" PRId64 "\n", |
| 644 | reg, offset); | 689 | reg, offset); |
| ... | @@ -650,8 +695,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, | ... | @@ -650,8 +695,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 650 | "malformed DW_CFA_val_expression DWARF unwind, reg too big"); | 695 | "malformed DW_CFA_val_expression DWARF unwind, reg too big"); |
| 651 | return false; | 696 | return false; |
| 652 | } | 697 | } |
| 653 | results->savedRegisters[reg].location = kRegisterIsExpression; | 698 | results->setRegister(reg, kRegisterIsExpression, (int64_t)p, |
| 654 | results->savedRegisters[reg].value = (int64_t)p; | 699 | initialState); |
| 655 | length = addressSpace.getULEB128(p, instructionsEnd); | 700 | length = addressSpace.getULEB128(p, instructionsEnd); |
| 656 | assert(length < static_cast<pint_t>(~0) && "pointer overflow"); | 701 | assert(length < static_cast<pint_t>(~0) && "pointer overflow"); |
| 657 | p += static_cast<pint_t>(length); | 702 | p += static_cast<pint_t>(length); |
| ... | @@ -673,8 +718,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, | ... | @@ -673,8 +718,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 673 | } | 718 | } |
| 674 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) | 719 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) |
| 675 | * cieInfo.dataAlignFactor; | 720 | * cieInfo.dataAlignFactor; |
| 676 | results->savedRegisters[reg].location = kRegisterInCFA; | 721 | results->setRegister(reg, kRegisterInCFA, -offset, initialState); |
| 677 | results->savedRegisters[reg].value = -offset; | ||
| 678 | _LIBUNWIND_TRACE_DWARF( | 722 | _LIBUNWIND_TRACE_DWARF( |
| 679 | "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset); | 723 | "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset); |
| 680 | break; | 724 | break; |
| ... | @@ -687,25 +731,27 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, | ... | @@ -687,25 +731,27 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 687 | case DW_CFA_AARCH64_negate_ra_state: | 731 | case DW_CFA_AARCH64_negate_ra_state: |
| 688 | switch (arch) { | 732 | switch (arch) { |
| 689 | #if defined(_LIBUNWIND_TARGET_AARCH64) | 733 | #if defined(_LIBUNWIND_TARGET_AARCH64) |
| 690 | case REGISTERS_ARM64: | 734 | case REGISTERS_ARM64: { |
| 691 | results->savedRegisters[UNW_ARM64_RA_SIGN_STATE].value ^= 0x1; | 735 | int64_t value = |
| 692 | _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n"); | 736 | results->savedRegisters[UNW_ARM64_RA_SIGN_STATE].value ^ 0x1; |
| 693 | break; | 737 | results->setRegisterValue(UNW_ARM64_RA_SIGN_STATE, value, initialState); |
| 738 | _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n"); | ||
| 739 | } break; | ||
| 694 | #endif | 740 | #endif |
| 741 | |||
| 695 | #if defined(_LIBUNWIND_TARGET_SPARC) | 742 | #if defined(_LIBUNWIND_TARGET_SPARC) |
| 696 | // case DW_CFA_GNU_window_save: | 743 | // case DW_CFA_GNU_window_save: |
| 697 | case REGISTERS_SPARC: | 744 | case REGISTERS_SPARC: |
| 698 | _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n"); | 745 | _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n"); |
| 699 | for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) { | 746 | for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) { |
| 700 | results->savedRegisters[reg].location = kRegisterInRegister; | 747 | results->setRegister(reg, kRegisterInRegister, |
| 701 | results->savedRegisters[reg].value = | 748 | ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0, |
| 702 | ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0; | 749 | initialState); |
| 703 | } | 750 | } |
| 704 | 751 | ||
| 705 | for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) { | 752 | for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) { |
| 706 | results->savedRegisters[reg].location = kRegisterInCFA; | 753 | results->setRegister(reg, kRegisterInCFA, |
| 707 | results->savedRegisters[reg].value = | 754 | ((int64_t)reg - UNW_SPARC_L0) * 4, initialState); |
| 708 | ((int64_t)reg - UNW_SPARC_L0) * 4; | ||
| 709 | } | 755 | } |
| 710 | break; | 756 | break; |
| 711 | #endif | 757 | #endif |
| ... | @@ -728,8 +774,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, | ... | @@ -728,8 +774,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 728 | } | 774 | } |
| 729 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) | 775 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) |
| 730 | * cieInfo.dataAlignFactor; | 776 | * cieInfo.dataAlignFactor; |
| 731 | results->savedRegisters[reg].location = kRegisterInCFA; | 777 | results->setRegister(reg, kRegisterInCFA, offset, initialState); |
| 732 | results->savedRegisters[reg].value = offset; | ||
| 733 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n", | 778 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n", |
| 734 | operand, offset); | 779 | operand, offset); |
| 735 | break; | 780 | break; |
| ... | @@ -746,7 +791,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, | ... | @@ -746,7 +791,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 746 | reg); | 791 | reg); |
| 747 | return false; | 792 | return false; |
| 748 | } | 793 | } |
| 749 | results->savedRegisters[reg] = initialState.savedRegisters[reg]; | 794 | results->restoreRegisterToInitialState(reg, initialState); |
| 750 | _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n", | 795 | _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n", |
| 751 | static_cast<uint64_t>(operand)); | 796 | static_cast<uint64_t>(operand)); |
| 752 | break; | 797 | break; |
lib/libunwind/src/EHHeaderParser.hpp+2| ... | @@ -109,6 +109,8 @@ bool EHHeaderParser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, | ... | @@ -109,6 +109,8 @@ bool EHHeaderParser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, |
| 109 | hdrInfo)) | 109 | hdrInfo)) |
| 110 | return false; | 110 | return false; |
| 111 | 111 | ||
| 112 | if (hdrInfo.fde_count == 0) return false; | ||
| 113 | |||
| 112 | size_t tableEntrySize = getTableEntrySize(hdrInfo.table_enc); | 114 | size_t tableEntrySize = getTableEntrySize(hdrInfo.table_enc); |
| 113 | pint_t tableEntry; | 115 | pint_t tableEntry; |
| 114 | 116 |
lib/libunwind/src/FrameHeaderCache.hpp created+149| ... | @@ -0,0 +1,149 @@ | ||
| 1 | //===-FrameHeaderCache.hpp ------------------------------------------------===// | ||
| 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 | // Cache the elf program headers necessary to unwind the stack more efficiently | ||
| 8 | // in the presence of many dsos. | ||
| 9 | // | ||
| 10 | //===----------------------------------------------------------------------===// | ||
| 11 | |||
| 12 | #ifndef __FRAMEHEADER_CACHE_HPP__ | ||
| 13 | #define __FRAMEHEADER_CACHE_HPP__ | ||
| 14 | |||
| 15 | #include "config.h" | ||
| 16 | #include <limits.h> | ||
| 17 | |||
| 18 | #ifdef _LIBUNWIND_DEBUG_FRAMEHEADER_CACHE | ||
| 19 | #define _LIBUNWIND_FRAMEHEADERCACHE_TRACE0(x) _LIBUNWIND_LOG0(x) | ||
| 20 | #define _LIBUNWIND_FRAMEHEADERCACHE_TRACE(msg, ...) \ | ||
| 21 | _LIBUNWIND_LOG(msg, __VA_ARGS__) | ||
| 22 | #else | ||
| 23 | #define _LIBUNWIND_FRAMEHEADERCACHE_TRACE0(x) | ||
| 24 | #define _LIBUNWIND_FRAMEHEADERCACHE_TRACE(msg, ...) | ||
| 25 | #endif | ||
| 26 | |||
| 27 | // This cache should only be be used from within a dl_iterate_phdr callback. | ||
| 28 | // dl_iterate_phdr does the necessary synchronization to prevent problems | ||
| 29 | // with concurrent access via the libc load lock. Adding synchronization | ||
| 30 | // for other uses is possible, but not currently done. | ||
| 31 | |||
| 32 | class _LIBUNWIND_HIDDEN FrameHeaderCache { | ||
| 33 | struct CacheEntry { | ||
| 34 | uintptr_t LowPC() { return Info.dso_base; }; | ||
| 35 | uintptr_t HighPC() { return Info.dso_base + Info.dwarf_section_length; }; | ||
| 36 | UnwindInfoSections Info; | ||
| 37 | CacheEntry *Next; | ||
| 38 | }; | ||
| 39 | |||
| 40 | static const size_t kCacheEntryCount = 8; | ||
| 41 | |||
| 42 | // Can't depend on the C++ standard library in libunwind, so use an array to | ||
| 43 | // allocate the entries, and two linked lists for ordering unused and recently | ||
| 44 | // used entries. FIXME: Would the the extra memory for a doubly-linked list | ||
| 45 | // be better than the runtime cost of traversing a very short singly-linked | ||
| 46 | // list on a cache miss? The entries themselves are all small and consecutive, | ||
| 47 | // so unlikely to cause page faults when following the pointers. The memory | ||
| 48 | // spent on additional pointers could also be spent on more entries. | ||
| 49 | |||
| 50 | CacheEntry Entries[kCacheEntryCount]; | ||
| 51 | CacheEntry *MostRecentlyUsed; | ||
| 52 | CacheEntry *Unused; | ||
| 53 | |||
| 54 | void resetCache() { | ||
| 55 | _LIBUNWIND_FRAMEHEADERCACHE_TRACE0("FrameHeaderCache reset"); | ||
| 56 | MostRecentlyUsed = nullptr; | ||
| 57 | Unused = &Entries[0]; | ||
| 58 | for (size_t i = 0; i < kCacheEntryCount - 1; i++) { | ||
| 59 | Entries[i].Next = &Entries[i + 1]; | ||
| 60 | } | ||
| 61 | Entries[kCacheEntryCount - 1].Next = nullptr; | ||
| 62 | } | ||
| 63 | |||
| 64 | bool cacheNeedsReset(dl_phdr_info *PInfo) { | ||
| 65 | // C libraries increment dl_phdr_info.adds and dl_phdr_info.subs when | ||
| 66 | // loading and unloading shared libraries. If these values change between | ||
| 67 | // iterations of dl_iterate_phdr, then invalidate the cache. | ||
| 68 | |||
| 69 | // These are static to avoid needing an initializer, and unsigned long long | ||
| 70 | // because that is their type within the extended dl_phdr_info. Initialize | ||
| 71 | // these to something extremely unlikely to be found upon the first call to | ||
| 72 | // dl_iterate_phdr. | ||
| 73 | static unsigned long long LastAdds = ULLONG_MAX; | ||
| 74 | static unsigned long long LastSubs = ULLONG_MAX; | ||
| 75 | if (PInfo->dlpi_adds != LastAdds || PInfo->dlpi_subs != LastSubs) { | ||
| 76 | // Resetting the entire cache is a big hammer, but this path is rare-- | ||
| 77 | // usually just on the very first call, when the cache is empty anyway--so | ||
| 78 | // added complexity doesn't buy much. | ||
| 79 | LastAdds = PInfo->dlpi_adds; | ||
| 80 | LastSubs = PInfo->dlpi_subs; | ||
| 81 | resetCache(); | ||
| 82 | return true; | ||
| 83 | } | ||
| 84 | return false; | ||
| 85 | } | ||
| 86 | |||
| 87 | public: | ||
| 88 | bool find(dl_phdr_info *PInfo, size_t, void *data) { | ||
| 89 | if (cacheNeedsReset(PInfo) || MostRecentlyUsed == nullptr) | ||
| 90 | return false; | ||
| 91 | |||
| 92 | auto *CBData = static_cast<dl_iterate_cb_data *>(data); | ||
| 93 | CacheEntry *Current = MostRecentlyUsed; | ||
| 94 | CacheEntry *Previous = nullptr; | ||
| 95 | while (Current != nullptr) { | ||
| 96 | _LIBUNWIND_FRAMEHEADERCACHE_TRACE( | ||
| 97 | "FrameHeaderCache check %lx in [%lx - %lx)", CBData->targetAddr, | ||
| 98 | Current->LowPC(), Current->HighPC()); | ||
| 99 | if (Current->LowPC() <= CBData->targetAddr && | ||
| 100 | CBData->targetAddr < Current->HighPC()) { | ||
| 101 | _LIBUNWIND_FRAMEHEADERCACHE_TRACE( | ||
| 102 | "FrameHeaderCache hit %lx in [%lx - %lx)", CBData->targetAddr, | ||
| 103 | Current->LowPC(), Current->HighPC()); | ||
| 104 | if (Previous) { | ||
| 105 | // If there is no Previous, then Current is already the | ||
| 106 | // MostRecentlyUsed, and no need to move it up. | ||
| 107 | Previous->Next = Current->Next; | ||
| 108 | Current->Next = MostRecentlyUsed; | ||
| 109 | MostRecentlyUsed = Current; | ||
| 110 | } | ||
| 111 | *CBData->sects = Current->Info; | ||
| 112 | return true; | ||
| 113 | } | ||
| 114 | Previous = Current; | ||
| 115 | Current = Current->Next; | ||
| 116 | } | ||
| 117 | _LIBUNWIND_FRAMEHEADERCACHE_TRACE("FrameHeaderCache miss for address %lx", | ||
| 118 | CBData->targetAddr); | ||
| 119 | return false; | ||
| 120 | } | ||
| 121 | |||
| 122 | void add(const UnwindInfoSections *UIS) { | ||
| 123 | CacheEntry *Current = nullptr; | ||
| 124 | |||
| 125 | if (Unused != nullptr) { | ||
| 126 | Current = Unused; | ||
| 127 | Unused = Unused->Next; | ||
| 128 | } else { | ||
| 129 | Current = MostRecentlyUsed; | ||
| 130 | CacheEntry *Previous = nullptr; | ||
| 131 | while (Current->Next != nullptr) { | ||
| 132 | Previous = Current; | ||
| 133 | Current = Current->Next; | ||
| 134 | } | ||
| 135 | Previous->Next = nullptr; | ||
| 136 | _LIBUNWIND_FRAMEHEADERCACHE_TRACE("FrameHeaderCache evict [%lx - %lx)", | ||
| 137 | Current->LowPC(), Current->HighPC()); | ||
| 138 | } | ||
| 139 | |||
| 140 | Current->Info = *UIS; | ||
| 141 | Current->Next = MostRecentlyUsed; | ||
| 142 | MostRecentlyUsed = Current; | ||
| 143 | _LIBUNWIND_FRAMEHEADERCACHE_TRACE("FrameHeaderCache add [%lx - %lx)", | ||
| 144 | MostRecentlyUsed->LowPC(), | ||
| 145 | MostRecentlyUsed->HighPC()); | ||
| 146 | } | ||
| 147 | }; | ||
| 148 | |||
| 149 | #endif // __FRAMEHEADER_CACHE_HPP__ | ||
lib/libunwind/src/Registers.hpp+200-5| ... | @@ -34,6 +34,7 @@ enum { | ... | @@ -34,6 +34,7 @@ enum { |
| 34 | REGISTERS_MIPS_O32, | 34 | REGISTERS_MIPS_O32, |
| 35 | REGISTERS_MIPS_NEWABI, | 35 | REGISTERS_MIPS_NEWABI, |
| 36 | REGISTERS_SPARC, | 36 | REGISTERS_SPARC, |
| 37 | REGISTERS_HEXAGON, | ||
| 37 | REGISTERS_RISCV, | 38 | REGISTERS_RISCV, |
| 38 | }; | 39 | }; |
| 39 | 40 | ||
| ... | @@ -2869,6 +2870,8 @@ inline bool Registers_mips_o32::validFloatRegister(int regNum) const { | ... | @@ -2869,6 +2870,8 @@ inline bool Registers_mips_o32::validFloatRegister(int regNum) const { |
| 2869 | #if defined(__mips_hard_float) && __mips_fpr == 64 | 2870 | #if defined(__mips_hard_float) && __mips_fpr == 64 |
| 2870 | if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) | 2871 | if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) |
| 2871 | return true; | 2872 | return true; |
| 2873 | #else | ||
| 2874 | (void)regNum; | ||
| 2872 | #endif | 2875 | #endif |
| 2873 | return false; | 2876 | return false; |
| 2874 | } | 2877 | } |
| ... | @@ -2878,6 +2881,7 @@ inline double Registers_mips_o32::getFloatRegister(int regNum) const { | ... | @@ -2878,6 +2881,7 @@ inline double Registers_mips_o32::getFloatRegister(int regNum) const { |
| 2878 | assert(validFloatRegister(regNum)); | 2881 | assert(validFloatRegister(regNum)); |
| 2879 | return _floats[regNum - UNW_MIPS_F0]; | 2882 | return _floats[regNum - UNW_MIPS_F0]; |
| 2880 | #else | 2883 | #else |
| 2884 | (void)regNum; | ||
| 2881 | _LIBUNWIND_ABORT("mips_o32 float support not implemented"); | 2885 | _LIBUNWIND_ABORT("mips_o32 float support not implemented"); |
| 2882 | #endif | 2886 | #endif |
| 2883 | } | 2887 | } |
| ... | @@ -2888,6 +2892,8 @@ inline void Registers_mips_o32::setFloatRegister(int regNum, | ... | @@ -2888,6 +2892,8 @@ inline void Registers_mips_o32::setFloatRegister(int regNum, |
| 2888 | assert(validFloatRegister(regNum)); | 2892 | assert(validFloatRegister(regNum)); |
| 2889 | _floats[regNum - UNW_MIPS_F0] = value; | 2893 | _floats[regNum - UNW_MIPS_F0] = value; |
| 2890 | #else | 2894 | #else |
| 2895 | (void)regNum; | ||
| 2896 | (void)value; | ||
| 2891 | _LIBUNWIND_ABORT("mips_o32 float support not implemented"); | 2897 | _LIBUNWIND_ABORT("mips_o32 float support not implemented"); |
| 2892 | #endif | 2898 | #endif |
| 2893 | } | 2899 | } |
| ... | @@ -3159,6 +3165,8 @@ inline bool Registers_mips_newabi::validFloatRegister(int regNum) const { | ... | @@ -3159,6 +3165,8 @@ inline bool Registers_mips_newabi::validFloatRegister(int regNum) const { |
| 3159 | #ifdef __mips_hard_float | 3165 | #ifdef __mips_hard_float |
| 3160 | if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) | 3166 | if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) |
| 3161 | return true; | 3167 | return true; |
| 3168 | #else | ||
| 3169 | (void)regNum; | ||
| 3162 | #endif | 3170 | #endif |
| 3163 | return false; | 3171 | return false; |
| 3164 | } | 3172 | } |
| ... | @@ -3168,6 +3176,7 @@ inline double Registers_mips_newabi::getFloatRegister(int regNum) const { | ... | @@ -3168,6 +3176,7 @@ inline double Registers_mips_newabi::getFloatRegister(int regNum) const { |
| 3168 | assert(validFloatRegister(regNum)); | 3176 | assert(validFloatRegister(regNum)); |
| 3169 | return _floats[regNum - UNW_MIPS_F0]; | 3177 | return _floats[regNum - UNW_MIPS_F0]; |
| 3170 | #else | 3178 | #else |
| 3179 | (void)regNum; | ||
| 3171 | _LIBUNWIND_ABORT("mips_newabi float support not implemented"); | 3180 | _LIBUNWIND_ABORT("mips_newabi float support not implemented"); |
| 3172 | #endif | 3181 | #endif |
| 3173 | } | 3182 | } |
| ... | @@ -3178,6 +3187,8 @@ inline void Registers_mips_newabi::setFloatRegister(int regNum, | ... | @@ -3178,6 +3187,8 @@ inline void Registers_mips_newabi::setFloatRegister(int regNum, |
| 3178 | assert(validFloatRegister(regNum)); | 3187 | assert(validFloatRegister(regNum)); |
| 3179 | _floats[regNum - UNW_MIPS_F0] = value; | 3188 | _floats[regNum - UNW_MIPS_F0] = value; |
| 3180 | #else | 3189 | #else |
| 3190 | (void)regNum; | ||
| 3191 | (void)value; | ||
| 3181 | _LIBUNWIND_ABORT("mips_newabi float support not implemented"); | 3192 | _LIBUNWIND_ABORT("mips_newabi float support not implemented"); |
| 3182 | #endif | 3193 | #endif |
| 3183 | } | 3194 | } |
| ... | @@ -3518,6 +3529,187 @@ inline const char *Registers_sparc::getRegisterName(int regNum) { | ... | @@ -3518,6 +3529,187 @@ inline const char *Registers_sparc::getRegisterName(int regNum) { |
| 3518 | } | 3529 | } |
| 3519 | #endif // _LIBUNWIND_TARGET_SPARC | 3530 | #endif // _LIBUNWIND_TARGET_SPARC |
| 3520 | 3531 | ||
| 3532 | #if defined(_LIBUNWIND_TARGET_HEXAGON) | ||
| 3533 | /// Registers_hexagon holds the register state of a thread in a Hexagon QDSP6 | ||
| 3534 | /// process. | ||
| 3535 | class _LIBUNWIND_HIDDEN Registers_hexagon { | ||
| 3536 | public: | ||
| 3537 | Registers_hexagon(); | ||
| 3538 | Registers_hexagon(const void *registers); | ||
| 3539 | |||
| 3540 | bool validRegister(int num) const; | ||
| 3541 | uint32_t getRegister(int num) const; | ||
| 3542 | void setRegister(int num, uint32_t value); | ||
| 3543 | bool validFloatRegister(int num) const; | ||
| 3544 | double getFloatRegister(int num) const; | ||
| 3545 | void setFloatRegister(int num, double value); | ||
| 3546 | bool validVectorRegister(int num) const; | ||
| 3547 | v128 getVectorRegister(int num) const; | ||
| 3548 | void setVectorRegister(int num, v128 value); | ||
| 3549 | const char *getRegisterName(int num); | ||
| 3550 | void jumpto(); | ||
| 3551 | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON; } | ||
| 3552 | static int getArch() { return REGISTERS_HEXAGON; } | ||
| 3553 | |||
| 3554 | uint32_t getSP() const { return _registers.__r[UNW_HEXAGON_R29]; } | ||
| 3555 | void setSP(uint32_t value) { _registers.__r[UNW_HEXAGON_R29] = value; } | ||
| 3556 | uint32_t getIP() const { return _registers.__r[UNW_HEXAGON_PC]; } | ||
| 3557 | void setIP(uint32_t value) { _registers.__r[UNW_HEXAGON_PC] = value; } | ||
| 3558 | |||
| 3559 | private: | ||
| 3560 | struct hexagon_thread_state_t { | ||
| 3561 | unsigned int __r[35]; | ||
| 3562 | }; | ||
| 3563 | |||
| 3564 | hexagon_thread_state_t _registers; | ||
| 3565 | }; | ||
| 3566 | |||
| 3567 | inline Registers_hexagon::Registers_hexagon(const void *registers) { | ||
| 3568 | static_assert((check_fit<Registers_hexagon, unw_context_t>::does_fit), | ||
| 3569 | "hexagon registers do not fit into unw_context_t"); | ||
| 3570 | memcpy(&_registers, static_cast<const uint8_t *>(registers), | ||
| 3571 | sizeof(_registers)); | ||
| 3572 | } | ||
| 3573 | |||
| 3574 | inline Registers_hexagon::Registers_hexagon() { | ||
| 3575 | memset(&_registers, 0, sizeof(_registers)); | ||
| 3576 | } | ||
| 3577 | |||
| 3578 | inline bool Registers_hexagon::validRegister(int regNum) const { | ||
| 3579 | if (regNum <= UNW_HEXAGON_R31) | ||
| 3580 | return true; | ||
| 3581 | return false; | ||
| 3582 | } | ||
| 3583 | |||
| 3584 | inline uint32_t Registers_hexagon::getRegister(int regNum) const { | ||
| 3585 | if (regNum >= UNW_HEXAGON_R0 && regNum <= UNW_HEXAGON_R31) | ||
| 3586 | return _registers.__r[regNum - UNW_HEXAGON_R0]; | ||
| 3587 | |||
| 3588 | switch (regNum) { | ||
| 3589 | case UNW_REG_IP: | ||
| 3590 | return _registers.__r[UNW_HEXAGON_PC]; | ||
| 3591 | case UNW_REG_SP: | ||
| 3592 | return _registers.__r[UNW_HEXAGON_R29]; | ||
| 3593 | } | ||
| 3594 | _LIBUNWIND_ABORT("unsupported hexagon register"); | ||
| 3595 | } | ||
| 3596 | |||
| 3597 | inline void Registers_hexagon::setRegister(int regNum, uint32_t value) { | ||
| 3598 | if (regNum >= UNW_HEXAGON_R0 && regNum <= UNW_HEXAGON_R31) { | ||
| 3599 | _registers.__r[regNum - UNW_HEXAGON_R0] = value; | ||
| 3600 | return; | ||
| 3601 | } | ||
| 3602 | |||
| 3603 | switch (regNum) { | ||
| 3604 | case UNW_REG_IP: | ||
| 3605 | _registers.__r[UNW_HEXAGON_PC] = value; | ||
| 3606 | return; | ||
| 3607 | case UNW_REG_SP: | ||
| 3608 | _registers.__r[UNW_HEXAGON_R29] = value; | ||
| 3609 | return; | ||
| 3610 | } | ||
| 3611 | _LIBUNWIND_ABORT("unsupported hexagon register"); | ||
| 3612 | } | ||
| 3613 | |||
| 3614 | inline bool Registers_hexagon::validFloatRegister(int /* regNum */) const { | ||
| 3615 | return false; | ||
| 3616 | } | ||
| 3617 | |||
| 3618 | inline double Registers_hexagon::getFloatRegister(int /* regNum */) const { | ||
| 3619 | _LIBUNWIND_ABORT("hexagon float support not implemented"); | ||
| 3620 | } | ||
| 3621 | |||
| 3622 | inline void Registers_hexagon::setFloatRegister(int /* regNum */, | ||
| 3623 | double /* value */) { | ||
| 3624 | _LIBUNWIND_ABORT("hexagon float support not implemented"); | ||
| 3625 | } | ||
| 3626 | |||
| 3627 | inline bool Registers_hexagon::validVectorRegister(int /* regNum */) const { | ||
| 3628 | return false; | ||
| 3629 | } | ||
| 3630 | |||
| 3631 | inline v128 Registers_hexagon::getVectorRegister(int /* regNum */) const { | ||
| 3632 | _LIBUNWIND_ABORT("hexagon vector support not implemented"); | ||
| 3633 | } | ||
| 3634 | |||
| 3635 | inline void Registers_hexagon::setVectorRegister(int /* regNum */, v128 /* value */) { | ||
| 3636 | _LIBUNWIND_ABORT("hexagon vector support not implemented"); | ||
| 3637 | } | ||
| 3638 | |||
| 3639 | inline const char *Registers_hexagon::getRegisterName(int regNum) { | ||
| 3640 | switch (regNum) { | ||
| 3641 | case UNW_HEXAGON_R0: | ||
| 3642 | return "r0"; | ||
| 3643 | case UNW_HEXAGON_R1: | ||
| 3644 | return "r1"; | ||
| 3645 | case UNW_HEXAGON_R2: | ||
| 3646 | return "r2"; | ||
| 3647 | case UNW_HEXAGON_R3: | ||
| 3648 | return "r3"; | ||
| 3649 | case UNW_HEXAGON_R4: | ||
| 3650 | return "r4"; | ||
| 3651 | case UNW_HEXAGON_R5: | ||
| 3652 | return "r5"; | ||
| 3653 | case UNW_HEXAGON_R6: | ||
| 3654 | return "r6"; | ||
| 3655 | case UNW_HEXAGON_R7: | ||
| 3656 | return "r7"; | ||
| 3657 | case UNW_HEXAGON_R8: | ||
| 3658 | return "r8"; | ||
| 3659 | case UNW_HEXAGON_R9: | ||
| 3660 | return "r9"; | ||
| 3661 | case UNW_HEXAGON_R10: | ||
| 3662 | return "r10"; | ||
| 3663 | case UNW_HEXAGON_R11: | ||
| 3664 | return "r11"; | ||
| 3665 | case UNW_HEXAGON_R12: | ||
| 3666 | return "r12"; | ||
| 3667 | case UNW_HEXAGON_R13: | ||
| 3668 | return "r13"; | ||
| 3669 | case UNW_HEXAGON_R14: | ||
| 3670 | return "r14"; | ||
| 3671 | case UNW_HEXAGON_R15: | ||
| 3672 | return "r15"; | ||
| 3673 | case UNW_HEXAGON_R16: | ||
| 3674 | return "r16"; | ||
| 3675 | case UNW_HEXAGON_R17: | ||
| 3676 | return "r17"; | ||
| 3677 | case UNW_HEXAGON_R18: | ||
| 3678 | return "r18"; | ||
| 3679 | case UNW_HEXAGON_R19: | ||
| 3680 | return "r19"; | ||
| 3681 | case UNW_HEXAGON_R20: | ||
| 3682 | return "r20"; | ||
| 3683 | case UNW_HEXAGON_R21: | ||
| 3684 | return "r21"; | ||
| 3685 | case UNW_HEXAGON_R22: | ||
| 3686 | return "r22"; | ||
| 3687 | case UNW_HEXAGON_R23: | ||
| 3688 | return "r23"; | ||
| 3689 | case UNW_HEXAGON_R24: | ||
| 3690 | return "r24"; | ||
| 3691 | case UNW_HEXAGON_R25: | ||
| 3692 | return "r25"; | ||
| 3693 | case UNW_HEXAGON_R26: | ||
| 3694 | return "r26"; | ||
| 3695 | case UNW_HEXAGON_R27: | ||
| 3696 | return "r27"; | ||
| 3697 | case UNW_HEXAGON_R28: | ||
| 3698 | return "r28"; | ||
| 3699 | case UNW_HEXAGON_R29: | ||
| 3700 | return "r29"; | ||
| 3701 | case UNW_HEXAGON_R30: | ||
| 3702 | return "r30"; | ||
| 3703 | case UNW_HEXAGON_R31: | ||
| 3704 | return "r31"; | ||
| 3705 | default: | ||
| 3706 | return "unknown register"; | ||
| 3707 | } | ||
| 3708 | |||
| 3709 | } | ||
| 3710 | #endif // _LIBUNWIND_TARGET_HEXAGON | ||
| 3711 | |||
| 3712 | |||
| 3521 | #if defined(_LIBUNWIND_TARGET_RISCV) | 3713 | #if defined(_LIBUNWIND_TARGET_RISCV) |
| 3522 | /// Registers_riscv holds the register state of a thread in a 64-bit RISC-V | 3714 | /// Registers_riscv holds the register state of a thread in a 64-bit RISC-V |
| 3523 | /// process. | 3715 | /// process. |
| ... | @@ -3542,11 +3734,11 @@ public: | ... | @@ -3542,11 +3734,11 @@ public: |
| 3542 | 3734 | ||
| 3543 | uint64_t getSP() const { return _registers[2]; } | 3735 | uint64_t getSP() const { return _registers[2]; } |
| 3544 | void setSP(uint64_t value) { _registers[2] = value; } | 3736 | void setSP(uint64_t value) { _registers[2] = value; } |
| 3545 | uint64_t getIP() const { return _registers[1]; } | 3737 | uint64_t getIP() const { return _registers[0]; } |
| 3546 | void setIP(uint64_t value) { _registers[1] = value; } | 3738 | void setIP(uint64_t value) { _registers[0] = value; } |
| 3547 | 3739 | ||
| 3548 | private: | 3740 | private: |
| 3549 | 3741 | // _registers[0] holds the pc | |
| 3550 | uint64_t _registers[32]; | 3742 | uint64_t _registers[32]; |
| 3551 | double _floats[32]; | 3743 | double _floats[32]; |
| 3552 | }; | 3744 | }; |
| ... | @@ -3581,7 +3773,7 @@ inline bool Registers_riscv::validRegister(int regNum) const { | ... | @@ -3581,7 +3773,7 @@ inline bool Registers_riscv::validRegister(int regNum) const { |
| 3581 | 3773 | ||
| 3582 | inline uint64_t Registers_riscv::getRegister(int regNum) const { | 3774 | inline uint64_t Registers_riscv::getRegister(int regNum) const { |
| 3583 | if (regNum == UNW_REG_IP) | 3775 | if (regNum == UNW_REG_IP) |
| 3584 | return _registers[1]; | 3776 | return _registers[0]; |
| 3585 | if (regNum == UNW_REG_SP) | 3777 | if (regNum == UNW_REG_SP) |
| 3586 | return _registers[2]; | 3778 | return _registers[2]; |
| 3587 | if (regNum == UNW_RISCV_X0) | 3779 | if (regNum == UNW_RISCV_X0) |
| ... | @@ -3593,7 +3785,7 @@ inline uint64_t Registers_riscv::getRegister(int regNum) const { | ... | @@ -3593,7 +3785,7 @@ inline uint64_t Registers_riscv::getRegister(int regNum) const { |
| 3593 | 3785 | ||
| 3594 | inline void Registers_riscv::setRegister(int regNum, uint64_t value) { | 3786 | inline void Registers_riscv::setRegister(int regNum, uint64_t value) { |
| 3595 | if (regNum == UNW_REG_IP) | 3787 | if (regNum == UNW_REG_IP) |
| 3596 | _registers[1] = value; | 3788 | _registers[0] = value; |
| 3597 | else if (regNum == UNW_REG_SP) | 3789 | else if (regNum == UNW_REG_SP) |
| 3598 | _registers[2] = value; | 3790 | _registers[2] = value; |
| 3599 | else if (regNum == UNW_RISCV_X0) | 3791 | else if (regNum == UNW_RISCV_X0) |
| ... | @@ -3757,6 +3949,7 @@ inline double Registers_riscv::getFloatRegister(int regNum) const { | ... | @@ -3757,6 +3949,7 @@ inline double Registers_riscv::getFloatRegister(int regNum) const { |
| 3757 | assert(validFloatRegister(regNum)); | 3949 | assert(validFloatRegister(regNum)); |
| 3758 | return _floats[regNum - UNW_RISCV_F0]; | 3950 | return _floats[regNum - UNW_RISCV_F0]; |
| 3759 | #else | 3951 | #else |
| 3952 | (void)regNum; | ||
| 3760 | _LIBUNWIND_ABORT("libunwind not built with float support"); | 3953 | _LIBUNWIND_ABORT("libunwind not built with float support"); |
| 3761 | #endif | 3954 | #endif |
| 3762 | } | 3955 | } |
| ... | @@ -3766,6 +3959,8 @@ inline void Registers_riscv::setFloatRegister(int regNum, double value) { | ... | @@ -3766,6 +3959,8 @@ inline void Registers_riscv::setFloatRegister(int regNum, double value) { |
| 3766 | assert(validFloatRegister(regNum)); | 3959 | assert(validFloatRegister(regNum)); |
| 3767 | _floats[regNum - UNW_RISCV_F0] = value; | 3960 | _floats[regNum - UNW_RISCV_F0] = value; |
| 3768 | #else | 3961 | #else |
| 3962 | (void)regNum; | ||
| 3963 | (void)value; | ||
| 3769 | _LIBUNWIND_ABORT("libunwind not built with float support"); | 3964 | _LIBUNWIND_ABORT("libunwind not built with float support"); |
| 3770 | #endif | 3965 | #endif |
| 3771 | } | 3966 | } |
lib/libunwind/src/Unwind-EHABI.cpp+12-8| ... | @@ -31,10 +31,12 @@ namespace { | ... | @@ -31,10 +31,12 @@ namespace { |
| 31 | // signinficant byte. | 31 | // signinficant byte. |
| 32 | uint8_t getByte(const uint32_t* data, size_t offset) { | 32 | uint8_t getByte(const uint32_t* data, size_t offset) { |
| 33 | const uint8_t* byteData = reinterpret_cast<const uint8_t*>(data); | 33 | const uint8_t* byteData = reinterpret_cast<const uint8_t*>(data); |
| 34 | #ifdef __LITTLE_ENDIAN__ | 34 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ |
| 35 | return byteData[(offset & ~(size_t)0x03) + (3 - (offset & (size_t)0x03))]; | 35 | return byteData[(offset & ~(size_t)0x03) + (3 - (offset & (size_t)0x03))]; |
| 36 | #else | 36 | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
| 37 | return byteData[offset]; | 37 | return byteData[offset]; |
| 38 | #else | ||
| 39 | #error "Unable to determine endianess" | ||
| 38 | #endif | 40 | #endif |
| 39 | } | 41 | } |
| 40 | 42 | ||
| ... | @@ -481,8 +483,8 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except | ... | @@ -481,8 +483,8 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 481 | // If there is a personality routine, ask it if it will want to stop at | 483 | // If there is a personality routine, ask it if it will want to stop at |
| 482 | // this frame. | 484 | // this frame. |
| 483 | if (frameInfo.handler != 0) { | 485 | if (frameInfo.handler != 0) { |
| 484 | __personality_routine p = | 486 | _Unwind_Personality_Fn p = |
| 485 | (__personality_routine)(long)(frameInfo.handler); | 487 | (_Unwind_Personality_Fn)(long)(frameInfo.handler); |
| 486 | _LIBUNWIND_TRACE_UNWINDING( | 488 | _LIBUNWIND_TRACE_UNWINDING( |
| 487 | "unwind_phase1(ex_ojb=%p): calling personality function %p", | 489 | "unwind_phase1(ex_ojb=%p): calling personality function %p", |
| 488 | static_cast<void *>(exception_object), | 490 | static_cast<void *>(exception_object), |
| ... | @@ -597,8 +599,8 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor | ... | @@ -597,8 +599,8 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor |
| 597 | 599 | ||
| 598 | // If there is a personality routine, tell it we are unwinding. | 600 | // If there is a personality routine, tell it we are unwinding. |
| 599 | if (frameInfo.handler != 0) { | 601 | if (frameInfo.handler != 0) { |
| 600 | __personality_routine p = | 602 | _Unwind_Personality_Fn p = |
| 601 | (__personality_routine)(long)(frameInfo.handler); | 603 | (_Unwind_Personality_Fn)(long)(frameInfo.handler); |
| 602 | struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor); | 604 | struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor); |
| 603 | // EHABI #7.2 | 605 | // EHABI #7.2 |
| 604 | exception_object->pr_cache.fnstart = frameInfo.start_ip; | 606 | exception_object->pr_cache.fnstart = frameInfo.start_ip; |
| ... | @@ -943,10 +945,12 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, | ... | @@ -943,10 +945,12 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, |
| 943 | // SP is only 32-bit aligned so don't copy 64-bit at a time. | 945 | // SP is only 32-bit aligned so don't copy 64-bit at a time. |
| 944 | uint64_t w0 = *sp++; | 946 | uint64_t w0 = *sp++; |
| 945 | uint64_t w1 = *sp++; | 947 | uint64_t w1 = *sp++; |
| 946 | #ifdef __LITTLE_ENDIAN__ | 948 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ |
| 947 | uint64_t value = (w1 << 32) | w0; | 949 | uint64_t value = (w1 << 32) | w0; |
| 948 | #else | 950 | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
| 949 | uint64_t value = (w0 << 32) | w1; | 951 | uint64_t value = (w0 << 32) | w1; |
| 952 | #else | ||
| 953 | #error "Unable to determine endianess" | ||
| 950 | #endif | 954 | #endif |
| 951 | if (_Unwind_VRS_Set(context, regclass, i, representation, &value) != | 955 | if (_Unwind_VRS_Set(context, regclass, i, representation, &value) != |
| 952 | _UVRSR_OK) | 956 | _UVRSR_OK) |
lib/libunwind/src/Unwind-seh.cpp+3-3| ... | @@ -69,7 +69,7 @@ static void __unw_seh_set_disp_ctx(unw_cursor_t *cursor, | ... | @@ -69,7 +69,7 @@ static void __unw_seh_set_disp_ctx(unw_cursor_t *cursor, |
| 69 | /// b) Initiate a collided unwind to halt unwinding. | 69 | /// b) Initiate a collided unwind to halt unwinding. |
| 70 | _LIBUNWIND_EXPORT EXCEPTION_DISPOSITION | 70 | _LIBUNWIND_EXPORT EXCEPTION_DISPOSITION |
| 71 | _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, | 71 | _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, |
| 72 | DISPATCHER_CONTEXT *disp, __personality_routine pers) { | 72 | DISPATCHER_CONTEXT *disp, _Unwind_Personality_Fn pers) { |
| 73 | unw_cursor_t cursor; | 73 | unw_cursor_t cursor; |
| 74 | _Unwind_Exception *exc; | 74 | _Unwind_Exception *exc; |
| 75 | _Unwind_Action action; | 75 | _Unwind_Action action; |
| ... | @@ -290,8 +290,8 @@ unwind_phase2_forced(unw_context_t *uc, | ... | @@ -290,8 +290,8 @@ unwind_phase2_forced(unw_context_t *uc, |
| 290 | 290 | ||
| 291 | // If there is a personality routine, tell it we are unwinding. | 291 | // If there is a personality routine, tell it we are unwinding. |
| 292 | if (frameInfo.handler != 0) { | 292 | if (frameInfo.handler != 0) { |
| 293 | __personality_routine p = | 293 | _Unwind_Personality_Fn p = |
| 294 | (__personality_routine)(intptr_t)(frameInfo.handler); | 294 | (_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler); |
| 295 | _LIBUNWIND_TRACE_UNWINDING( | 295 | _LIBUNWIND_TRACE_UNWINDING( |
| 296 | "unwind_phase2_forced(ex_ojb=%p): calling personality function %p", | 296 | "unwind_phase2_forced(ex_ojb=%p): calling personality function %p", |
| 297 | (void *)exception_object, (void *)(uintptr_t)p); | 297 | (void *)exception_object, (void *)(uintptr_t)p); |
lib/libunwind/src/Unwind-sjlj.c+2-2| ... | @@ -39,7 +39,7 @@ struct _Unwind_FunctionContext { | ... | @@ -39,7 +39,7 @@ struct _Unwind_FunctionContext { |
| 39 | uint32_t resumeParameters[4]; | 39 | uint32_t resumeParameters[4]; |
| 40 | 40 | ||
| 41 | // set by calling function before registering | 41 | // set by calling function before registering |
| 42 | __personality_routine personality; // arm offset=24 | 42 | _Unwind_Personality_Fn personality; // arm offset=24 |
| 43 | uintptr_t lsda; // arm offset=28 | 43 | uintptr_t lsda; // arm offset=28 |
| 44 | 44 | ||
| 45 | // variable length array, contains registers to restore | 45 | // variable length array, contains registers to restore |
| ... | @@ -268,7 +268,7 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object, | ... | @@ -268,7 +268,7 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object, |
| 268 | 268 | ||
| 269 | // if there is a personality routine, tell it we are unwinding | 269 | // if there is a personality routine, tell it we are unwinding |
| 270 | if (c->personality != NULL) { | 270 | if (c->personality != NULL) { |
| 271 | __personality_routine p = (__personality_routine) c->personality; | 271 | _Unwind_Personality_Fn p = (_Unwind_Personality_Fn)c->personality; |
| 272 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " | 272 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " |
| 273 | "calling personality function %p", | 273 | "calling personality function %p", |
| 274 | (void *)exception_object, (void *)p); | 274 | (void *)exception_object, (void *)p); |
lib/libunwind/src/UnwindCursor.hpp+22-3| ... | @@ -1123,6 +1123,12 @@ private: | ... | @@ -1123,6 +1123,12 @@ private: |
| 1123 | } | 1123 | } |
| 1124 | #endif | 1124 | #endif |
| 1125 | 1125 | ||
| 1126 | #if defined (_LIBUNWIND_TARGET_HEXAGON) | ||
| 1127 | compact_unwind_encoding_t dwarfEncoding(Registers_hexagon &) const { | ||
| 1128 | return 0; | ||
| 1129 | } | ||
| 1130 | #endif | ||
| 1131 | |||
| 1126 | #if defined (_LIBUNWIND_TARGET_MIPS_O32) | 1132 | #if defined (_LIBUNWIND_TARGET_MIPS_O32) |
| 1127 | compact_unwind_encoding_t dwarfEncoding(Registers_mips_o32 &) const { | 1133 | compact_unwind_encoding_t dwarfEncoding(Registers_mips_o32 &) const { |
| 1128 | return 0; | 1134 | return 0; |
| ... | @@ -1269,7 +1275,7 @@ struct EHABISectionIterator { | ... | @@ -1269,7 +1275,7 @@ struct EHABISectionIterator { |
| 1269 | _Self operator+(size_t a) { _Self out = *this; out._i += a; return out; } | 1275 | _Self operator+(size_t a) { _Self out = *this; out._i += a; return out; } |
| 1270 | _Self operator-(size_t a) { assert(_i >= a); _Self out = *this; out._i -= a; return out; } | 1276 | _Self operator-(size_t a) { assert(_i >= a); _Self out = *this; out._i -= a; return out; } |
| 1271 | 1277 | ||
| 1272 | size_t operator-(const _Self& other) { return _i - other._i; } | 1278 | size_t operator-(const _Self& other) const { return _i - other._i; } |
| 1273 | 1279 | ||
| 1274 | bool operator==(const _Self& other) const { | 1280 | bool operator==(const _Self& other) const { |
| 1275 | assert(_addressSpace == other._addressSpace); | 1281 | assert(_addressSpace == other._addressSpace); |
| ... | @@ -1277,6 +1283,12 @@ struct EHABISectionIterator { | ... | @@ -1277,6 +1283,12 @@ struct EHABISectionIterator { |
| 1277 | return _i == other._i; | 1283 | return _i == other._i; |
| 1278 | } | 1284 | } |
| 1279 | 1285 | ||
| 1286 | bool operator!=(const _Self& other) const { | ||
| 1287 | assert(_addressSpace == other._addressSpace); | ||
| 1288 | assert(_sects == other._sects); | ||
| 1289 | return _i != other._i; | ||
| 1290 | } | ||
| 1291 | |||
| 1280 | typename A::pint_t operator*() const { return functionAddress(); } | 1292 | typename A::pint_t operator*() const { return functionAddress(); } |
| 1281 | 1293 | ||
| 1282 | typename A::pint_t functionAddress() const { | 1294 | typename A::pint_t functionAddress() const { |
| ... | @@ -1353,7 +1365,8 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection( | ... | @@ -1353,7 +1365,8 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection( |
| 1353 | 1365 | ||
| 1354 | // If the high bit is set, the exception handling table entry is inline inside | 1366 | // If the high bit is set, the exception handling table entry is inline inside |
| 1355 | // the index table entry on the second word (aka |indexDataAddr|). Otherwise, | 1367 | // the index table entry on the second word (aka |indexDataAddr|). Otherwise, |
| 1356 | // the table points at an offset in the exception handling table (section 5 EHABI). | 1368 | // the table points at an offset in the exception handling table (section 5 |
| 1369 | // EHABI). | ||
| 1357 | pint_t exceptionTableAddr; | 1370 | pint_t exceptionTableAddr; |
| 1358 | uint32_t exceptionTableData; | 1371 | uint32_t exceptionTableData; |
| 1359 | bool isSingleWordEHT; | 1372 | bool isSingleWordEHT; |
| ... | @@ -1452,7 +1465,7 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection( | ... | @@ -1452,7 +1465,7 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection( |
| 1452 | _info.unwind_info = exceptionTableAddr; | 1465 | _info.unwind_info = exceptionTableAddr; |
| 1453 | _info.lsda = lsda; | 1466 | _info.lsda = lsda; |
| 1454 | // flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0. | 1467 | // flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0. |
| 1455 | _info.flags = isSingleWordEHT ? 1 : 0 | scope32 ? 0x2 : 0; // Use enum? | 1468 | _info.flags = (isSingleWordEHT ? 1 : 0) | (scope32 ? 0x2 : 0); // Use enum? |
| 1456 | 1469 | ||
| 1457 | return true; | 1470 | return true; |
| 1458 | } | 1471 | } |
| ... | @@ -1847,6 +1860,12 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { | ... | @@ -1847,6 +1860,12 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { |
| 1847 | pc &= (pint_t)~0x1; | 1860 | pc &= (pint_t)~0x1; |
| 1848 | #endif | 1861 | #endif |
| 1849 | 1862 | ||
| 1863 | // Exit early if at the top of the stack. | ||
| 1864 | if (pc == 0) { | ||
| 1865 | _unwindInfoMissing = true; | ||
| 1866 | return; | ||
| 1867 | } | ||
| 1868 | |||
| 1850 | // If the last line of a function is a "throw" the compiler sometimes | 1869 | // If the last line of a function is a "throw" the compiler sometimes |
| 1851 | // emits no instructions after the call to __cxa_throw. This means | 1870 | // emits no instructions after the call to __cxa_throw. This means |
| 1852 | // the return address is actually the start of the next function. | 1871 | // the return address is actually the start of the next function. |
lib/libunwind/src/UnwindLevel1-gcc-ext.c+1-1| ... | @@ -149,7 +149,7 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) { | ... | @@ -149,7 +149,7 @@ _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) { |
| 149 | 149 | ||
| 150 | struct _Unwind_Context *context = (struct _Unwind_Context *)&cursor; | 150 | struct _Unwind_Context *context = (struct _Unwind_Context *)&cursor; |
| 151 | // Get and call the personality function to unwind the frame. | 151 | // Get and call the personality function to unwind the frame. |
| 152 | __personality_routine handler = (__personality_routine) frameInfo.handler; | 152 | _Unwind_Personality_Fn handler = (_Unwind_Personality_Fn)frameInfo.handler; |
| 153 | if (handler == NULL) { | 153 | if (handler == NULL) { |
| 154 | return _URC_END_OF_STACK; | 154 | return _URC_END_OF_STACK; |
| 155 | } | 155 | } |
lib/libunwind/src/UnwindLevel1.c+6-6| ... | @@ -90,8 +90,8 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except | ... | @@ -90,8 +90,8 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 90 | // If there is a personality routine, ask it if it will want to stop at | 90 | // If there is a personality routine, ask it if it will want to stop at |
| 91 | // this frame. | 91 | // this frame. |
| 92 | if (frameInfo.handler != 0) { | 92 | if (frameInfo.handler != 0) { |
| 93 | __personality_routine p = | 93 | _Unwind_Personality_Fn p = |
| 94 | (__personality_routine)(uintptr_t)(frameInfo.handler); | 94 | (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler); |
| 95 | _LIBUNWIND_TRACE_UNWINDING( | 95 | _LIBUNWIND_TRACE_UNWINDING( |
| 96 | "unwind_phase1(ex_ojb=%p): calling personality function %p", | 96 | "unwind_phase1(ex_ojb=%p): calling personality function %p", |
| 97 | (void *)exception_object, (void *)(uintptr_t)p); | 97 | (void *)exception_object, (void *)(uintptr_t)p); |
| ... | @@ -188,8 +188,8 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except | ... | @@ -188,8 +188,8 @@ unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 188 | 188 | ||
| 189 | // If there is a personality routine, tell it we are unwinding. | 189 | // If there is a personality routine, tell it we are unwinding. |
| 190 | if (frameInfo.handler != 0) { | 190 | if (frameInfo.handler != 0) { |
| 191 | __personality_routine p = | 191 | _Unwind_Personality_Fn p = |
| 192 | (__personality_routine)(uintptr_t)(frameInfo.handler); | 192 | (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler); |
| 193 | _Unwind_Action action = _UA_CLEANUP_PHASE; | 193 | _Unwind_Action action = _UA_CLEANUP_PHASE; |
| 194 | if (sp == exception_object->private_2) { | 194 | if (sp == exception_object->private_2) { |
| 195 | // Tell personality this was the frame it marked in phase 1. | 195 | // Tell personality this was the frame it marked in phase 1. |
| ... | @@ -294,8 +294,8 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, | ... | @@ -294,8 +294,8 @@ unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor, |
| 294 | 294 | ||
| 295 | // If there is a personality routine, tell it we are unwinding. | 295 | // If there is a personality routine, tell it we are unwinding. |
| 296 | if (frameInfo.handler != 0) { | 296 | if (frameInfo.handler != 0) { |
| 297 | __personality_routine p = | 297 | _Unwind_Personality_Fn p = |
| 298 | (__personality_routine)(intptr_t)(frameInfo.handler); | 298 | (_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler); |
| 299 | _LIBUNWIND_TRACE_UNWINDING( | 299 | _LIBUNWIND_TRACE_UNWINDING( |
| 300 | "unwind_phase2_forced(ex_ojb=%p): calling personality function %p", | 300 | "unwind_phase2_forced(ex_ojb=%p): calling personality function %p", |
| 301 | (void *)exception_object, (void *)(uintptr_t)p); | 301 | (void *)exception_object, (void *)(uintptr_t)p); |
lib/libunwind/src/UnwindRegistersRestore.S+44-2| ... | @@ -557,7 +557,7 @@ Lnovec: | ... | @@ -557,7 +557,7 @@ Lnovec: |
| 557 | lwz %r3, 20(%r3) // do r3 last | 557 | lwz %r3, 20(%r3) // do r3 last |
| 558 | bctr | 558 | bctr |
| 559 | 559 | ||
| 560 | #elif defined(__arm64__) || defined(__aarch64__) | 560 | #elif defined(__aarch64__) |
| 561 | 561 | ||
| 562 | // | 562 | // |
| 563 | // void libunwind::Registers_arm64::jumpto() | 563 | // void libunwind::Registers_arm64::jumpto() |
| ... | @@ -808,6 +808,48 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv) | ... | @@ -808,6 +808,48 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv) |
| 808 | l.jr r9 | 808 | l.jr r9 |
| 809 | l.nop | 809 | l.nop |
| 810 | 810 | ||
| 811 | #elif defined(__hexagon__) | ||
| 812 | # On entry: | ||
| 813 | # thread_state pointer is in r2 | ||
| 814 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind17Registers_hexagon6jumptoEv) | ||
| 815 | # | ||
| 816 | # void libunwind::Registers_hexagon::jumpto() | ||
| 817 | # | ||
| 818 | r8 = memw(r0+#32) | ||
| 819 | r9 = memw(r0+#36) | ||
| 820 | r10 = memw(r0+#40) | ||
| 821 | r11 = memw(r0+#44) | ||
| 822 | |||
| 823 | r12 = memw(r0+#48) | ||
| 824 | r13 = memw(r0+#52) | ||
| 825 | r14 = memw(r0+#56) | ||
| 826 | r15 = memw(r0+#60) | ||
| 827 | |||
| 828 | r16 = memw(r0+#64) | ||
| 829 | r17 = memw(r0+#68) | ||
| 830 | r18 = memw(r0+#72) | ||
| 831 | r19 = memw(r0+#76) | ||
| 832 | |||
| 833 | r20 = memw(r0+#80) | ||
| 834 | r21 = memw(r0+#84) | ||
| 835 | r22 = memw(r0+#88) | ||
| 836 | r23 = memw(r0+#92) | ||
| 837 | |||
| 838 | r24 = memw(r0+#96) | ||
| 839 | r25 = memw(r0+#100) | ||
| 840 | r26 = memw(r0+#104) | ||
| 841 | r27 = memw(r0+#108) | ||
| 842 | |||
| 843 | r28 = memw(r0+#112) | ||
| 844 | r29 = memw(r0+#116) | ||
| 845 | r30 = memw(r0+#120) | ||
| 846 | r31 = memw(r0+#132) | ||
| 847 | |||
| 848 | r1 = memw(r0+#128) | ||
| 849 | c4 = r1 // Predicate register | ||
| 850 | r1 = memw(r0+#4) | ||
| 851 | r0 = memw(r0) | ||
| 852 | jumpr r31 | ||
| 811 | #elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 | 853 | #elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 |
| 812 | 854 | ||
| 813 | // | 855 | // |
| ... | @@ -1075,7 +1117,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv) | ... | @@ -1075,7 +1117,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv) |
| 1075 | #endif | 1117 | #endif |
| 1076 | 1118 | ||
| 1077 | // x0 is zero | 1119 | // x0 is zero |
| 1078 | ld x1, (8 * 1)(a0) | 1120 | ld x1, (8 * 0)(a0) // restore pc into ra |
| 1079 | ld x2, (8 * 2)(a0) | 1121 | ld x2, (8 * 2)(a0) |
| 1080 | ld x3, (8 * 3)(a0) | 1122 | ld x3, (8 * 3)(a0) |
| 1081 | ld x4, (8 * 4)(a0) | 1123 | ld x4, (8 * 4)(a0) |
lib/libunwind/src/UnwindRegistersSave.S+48-2| ... | @@ -697,7 +697,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) | ... | @@ -697,7 +697,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 697 | blr | 697 | blr |
| 698 | 698 | ||
| 699 | 699 | ||
| 700 | #elif defined(__arm64__) || defined(__aarch64__) | 700 | #elif defined(__aarch64__) |
| 701 | 701 | ||
| 702 | // | 702 | // |
| 703 | // extern int __unw_getcontext(unw_context_t* thread_state) | 703 | // extern int __unw_getcontext(unw_context_t* thread_state) |
| ... | @@ -945,6 +945,52 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) | ... | @@ -945,6 +945,52 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 945 | # zero epcr | 945 | # zero epcr |
| 946 | l.sw 132(r3), r0 | 946 | l.sw 132(r3), r0 |
| 947 | 947 | ||
| 948 | #elif defined(__hexagon__) | ||
| 949 | # | ||
| 950 | # extern int unw_getcontext(unw_context_t* thread_state) | ||
| 951 | # | ||
| 952 | # On entry: | ||
| 953 | # thread_state pointer is in r0 | ||
| 954 | # | ||
| 955 | #define OFFSET(offset) (offset/4) | ||
| 956 | DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) | ||
| 957 | memw(r0+#32) = r8 | ||
| 958 | memw(r0+#36) = r9 | ||
| 959 | memw(r0+#40) = r10 | ||
| 960 | memw(r0+#44) = r11 | ||
| 961 | |||
| 962 | memw(r0+#48) = r12 | ||
| 963 | memw(r0+#52) = r13 | ||
| 964 | memw(r0+#56) = r14 | ||
| 965 | memw(r0+#60) = r15 | ||
| 966 | |||
| 967 | memw(r0+#64) = r16 | ||
| 968 | memw(r0+#68) = r17 | ||
| 969 | memw(r0+#72) = r18 | ||
| 970 | memw(r0+#76) = r19 | ||
| 971 | |||
| 972 | memw(r0+#80) = r20 | ||
| 973 | memw(r0+#84) = r21 | ||
| 974 | memw(r0+#88) = r22 | ||
| 975 | memw(r0+#92) = r23 | ||
| 976 | |||
| 977 | memw(r0+#96) = r24 | ||
| 978 | memw(r0+#100) = r25 | ||
| 979 | memw(r0+#104) = r26 | ||
| 980 | memw(r0+#108) = r27 | ||
| 981 | |||
| 982 | memw(r0+#112) = r28 | ||
| 983 | memw(r0+#116) = r29 | ||
| 984 | memw(r0+#120) = r30 | ||
| 985 | memw(r0+#124) = r31 | ||
| 986 | r1 = c4 // Predicate register | ||
| 987 | memw(r0+#128) = r1 | ||
| 988 | r1 = memw(r30) // *FP == Saved FP | ||
| 989 | r1 = r31 | ||
| 990 | memw(r0+#132) = r1 | ||
| 991 | |||
| 992 | jumpr r31 | ||
| 993 | |||
| 948 | #elif defined(__sparc__) | 994 | #elif defined(__sparc__) |
| 949 | 995 | ||
| 950 | # | 996 | # |
| ... | @@ -984,7 +1030,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) | ... | @@ -984,7 +1030,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 984 | # thread_state pointer is in a0 | 1030 | # thread_state pointer is in a0 |
| 985 | # | 1031 | # |
| 986 | DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) | 1032 | DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 987 | // x0 is zero | 1033 | sd x1, (8 * 0)(a0) // store ra as pc |
| 988 | sd x1, (8 * 1)(a0) | 1034 | sd x1, (8 * 1)(a0) |
| 989 | sd x2, (8 * 2)(a0) | 1035 | sd x2, (8 * 2)(a0) |
| 990 | sd x3, (8 * 3)(a0) | 1036 | sd x3, (8 * 3)(a0) |
lib/libunwind/src/Unwind_AppleExtras.cpp+1-1| ... | @@ -56,7 +56,7 @@ struct libgcc_object_info { | ... | @@ -56,7 +56,7 @@ struct libgcc_object_info { |
| 56 | __attribute__((visibility("default"))) const char sym##_tmp42 = 0; \ | 56 | __attribute__((visibility("default"))) const char sym##_tmp42 = 0; \ |
| 57 | extern const char sym##_tmp43 __asm("$ld$hide$os4.3$_" #sym ); \ | 57 | extern const char sym##_tmp43 __asm("$ld$hide$os4.3$_" #sym ); \ |
| 58 | __attribute__((visibility("default"))) const char sym##_tmp43 = 0; | 58 | __attribute__((visibility("default"))) const char sym##_tmp43 = 0; |
| 59 | #elif defined(__arm64__) | 59 | #elif defined(__aarch64__) |
| 60 | #define NOT_HERE_BEFORE_10_6(sym) | 60 | #define NOT_HERE_BEFORE_10_6(sym) |
| 61 | #define NEVER_HERE(sym) | 61 | #define NEVER_HERE(sym) |
| 62 | #else | 62 | #else |
lib/libunwind/src/assembly.h+8-1| ... | @@ -28,7 +28,7 @@ | ... | @@ -28,7 +28,7 @@ |
| 28 | #ifdef _ARCH_PWR8 | 28 | #ifdef _ARCH_PWR8 |
| 29 | #define PPC64_HAS_VMX | 29 | #define PPC64_HAS_VMX |
| 30 | #endif | 30 | #endif |
| 31 | #elif defined(__arm64__) | 31 | #elif defined(__APPLE__) && defined(__aarch64__) |
| 32 | #define SEPARATOR %% | 32 | #define SEPARATOR %% |
| 33 | #else | 33 | #else |
| 34 | #define SEPARATOR ; | 34 | #define SEPARATOR ; |
| ... | @@ -75,9 +75,16 @@ | ... | @@ -75,9 +75,16 @@ |
| 75 | #define EXPORT_SYMBOL(name) | 75 | #define EXPORT_SYMBOL(name) |
| 76 | #define HIDDEN_SYMBOL(name) .hidden name | 76 | #define HIDDEN_SYMBOL(name) .hidden name |
| 77 | #define WEAK_SYMBOL(name) .weak name | 77 | #define WEAK_SYMBOL(name) .weak name |
| 78 | |||
| 79 | #if defined(__hexagon__) | ||
| 80 | #define WEAK_ALIAS(name, aliasname) \ | ||
| 81 | WEAK_SYMBOL(aliasname) SEPARATOR \ | ||
| 82 | .equiv SYMBOL_NAME(aliasname), SYMBOL_NAME(name) | ||
| 83 | #else | ||
| 78 | #define WEAK_ALIAS(name, aliasname) \ | 84 | #define WEAK_ALIAS(name, aliasname) \ |
| 79 | WEAK_SYMBOL(aliasname) SEPARATOR \ | 85 | WEAK_SYMBOL(aliasname) SEPARATOR \ |
| 80 | SYMBOL_NAME(aliasname) = SYMBOL_NAME(name) | 86 | SYMBOL_NAME(aliasname) = SYMBOL_NAME(name) |
| 87 | #endif | ||
| 81 | 88 | ||
| 82 | #if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \ | 89 | #if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \ |
| 83 | defined(__linux__) | 90 | defined(__linux__) |
lib/libunwind/src/config.h+4-4| ... | @@ -102,9 +102,10 @@ | ... | @@ -102,9 +102,10 @@ |
| 102 | #if defined(__i386__) || defined(__x86_64__) || \ | 102 | #if defined(__i386__) || defined(__x86_64__) || \ |
| 103 | defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__) || \ | 103 | defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__) || \ |
| 104 | (!defined(__APPLE__) && defined(__arm__)) || \ | 104 | (!defined(__APPLE__) && defined(__arm__)) || \ |
| 105 | (defined(__arm64__) || defined(__aarch64__)) || \ | 105 | defined(__aarch64__) || \ |
| 106 | defined(__mips__) || \ | 106 | defined(__mips__) || \ |
| 107 | defined(__riscv) | 107 | defined(__riscv) || \ |
| 108 | defined(__hexagon__) | ||
| 108 | #if !defined(_LIBUNWIND_BUILD_SJLJ_APIS) | 109 | #if !defined(_LIBUNWIND_BUILD_SJLJ_APIS) |
| 109 | #define _LIBUNWIND_BUILD_ZERO_COST_APIS | 110 | #define _LIBUNWIND_BUILD_ZERO_COST_APIS |
| 110 | #endif | 111 | #endif |
| ... | @@ -122,8 +123,7 @@ | ... | @@ -122,8 +123,7 @@ |
| 122 | #else | 123 | #else |
| 123 | #define _LIBUNWIND_ABORT(msg) \ | 124 | #define _LIBUNWIND_ABORT(msg) \ |
| 124 | do { \ | 125 | do { \ |
| 125 | fprintf(stderr, "libunwind: %s %s:%d - %s\n", __func__, __FILE__, \ | 126 | fprintf(stderr, "libunwind: %s - %s\n", __func__, msg); \ |
| 126 | __LINE__, msg); \ | ||
| 127 | fflush(stderr); \ | 127 | fflush(stderr); \ |
| 128 | abort(); \ | 128 | abort(); \ |
| 129 | } while (0) | 129 | } while (0) |
lib/libunwind/src/libunwind.cpp+2| ... | @@ -50,6 +50,8 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor, | ... | @@ -50,6 +50,8 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor, |
| 50 | # define REGISTER_KIND Registers_arm | 50 | # define REGISTER_KIND Registers_arm |
| 51 | #elif defined(__or1k__) | 51 | #elif defined(__or1k__) |
| 52 | # define REGISTER_KIND Registers_or1k | 52 | # define REGISTER_KIND Registers_or1k |
| 53 | #elif defined(__hexagon__) | ||
| 54 | # define REGISTER_KIND Registers_hexagon | ||
| 53 | #elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 | 55 | #elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 |
| 54 | # define REGISTER_KIND Registers_mips_o32 | 56 | # define REGISTER_KIND Registers_mips_o32 |
| 55 | #elif defined(__mips64) | 57 | #elif defined(__mips64) |