| 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 | 23 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_OR1K 32 |
| 24 | 24 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_MIPS 65 |
| 25 | 25 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_SPARC 31 |
| 26 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_HEXAGON 34 | |
| 26 | 27 | #define _LIBUNWIND_HIGHEST_DWARF_REGISTER_RISCV 64 |
| 27 | 28 | |
| 28 | 29 | #if defined(_LIBUNWIND_IS_NATIVE_ONLY) |
| ... | ... | @@ -82,6 +83,12 @@ |
| 82 | 83 | # define _LIBUNWIND_CONTEXT_SIZE 16 |
| 83 | 84 | # define _LIBUNWIND_CURSOR_SIZE 24 |
| 84 | 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 | 92 | # elif defined(__mips__) |
| 86 | 93 | # if defined(_ABIO32) && _MIPS_SIM == _ABIO32 |
| 87 | 94 | # define _LIBUNWIND_TARGET_MIPS_O32 1 |
| ... | ... | @@ -142,6 +149,7 @@ |
| 142 | 149 | # define _LIBUNWIND_TARGET_MIPS_O32 1 |
| 143 | 150 | # define _LIBUNWIND_TARGET_MIPS_NEWABI 1 |
| 144 | 151 | # define _LIBUNWIND_TARGET_SPARC 1 |
| 152 | # define _LIBUNWIND_TARGET_HEXAGON 1 | |
| 145 | 153 | # define _LIBUNWIND_TARGET_RISCV 1 |
| 146 | 154 | # define _LIBUNWIND_CONTEXT_SIZE 167 |
| 147 | 155 | # define _LIBUNWIND_CURSOR_SIZE 179 |
lib/libunwind/include/libunwind.h+38| ... | ... | @@ -832,6 +832,44 @@ enum { |
| 832 | 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 | 873 | // RISC-V registers. These match the DWARF register numbers defined by section |
| 836 | 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 | 111 | _Unwind_Exception* exceptionObject, |
| 112 | 112 | struct _Unwind_Context* context); |
| 113 | 113 | |
| 114 | typedef _Unwind_Reason_Code (*__personality_routine) | |
| 115 | (_Unwind_State state, | |
| 116 | _Unwind_Exception* exceptionObject, | |
| 117 | struct _Unwind_Context* context); | |
| 114 | typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)( | |
| 115 | _Unwind_State state, _Unwind_Exception *exceptionObject, | |
| 116 | struct _Unwind_Context *context); | |
| 118 | 117 | #else |
| 119 | 118 | struct _Unwind_Context; // opaque |
| 120 | 119 | struct _Unwind_Exception; // forward declaration |
| ... | ... | @@ -150,12 +149,9 @@ typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) |
| 150 | 149 | struct _Unwind_Context* context, |
| 151 | 150 | void* stop_parameter ); |
| 152 | 151 | |
| 153 | typedef _Unwind_Reason_Code (*__personality_routine) | |
| 154 | (int version, | |
| 155 | _Unwind_Action actions, | |
| 156 | uint64_t exceptionClass, | |
| 157 | _Unwind_Exception* exceptionObject, | |
| 158 | struct _Unwind_Context* context); | |
| 152 | typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn)( | |
| 153 | int version, _Unwind_Action actions, uint64_t exceptionClass, | |
| 154 | _Unwind_Exception *exceptionObject, struct _Unwind_Context *context); | |
| 159 | 155 | #endif |
| 160 | 156 | |
| 161 | 157 | #ifdef __cplusplus |
| ... | ... | @@ -387,10 +383,9 @@ typedef struct _DISPATCHER_CONTEXT DISPATCHER_CONTEXT; |
| 387 | 383 | #endif |
| 388 | 384 | // This is the common wrapper for GCC-style personality functions with SEH. |
| 389 | 385 | extern EXCEPTION_DISPOSITION _GCC_specific_handler(EXCEPTION_RECORD *exc, |
| 390 | void *frame, | |
| 391 | CONTEXT *ctx, | |
| 386 | void *frame, CONTEXT *ctx, | |
| 392 | 387 | DISPATCHER_CONTEXT *disp, |
| 393 | __personality_routine pers); | |
| 388 | _Unwind_Personality_Fn pers); | |
| 394 | 389 | #endif |
| 395 | 390 | |
| 396 | 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 | 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 | 553 | inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, |
| 396 | 554 | UnwindInfoSections &info) { |
| 397 | 555 | #ifdef __APPLE__ |
| ... | ... | @@ -483,110 +641,8 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, |
| 483 | 641 | if (info.arm_section && info.arm_section_length) |
| 484 | 642 | return true; |
| 485 | 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 | 644 | dl_iterate_cb_data cb_data = {this, &info, targetAddr}; |
| 493 | int found = dl_iterate_phdr( | |
| 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); | |
| 645 | int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data); | |
| 590 | 646 | return static_cast<bool>(found); |
| 591 | 647 | #endif |
| 592 | 648 |
lib/libunwind/src/DwarfParser.hpp+87-42| ... | ... | @@ -77,6 +77,7 @@ public: |
| 77 | 77 | }; |
| 78 | 78 | struct RegisterLocation { |
| 79 | 79 | RegisterSavedWhere location; |
| 80 | bool initialStateSaved; | |
| 80 | 81 | int64_t value; |
| 81 | 82 | }; |
| 82 | 83 | /// Information about a frame layout and registers saved determined |
| ... | ... | @@ -90,6 +91,40 @@ public: |
| 90 | 91 | bool registersInOtherRegisters; |
| 91 | 92 | bool sameValueUsed; |
| 92 | 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 | 130 | struct PrologInfoStackEntry { |
| ... | ... | @@ -355,18 +390,30 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, |
| 355 | 390 | const FDE_Info &fdeInfo, |
| 356 | 391 | const CIE_Info &cieInfo, pint_t upToPC, |
| 357 | 392 | int arch, PrologInfo *results) { |
| 358 | // clear results | |
| 359 | memset(results, '\0', sizeof(PrologInfo)); | |
| 360 | 393 | PrologInfoStackEntry *rememberStack = NULL; |
| 361 | 394 | |
| 362 | 395 | // parse CIE then FDE instructions |
| 363 | return parseInstructions(addressSpace, cieInfo.cieInstructions, | |
| 364 | cieInfo.cieStart + cieInfo.cieLength, cieInfo, | |
| 365 | (pint_t)(-1), rememberStack, arch, results) && | |
| 366 | parseInstructions(addressSpace, fdeInfo.fdeInstructions, | |
| 367 | fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo, | |
| 368 | upToPC - fdeInfo.pcStart, rememberStack, arch, | |
| 369 | results); | |
| 396 | bool returnValue = | |
| 397 | parseInstructions(addressSpace, cieInfo.cieInstructions, | |
| 398 | cieInfo.cieStart + cieInfo.cieLength, cieInfo, | |
| 399 | (pint_t)(-1), rememberStack, arch, results) && | |
| 400 | parseInstructions(addressSpace, fdeInfo.fdeInstructions, | |
| 401 | fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo, | |
| 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 | 419 | /// "run" the DWARF instructions |
| ... | ... | @@ -378,7 +425,9 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 378 | 425 | int arch, PrologInfo *results) { |
| 379 | 426 | pint_t p = instructions; |
| 380 | 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 | 432 | _LIBUNWIND_TRACE_DWARF("parseInstructions(instructions=0x%0" PRIx64 ")\n", |
| 384 | 433 | static_cast<uint64_t>(instructionsEnd)); |
| ... | ... | @@ -431,8 +480,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 431 | 480 | "malformed DW_CFA_offset_extended DWARF unwind, reg too big"); |
| 432 | 481 | return false; |
| 433 | 482 | } |
| 434 | results->savedRegisters[reg].location = kRegisterInCFA; | |
| 435 | results->savedRegisters[reg].value = offset; | |
| 483 | results->setRegister(reg, kRegisterInCFA, offset, initialState); | |
| 436 | 484 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", " |
| 437 | 485 | "offset=%" PRId64 ")\n", |
| 438 | 486 | reg, offset); |
| ... | ... | @@ -444,7 +492,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 444 | 492 | "malformed DW_CFA_restore_extended DWARF unwind, reg too big"); |
| 445 | 493 | return false; |
| 446 | 494 | } |
| 447 | results->savedRegisters[reg] = initialState.savedRegisters[reg]; | |
| 495 | results->restoreRegisterToInitialState(reg, initialState); | |
| 448 | 496 | _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg); |
| 449 | 497 | break; |
| 450 | 498 | case DW_CFA_undefined: |
| ... | ... | @@ -454,7 +502,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 454 | 502 | "malformed DW_CFA_undefined DWARF unwind, reg too big"); |
| 455 | 503 | return false; |
| 456 | 504 | } |
| 457 | results->savedRegisters[reg].location = kRegisterUnused; | |
| 505 | results->setRegisterLocation(reg, kRegisterUnused, initialState); | |
| 458 | 506 | _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg); |
| 459 | 507 | break; |
| 460 | 508 | case DW_CFA_same_value: |
| ... | ... | @@ -468,7 +516,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 468 | 516 | // "same value" means register was stored in frame, but its current |
| 469 | 517 | // value has not changed, so no need to restore from frame. |
| 470 | 518 | // We model this as if the register was never saved. |
| 471 | results->savedRegisters[reg].location = kRegisterUnused; | |
| 519 | results->setRegisterLocation(reg, kRegisterUnused, initialState); | |
| 472 | 520 | // set flag to disable conversion to compact unwind |
| 473 | 521 | results->sameValueUsed = true; |
| 474 | 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 | 534 | "malformed DW_CFA_register DWARF unwind, reg2 too big"); |
| 487 | 535 | return false; |
| 488 | 536 | } |
| 489 | results->savedRegisters[reg].location = kRegisterInRegister; | |
| 490 | results->savedRegisters[reg].value = (int64_t)reg2; | |
| 537 | results->setRegister(reg, kRegisterInRegister, (int64_t)reg2, | |
| 538 | initialState); | |
| 491 | 539 | // set flag to disable conversion to compact unwind |
| 492 | 540 | results->registersInOtherRegisters = true; |
| 493 | 541 | _LIBUNWIND_TRACE_DWARF( |
| ... | ... | @@ -564,8 +612,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 564 | 612 | "malformed DW_CFA_expression DWARF unwind, reg too big"); |
| 565 | 613 | return false; |
| 566 | 614 | } |
| 567 | results->savedRegisters[reg].location = kRegisterAtExpression; | |
| 568 | results->savedRegisters[reg].value = (int64_t)p; | |
| 615 | results->setRegister(reg, kRegisterAtExpression, (int64_t)p, | |
| 616 | initialState); | |
| 569 | 617 | length = addressSpace.getULEB128(p, instructionsEnd); |
| 570 | 618 | assert(length < static_cast<pint_t>(~0) && "pointer overflow"); |
| 571 | 619 | p += static_cast<pint_t>(length); |
| ... | ... | @@ -583,8 +631,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 583 | 631 | } |
| 584 | 632 | offset = |
| 585 | 633 | addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; |
| 586 | results->savedRegisters[reg].location = kRegisterInCFA; | |
| 587 | results->savedRegisters[reg].value = offset; | |
| 634 | results->setRegister(reg, kRegisterInCFA, offset, initialState); | |
| 588 | 635 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64 ", " |
| 589 | 636 | "offset=%" PRId64 ")\n", |
| 590 | 637 | reg, offset); |
| ... | ... | @@ -622,8 +669,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 622 | 669 | } |
| 623 | 670 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) |
| 624 | 671 | * cieInfo.dataAlignFactor; |
| 625 | results->savedRegisters[reg].location = kRegisterOffsetFromCFA; | |
| 626 | results->savedRegisters[reg].value = offset; | |
| 672 | results->setRegister(reg, kRegisterOffsetFromCFA, offset, initialState); | |
| 627 | 673 | _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64 ", " |
| 628 | 674 | "offset=%" PRId64 "\n", |
| 629 | 675 | reg, offset); |
| ... | ... | @@ -637,8 +683,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 637 | 683 | } |
| 638 | 684 | offset = |
| 639 | 685 | addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; |
| 640 | results->savedRegisters[reg].location = kRegisterOffsetFromCFA; | |
| 641 | results->savedRegisters[reg].value = offset; | |
| 686 | results->setRegister(reg, kRegisterOffsetFromCFA, offset, initialState); | |
| 642 | 687 | _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64 ", " |
| 643 | 688 | "offset=%" PRId64 "\n", |
| 644 | 689 | reg, offset); |
| ... | ... | @@ -650,8 +695,8 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 650 | 695 | "malformed DW_CFA_val_expression DWARF unwind, reg too big"); |
| 651 | 696 | return false; |
| 652 | 697 | } |
| 653 | results->savedRegisters[reg].location = kRegisterIsExpression; | |
| 654 | results->savedRegisters[reg].value = (int64_t)p; | |
| 698 | results->setRegister(reg, kRegisterIsExpression, (int64_t)p, | |
| 699 | initialState); | |
| 655 | 700 | length = addressSpace.getULEB128(p, instructionsEnd); |
| 656 | 701 | assert(length < static_cast<pint_t>(~0) && "pointer overflow"); |
| 657 | 702 | p += static_cast<pint_t>(length); |
| ... | ... | @@ -673,8 +718,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 673 | 718 | } |
| 674 | 719 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) |
| 675 | 720 | * cieInfo.dataAlignFactor; |
| 676 | results->savedRegisters[reg].location = kRegisterInCFA; | |
| 677 | results->savedRegisters[reg].value = -offset; | |
| 721 | results->setRegister(reg, kRegisterInCFA, -offset, initialState); | |
| 678 | 722 | _LIBUNWIND_TRACE_DWARF( |
| 679 | 723 | "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset); |
| 680 | 724 | break; |
| ... | ... | @@ -687,25 +731,27 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 687 | 731 | case DW_CFA_AARCH64_negate_ra_state: |
| 688 | 732 | switch (arch) { |
| 689 | 733 | #if defined(_LIBUNWIND_TARGET_AARCH64) |
| 690 | case REGISTERS_ARM64: | |
| 691 | results->savedRegisters[UNW_ARM64_RA_SIGN_STATE].value ^= 0x1; | |
| 692 | _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n"); | |
| 693 | break; | |
| 734 | case REGISTERS_ARM64: { | |
| 735 | int64_t value = | |
| 736 | results->savedRegisters[UNW_ARM64_RA_SIGN_STATE].value ^ 0x1; | |
| 737 | results->setRegisterValue(UNW_ARM64_RA_SIGN_STATE, value, initialState); | |
| 738 | _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n"); | |
| 739 | } break; | |
| 694 | 740 | #endif |
| 741 | ||
| 695 | 742 | #if defined(_LIBUNWIND_TARGET_SPARC) |
| 696 | 743 | // case DW_CFA_GNU_window_save: |
| 697 | 744 | case REGISTERS_SPARC: |
| 698 | 745 | _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n"); |
| 699 | 746 | for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) { |
| 700 | results->savedRegisters[reg].location = kRegisterInRegister; | |
| 701 | results->savedRegisters[reg].value = | |
| 702 | ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0; | |
| 747 | results->setRegister(reg, kRegisterInRegister, | |
| 748 | ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0, | |
| 749 | initialState); | |
| 703 | 750 | } |
| 704 | 751 | |
| 705 | 752 | for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) { |
| 706 | results->savedRegisters[reg].location = kRegisterInCFA; | |
| 707 | results->savedRegisters[reg].value = | |
| 708 | ((int64_t)reg - UNW_SPARC_L0) * 4; | |
| 753 | results->setRegister(reg, kRegisterInCFA, | |
| 754 | ((int64_t)reg - UNW_SPARC_L0) * 4, initialState); | |
| 709 | 755 | } |
| 710 | 756 | break; |
| 711 | 757 | #endif |
| ... | ... | @@ -728,8 +774,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 728 | 774 | } |
| 729 | 775 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) |
| 730 | 776 | * cieInfo.dataAlignFactor; |
| 731 | results->savedRegisters[reg].location = kRegisterInCFA; | |
| 732 | results->savedRegisters[reg].value = offset; | |
| 777 | results->setRegister(reg, kRegisterInCFA, offset, initialState); | |
| 733 | 778 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n", |
| 734 | 779 | operand, offset); |
| 735 | 780 | break; |
| ... | ... | @@ -746,7 +791,7 @@ bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, |
| 746 | 791 | reg); |
| 747 | 792 | return false; |
| 748 | 793 | } |
| 749 | results->savedRegisters[reg] = initialState.savedRegisters[reg]; | |
| 794 | results->restoreRegisterToInitialState(reg, initialState); | |
| 750 | 795 | _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n", |
| 751 | 796 | static_cast<uint64_t>(operand)); |
| 752 | 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 | 109 | hdrInfo)) |
| 110 | 110 | return false; |
| 111 | 111 | |
| 112 | if (hdrInfo.fde_count == 0) return false; | |
| 113 | ||
| 112 | 114 | size_t tableEntrySize = getTableEntrySize(hdrInfo.table_enc); |
| 113 | 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 | 34 | REGISTERS_MIPS_O32, |
| 35 | 35 | REGISTERS_MIPS_NEWABI, |
| 36 | 36 | REGISTERS_SPARC, |
| 37 | REGISTERS_HEXAGON, | |
| 37 | 38 | REGISTERS_RISCV, |
| 38 | 39 | }; |
| 39 | 40 | |
| ... | ... | @@ -2869,6 +2870,8 @@ inline bool Registers_mips_o32::validFloatRegister(int regNum) const { |
| 2869 | 2870 | #if defined(__mips_hard_float) && __mips_fpr == 64 |
| 2870 | 2871 | if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) |
| 2871 | 2872 | return true; |
| 2873 | #else | |
| 2874 | (void)regNum; | |
| 2872 | 2875 | #endif |
| 2873 | 2876 | return false; |
| 2874 | 2877 | } |
| ... | ... | @@ -2878,6 +2881,7 @@ inline double Registers_mips_o32::getFloatRegister(int regNum) const { |
| 2878 | 2881 | assert(validFloatRegister(regNum)); |
| 2879 | 2882 | return _floats[regNum - UNW_MIPS_F0]; |
| 2880 | 2883 | #else |
| 2884 | (void)regNum; | |
| 2881 | 2885 | _LIBUNWIND_ABORT("mips_o32 float support not implemented"); |
| 2882 | 2886 | #endif |
| 2883 | 2887 | } |
| ... | ... | @@ -2888,6 +2892,8 @@ inline void Registers_mips_o32::setFloatRegister(int regNum, |
| 2888 | 2892 | assert(validFloatRegister(regNum)); |
| 2889 | 2893 | _floats[regNum - UNW_MIPS_F0] = value; |
| 2890 | 2894 | #else |
| 2895 | (void)regNum; | |
| 2896 | (void)value; | |
| 2891 | 2897 | _LIBUNWIND_ABORT("mips_o32 float support not implemented"); |
| 2892 | 2898 | #endif |
| 2893 | 2899 | } |
| ... | ... | @@ -3159,6 +3165,8 @@ inline bool Registers_mips_newabi::validFloatRegister(int regNum) const { |
| 3159 | 3165 | #ifdef __mips_hard_float |
| 3160 | 3166 | if (regNum >= UNW_MIPS_F0 && regNum <= UNW_MIPS_F31) |
| 3161 | 3167 | return true; |
| 3168 | #else | |
| 3169 | (void)regNum; | |
| 3162 | 3170 | #endif |
| 3163 | 3171 | return false; |
| 3164 | 3172 | } |
| ... | ... | @@ -3168,6 +3176,7 @@ inline double Registers_mips_newabi::getFloatRegister(int regNum) const { |
| 3168 | 3176 | assert(validFloatRegister(regNum)); |
| 3169 | 3177 | return _floats[regNum - UNW_MIPS_F0]; |
| 3170 | 3178 | #else |
| 3179 | (void)regNum; | |
| 3171 | 3180 | _LIBUNWIND_ABORT("mips_newabi float support not implemented"); |
| 3172 | 3181 | #endif |
| 3173 | 3182 | } |
| ... | ... | @@ -3178,6 +3187,8 @@ inline void Registers_mips_newabi::setFloatRegister(int regNum, |
| 3178 | 3187 | assert(validFloatRegister(regNum)); |
| 3179 | 3188 | _floats[regNum - UNW_MIPS_F0] = value; |
| 3180 | 3189 | #else |
| 3190 | (void)regNum; | |
| 3191 | (void)value; | |
| 3181 | 3192 | _LIBUNWIND_ABORT("mips_newabi float support not implemented"); |
| 3182 | 3193 | #endif |
| 3183 | 3194 | } |
| ... | ... | @@ -3518,6 +3529,187 @@ inline const char *Registers_sparc::getRegisterName(int regNum) { |
| 3518 | 3529 | } |
| 3519 | 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 | 3713 | #if defined(_LIBUNWIND_TARGET_RISCV) |
| 3522 | 3714 | /// Registers_riscv holds the register state of a thread in a 64-bit RISC-V |
| 3523 | 3715 | /// process. |
| ... | ... | @@ -3542,11 +3734,11 @@ public: |
| 3542 | 3734 | |
| 3543 | 3735 | uint64_t getSP() const { return _registers[2]; } |
| 3544 | 3736 | void setSP(uint64_t value) { _registers[2] = value; } |
| 3545 | uint64_t getIP() const { return _registers[1]; } | |
| 3546 | void setIP(uint64_t value) { _registers[1] = value; } | |
| 3737 | uint64_t getIP() const { return _registers[0]; } | |
| 3738 | void setIP(uint64_t value) { _registers[0] = value; } | |
| 3547 | 3739 | |
| 3548 | 3740 | private: |
| 3549 | ||
| 3741 | // _registers[0] holds the pc | |
| 3550 | 3742 | uint64_t _registers[32]; |
| 3551 | 3743 | double _floats[32]; |
| 3552 | 3744 | }; |
| ... | ... | @@ -3581,7 +3773,7 @@ inline bool Registers_riscv::validRegister(int regNum) const { |
| 3581 | 3773 | |
| 3582 | 3774 | inline uint64_t Registers_riscv::getRegister(int regNum) const { |
| 3583 | 3775 | if (regNum == UNW_REG_IP) |
| 3584 | return _registers[1]; | |
| 3776 | return _registers[0]; | |
| 3585 | 3777 | if (regNum == UNW_REG_SP) |
| 3586 | 3778 | return _registers[2]; |
| 3587 | 3779 | if (regNum == UNW_RISCV_X0) |
| ... | ... | @@ -3593,7 +3785,7 @@ inline uint64_t Registers_riscv::getRegister(int regNum) const { |
| 3593 | 3785 | |
| 3594 | 3786 | inline void Registers_riscv::setRegister(int regNum, uint64_t value) { |
| 3595 | 3787 | if (regNum == UNW_REG_IP) |
| 3596 | _registers[1] = value; | |
| 3788 | _registers[0] = value; | |
| 3597 | 3789 | else if (regNum == UNW_REG_SP) |
| 3598 | 3790 | _registers[2] = value; |
| 3599 | 3791 | else if (regNum == UNW_RISCV_X0) |
| ... | ... | @@ -3757,6 +3949,7 @@ inline double Registers_riscv::getFloatRegister(int regNum) const { |
| 3757 | 3949 | assert(validFloatRegister(regNum)); |
| 3758 | 3950 | return _floats[regNum - UNW_RISCV_F0]; |
| 3759 | 3951 | #else |
| 3952 | (void)regNum; | |
| 3760 | 3953 | _LIBUNWIND_ABORT("libunwind not built with float support"); |
| 3761 | 3954 | #endif |
| 3762 | 3955 | } |
| ... | ... | @@ -3766,6 +3959,8 @@ inline void Registers_riscv::setFloatRegister(int regNum, double value) { |
| 3766 | 3959 | assert(validFloatRegister(regNum)); |
| 3767 | 3960 | _floats[regNum - UNW_RISCV_F0] = value; |
| 3768 | 3961 | #else |
| 3962 | (void)regNum; | |
| 3963 | (void)value; | |
| 3769 | 3964 | _LIBUNWIND_ABORT("libunwind not built with float support"); |
| 3770 | 3965 | #endif |
| 3771 | 3966 | } |
lib/libunwind/src/Unwind-EHABI.cpp+12-8| ... | ... | @@ -31,10 +31,12 @@ namespace { |
| 31 | 31 | // signinficant byte. |
| 32 | 32 | uint8_t getByte(const uint32_t* data, size_t offset) { |
| 33 | 33 | const uint8_t* byteData = reinterpret_cast<const uint8_t*>(data); |
| 34 | #ifdef __LITTLE_ENDIAN__ | |
| 34 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | |
| 35 | 35 | return byteData[(offset & ~(size_t)0x03) + (3 - (offset & (size_t)0x03))]; |
| 36 | #else | |
| 36 | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ | |
| 37 | 37 | return byteData[offset]; |
| 38 | #else | |
| 39 | #error "Unable to determine endianess" | |
| 38 | 40 | #endif |
| 39 | 41 | } |
| 40 | 42 | |
| ... | ... | @@ -481,8 +483,8 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 481 | 483 | // If there is a personality routine, ask it if it will want to stop at |
| 482 | 484 | // this frame. |
| 483 | 485 | if (frameInfo.handler != 0) { |
| 484 | __personality_routine p = | |
| 485 | (__personality_routine)(long)(frameInfo.handler); | |
| 486 | _Unwind_Personality_Fn p = | |
| 487 | (_Unwind_Personality_Fn)(long)(frameInfo.handler); | |
| 486 | 488 | _LIBUNWIND_TRACE_UNWINDING( |
| 487 | 489 | "unwind_phase1(ex_ojb=%p): calling personality function %p", |
| 488 | 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 | 599 | |
| 598 | 600 | // If there is a personality routine, tell it we are unwinding. |
| 599 | 601 | if (frameInfo.handler != 0) { |
| 600 | __personality_routine p = | |
| 601 | (__personality_routine)(long)(frameInfo.handler); | |
| 602 | _Unwind_Personality_Fn p = | |
| 603 | (_Unwind_Personality_Fn)(long)(frameInfo.handler); | |
| 602 | 604 | struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor); |
| 603 | 605 | // EHABI #7.2 |
| 604 | 606 | exception_object->pr_cache.fnstart = frameInfo.start_ip; |
| ... | ... | @@ -943,10 +945,12 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass, |
| 943 | 945 | // SP is only 32-bit aligned so don't copy 64-bit at a time. |
| 944 | 946 | uint64_t w0 = *sp++; |
| 945 | 947 | uint64_t w1 = *sp++; |
| 946 | #ifdef __LITTLE_ENDIAN__ | |
| 948 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | |
| 947 | 949 | uint64_t value = (w1 << 32) | w0; |
| 948 | #else | |
| 950 | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ | |
| 949 | 951 | uint64_t value = (w0 << 32) | w1; |
| 952 | #else | |
| 953 | #error "Unable to determine endianess" | |
| 950 | 954 | #endif |
| 951 | 955 | if (_Unwind_VRS_Set(context, regclass, i, representation, &value) != |
| 952 | 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 | 69 | /// b) Initiate a collided unwind to halt unwinding. |
| 70 | 70 | _LIBUNWIND_EXPORT EXCEPTION_DISPOSITION |
| 71 | 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 | 73 | unw_cursor_t cursor; |
| 74 | 74 | _Unwind_Exception *exc; |
| 75 | 75 | _Unwind_Action action; |
| ... | ... | @@ -290,8 +290,8 @@ unwind_phase2_forced(unw_context_t *uc, |
| 290 | 290 | |
| 291 | 291 | // If there is a personality routine, tell it we are unwinding. |
| 292 | 292 | if (frameInfo.handler != 0) { |
| 293 | __personality_routine p = | |
| 294 | (__personality_routine)(intptr_t)(frameInfo.handler); | |
| 293 | _Unwind_Personality_Fn p = | |
| 294 | (_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler); | |
| 295 | 295 | _LIBUNWIND_TRACE_UNWINDING( |
| 296 | 296 | "unwind_phase2_forced(ex_ojb=%p): calling personality function %p", |
| 297 | 297 | (void *)exception_object, (void *)(uintptr_t)p); |
lib/libunwind/src/Unwind-sjlj.c+2-2| ... | ... | @@ -39,7 +39,7 @@ struct _Unwind_FunctionContext { |
| 39 | 39 | uint32_t resumeParameters[4]; |
| 40 | 40 | |
| 41 | 41 | // set by calling function before registering |
| 42 | __personality_routine personality; // arm offset=24 | |
| 42 | _Unwind_Personality_Fn personality; // arm offset=24 | |
| 43 | 43 | uintptr_t lsda; // arm offset=28 |
| 44 | 44 | |
| 45 | 45 | // variable length array, contains registers to restore |
| ... | ... | @@ -268,7 +268,7 @@ unwind_phase2_forced(struct _Unwind_Exception *exception_object, |
| 268 | 268 | |
| 269 | 269 | // if there is a personality routine, tell it we are unwinding |
| 270 | 270 | if (c->personality != NULL) { |
| 271 | __personality_routine p = (__personality_routine) c->personality; | |
| 271 | _Unwind_Personality_Fn p = (_Unwind_Personality_Fn)c->personality; | |
| 272 | 272 | _LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): " |
| 273 | 273 | "calling personality function %p", |
| 274 | 274 | (void *)exception_object, (void *)p); |
lib/libunwind/src/UnwindCursor.hpp+22-3| ... | ... | @@ -1123,6 +1123,12 @@ private: |
| 1123 | 1123 | } |
| 1124 | 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 | 1132 | #if defined (_LIBUNWIND_TARGET_MIPS_O32) |
| 1127 | 1133 | compact_unwind_encoding_t dwarfEncoding(Registers_mips_o32 &) const { |
| 1128 | 1134 | return 0; |
| ... | ... | @@ -1269,7 +1275,7 @@ struct EHABISectionIterator { |
| 1269 | 1275 | _Self operator+(size_t a) { _Self out = *this; out._i += a; return out; } |
| 1270 | 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 | 1280 | bool operator==(const _Self& other) const { |
| 1275 | 1281 | assert(_addressSpace == other._addressSpace); |
| ... | ... | @@ -1277,6 +1283,12 @@ struct EHABISectionIterator { |
| 1277 | 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 | 1292 | typename A::pint_t operator*() const { return functionAddress(); } |
| 1281 | 1293 | |
| 1282 | 1294 | typename A::pint_t functionAddress() const { |
| ... | ... | @@ -1353,7 +1365,8 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection( |
| 1353 | 1365 | |
| 1354 | 1366 | // If the high bit is set, the exception handling table entry is inline inside |
| 1355 | 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 | 1370 | pint_t exceptionTableAddr; |
| 1358 | 1371 | uint32_t exceptionTableData; |
| 1359 | 1372 | bool isSingleWordEHT; |
| ... | ... | @@ -1452,7 +1465,7 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection( |
| 1452 | 1465 | _info.unwind_info = exceptionTableAddr; |
| 1453 | 1466 | _info.lsda = lsda; |
| 1454 | 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 | 1470 | return true; |
| 1458 | 1471 | } |
| ... | ... | @@ -1847,6 +1860,12 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { |
| 1847 | 1860 | pc &= (pint_t)~0x1; |
| 1848 | 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 | 1869 | // If the last line of a function is a "throw" the compiler sometimes |
| 1851 | 1870 | // emits no instructions after the call to __cxa_throw. This means |
| 1852 | 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 | 149 | |
| 150 | 150 | struct _Unwind_Context *context = (struct _Unwind_Context *)&cursor; |
| 151 | 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 | 153 | if (handler == NULL) { |
| 154 | 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 | 90 | // If there is a personality routine, ask it if it will want to stop at |
| 91 | 91 | // this frame. |
| 92 | 92 | if (frameInfo.handler != 0) { |
| 93 | __personality_routine p = | |
| 94 | (__personality_routine)(uintptr_t)(frameInfo.handler); | |
| 93 | _Unwind_Personality_Fn p = | |
| 94 | (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler); | |
| 95 | 95 | _LIBUNWIND_TRACE_UNWINDING( |
| 96 | 96 | "unwind_phase1(ex_ojb=%p): calling personality function %p", |
| 97 | 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 | 188 | |
| 189 | 189 | // If there is a personality routine, tell it we are unwinding. |
| 190 | 190 | if (frameInfo.handler != 0) { |
| 191 | __personality_routine p = | |
| 192 | (__personality_routine)(uintptr_t)(frameInfo.handler); | |
| 191 | _Unwind_Personality_Fn p = | |
| 192 | (_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler); | |
| 193 | 193 | _Unwind_Action action = _UA_CLEANUP_PHASE; |
| 194 | 194 | if (sp == exception_object->private_2) { |
| 195 | 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 | 294 | |
| 295 | 295 | // If there is a personality routine, tell it we are unwinding. |
| 296 | 296 | if (frameInfo.handler != 0) { |
| 297 | __personality_routine p = | |
| 298 | (__personality_routine)(intptr_t)(frameInfo.handler); | |
| 297 | _Unwind_Personality_Fn p = | |
| 298 | (_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler); | |
| 299 | 299 | _LIBUNWIND_TRACE_UNWINDING( |
| 300 | 300 | "unwind_phase2_forced(ex_ojb=%p): calling personality function %p", |
| 301 | 301 | (void *)exception_object, (void *)(uintptr_t)p); |
lib/libunwind/src/UnwindRegistersRestore.S+44-2| ... | ... | @@ -557,7 +557,7 @@ Lnovec: |
| 557 | 557 | lwz %r3, 20(%r3) // do r3 last |
| 558 | 558 | bctr |
| 559 | 559 | |
| 560 | #elif defined(__arm64__) || defined(__aarch64__) | |
| 560 | #elif defined(__aarch64__) | |
| 561 | 561 | |
| 562 | 562 | // |
| 563 | 563 | // void libunwind::Registers_arm64::jumpto() |
| ... | ... | @@ -808,6 +808,48 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind14Registers_or1k6jumptoEv) |
| 808 | 808 | l.jr r9 |
| 809 | 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 | 853 | #elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 |
| 812 | 854 | |
| 813 | 855 | // |
| ... | ... | @@ -1075,7 +1117,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_riscv6jumptoEv) |
| 1075 | 1117 | #endif |
| 1076 | 1118 | |
| 1077 | 1119 | // x0 is zero |
| 1078 | ld x1, (8 * 1)(a0) | |
| 1120 | ld x1, (8 * 0)(a0) // restore pc into ra | |
| 1079 | 1121 | ld x2, (8 * 2)(a0) |
| 1080 | 1122 | ld x3, (8 * 3)(a0) |
| 1081 | 1123 | ld x4, (8 * 4)(a0) |
lib/libunwind/src/UnwindRegistersSave.S+48-2| ... | ... | @@ -697,7 +697,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 697 | 697 | blr |
| 698 | 698 | |
| 699 | 699 | |
| 700 | #elif defined(__arm64__) || defined(__aarch64__) | |
| 700 | #elif defined(__aarch64__) | |
| 701 | 701 | |
| 702 | 702 | // |
| 703 | 703 | // extern int __unw_getcontext(unw_context_t* thread_state) |
| ... | ... | @@ -945,6 +945,52 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 945 | 945 | # zero epcr |
| 946 | 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 | 994 | #elif defined(__sparc__) |
| 949 | 995 | |
| 950 | 996 | # |
| ... | ... | @@ -984,7 +1030,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 984 | 1030 | # thread_state pointer is in a0 |
| 985 | 1031 | # |
| 986 | 1032 | DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 987 | // x0 is zero | |
| 1033 | sd x1, (8 * 0)(a0) // store ra as pc | |
| 988 | 1034 | sd x1, (8 * 1)(a0) |
| 989 | 1035 | sd x2, (8 * 2)(a0) |
| 990 | 1036 | sd x3, (8 * 3)(a0) |
lib/libunwind/src/Unwind_AppleExtras.cpp+1-1| ... | ... | @@ -56,7 +56,7 @@ struct libgcc_object_info { |
| 56 | 56 | __attribute__((visibility("default"))) const char sym##_tmp42 = 0; \ |
| 57 | 57 | extern const char sym##_tmp43 __asm("$ld$hide$os4.3$_" #sym ); \ |
| 58 | 58 | __attribute__((visibility("default"))) const char sym##_tmp43 = 0; |
| 59 | #elif defined(__arm64__) | |
| 59 | #elif defined(__aarch64__) | |
| 60 | 60 | #define NOT_HERE_BEFORE_10_6(sym) |
| 61 | 61 | #define NEVER_HERE(sym) |
| 62 | 62 | #else |
lib/libunwind/src/assembly.h+8-1| ... | ... | @@ -28,7 +28,7 @@ |
| 28 | 28 | #ifdef _ARCH_PWR8 |
| 29 | 29 | #define PPC64_HAS_VMX |
| 30 | 30 | #endif |
| 31 | #elif defined(__arm64__) | |
| 31 | #elif defined(__APPLE__) && defined(__aarch64__) | |
| 32 | 32 | #define SEPARATOR %% |
| 33 | 33 | #else |
| 34 | 34 | #define SEPARATOR ; |
| ... | ... | @@ -75,9 +75,16 @@ |
| 75 | 75 | #define EXPORT_SYMBOL(name) |
| 76 | 76 | #define HIDDEN_SYMBOL(name) .hidden name |
| 77 | 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 | 84 | #define WEAK_ALIAS(name, aliasname) \ |
| 79 | 85 | WEAK_SYMBOL(aliasname) SEPARATOR \ |
| 80 | 86 | SYMBOL_NAME(aliasname) = SYMBOL_NAME(name) |
| 87 | #endif | |
| 81 | 88 | |
| 82 | 89 | #if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \ |
| 83 | 90 | defined(__linux__) |
lib/libunwind/src/config.h+4-4| ... | ... | @@ -102,9 +102,10 @@ |
| 102 | 102 | #if defined(__i386__) || defined(__x86_64__) || \ |
| 103 | 103 | defined(__ppc__) || defined(__ppc64__) || defined(__powerpc64__) || \ |
| 104 | 104 | (!defined(__APPLE__) && defined(__arm__)) || \ |
| 105 | (defined(__arm64__) || defined(__aarch64__)) || \ | |
| 105 | defined(__aarch64__) || \ | |
| 106 | 106 | defined(__mips__) || \ |
| 107 | defined(__riscv) | |
| 107 | defined(__riscv) || \ | |
| 108 | defined(__hexagon__) | |
| 108 | 109 | #if !defined(_LIBUNWIND_BUILD_SJLJ_APIS) |
| 109 | 110 | #define _LIBUNWIND_BUILD_ZERO_COST_APIS |
| 110 | 111 | #endif |
| ... | ... | @@ -122,8 +123,7 @@ |
| 122 | 123 | #else |
| 123 | 124 | #define _LIBUNWIND_ABORT(msg) \ |
| 124 | 125 | do { \ |
| 125 | fprintf(stderr, "libunwind: %s %s:%d - %s\n", __func__, __FILE__, \ | |
| 126 | __LINE__, msg); \ | |
| 126 | fprintf(stderr, "libunwind: %s - %s\n", __func__, msg); \ | |
| 127 | 127 | fflush(stderr); \ |
| 128 | 128 | abort(); \ |
| 129 | 129 | } while (0) |
lib/libunwind/src/libunwind.cpp+2| ... | ... | @@ -50,6 +50,8 @@ _LIBUNWIND_HIDDEN int __unw_init_local(unw_cursor_t *cursor, |
| 50 | 50 | # define REGISTER_KIND Registers_arm |
| 51 | 51 | #elif defined(__or1k__) |
| 52 | 52 | # define REGISTER_KIND Registers_or1k |
| 53 | #elif defined(__hexagon__) | |
| 54 | # define REGISTER_KIND Registers_hexagon | |
| 53 | 55 | #elif defined(__mips__) && defined(_ABIO32) && _MIPS_SIM == _ABIO32 |
| 54 | 56 | # define REGISTER_KIND Registers_mips_o32 |
| 55 | 57 | #elif defined(__mips64) |