| author | |
| committer | |
| log | 1e66ac5755ebe8614b8b3a278eabcfca5f78c3c2 |
| tree | 3a642c70e5cfc6e4c298a1e2c40653c7a0c2e72a |
| parent | 8612dac225a55e09293b767aab3c81a459609bb4 |
llvm commit b2851aea80e5a8f0cfd6c3c5a56a6b00fb28c6b614 files changed, 667 insertions(+), 760 deletions(-)
lib/libunwind/include/libunwind.h+7-1| ... | ... | @@ -43,6 +43,12 @@ |
| 43 | 43 | #define LIBUNWIND_AVAIL |
| 44 | 44 | #endif |
| 45 | 45 | |
| 46 | #if defined(_WIN32) && defined(__SEH__) | |
| 47 | #define LIBUNWIND_CURSOR_ALIGNMENT_ATTR __attribute__((__aligned__(16))) | |
| 48 | #else | |
| 49 | #define LIBUNWIND_CURSOR_ALIGNMENT_ATTR | |
| 50 | #endif | |
| 51 | ||
| 46 | 52 | /* error codes */ |
| 47 | 53 | enum { |
| 48 | 54 | UNW_ESUCCESS = 0, /* no error */ |
| ... | ... | @@ -68,7 +74,7 @@ typedef struct unw_context_t unw_context_t; |
| 68 | 74 | |
| 69 | 75 | struct unw_cursor_t { |
| 70 | 76 | uint64_t data[_LIBUNWIND_CURSOR_SIZE]; |
| 71 | }; | |
| 77 | } LIBUNWIND_CURSOR_ALIGNMENT_ATTR; | |
| 72 | 78 | typedef struct unw_cursor_t unw_cursor_t; |
| 73 | 79 | |
| 74 | 80 | typedef struct unw_addr_space *unw_addr_space_t; |
lib/libunwind/src/AddressSpace.hpp+98-162| ... | ... | @@ -17,6 +17,12 @@ |
| 17 | 17 | #include <stdlib.h> |
| 18 | 18 | #include <string.h> |
| 19 | 19 | |
| 20 | #include "libunwind.h" | |
| 21 | #include "config.h" | |
| 22 | #include "dwarf2.h" | |
| 23 | #include "EHHeaderParser.hpp" | |
| 24 | #include "Registers.hpp" | |
| 25 | ||
| 20 | 26 | #ifndef _LIBUNWIND_USE_DLADDR |
| 21 | 27 | #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32) |
| 22 | 28 | #define _LIBUNWIND_USE_DLADDR 1 |
| ... | ... | @@ -39,19 +45,6 @@ struct EHABIIndexEntry { |
| 39 | 45 | }; |
| 40 | 46 | #endif |
| 41 | 47 | |
| 42 | #ifdef __APPLE__ | |
| 43 | #include <mach-o/getsect.h> | |
| 44 | namespace libunwind { | |
| 45 | bool checkKeyMgrRegisteredFDEs(uintptr_t targetAddr, void *&fde); | |
| 46 | } | |
| 47 | #endif | |
| 48 | ||
| 49 | #include "libunwind.h" | |
| 50 | #include "config.h" | |
| 51 | #include "dwarf2.h" | |
| 52 | #include "EHHeaderParser.hpp" | |
| 53 | #include "Registers.hpp" | |
| 54 | ||
| 55 | 48 | #ifdef __APPLE__ |
| 56 | 49 | |
| 57 | 50 | struct dyld_unwind_sections |
| ... | ... | @@ -62,43 +55,9 @@ namespace libunwind { |
| 62 | 55 | const void* compact_unwind_section; |
| 63 | 56 | uintptr_t compact_unwind_section_length; |
| 64 | 57 | }; |
| 65 | #if (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) \ | |
| 66 | && (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)) \ | |
| 67 | || defined(__IPHONE_OS_VERSION_MIN_REQUIRED) | |
| 68 | // In 10.7.0 or later, libSystem.dylib implements this function. | |
| 69 | extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *); | |
| 70 | #else | |
| 71 | // In 10.6.x and earlier, we need to implement this functionality. Note | |
| 72 | // that this requires a newer version of libmacho (from cctools) than is | |
| 73 | // present in libSystem on 10.6.x (for getsectiondata). | |
| 74 | static inline bool _dyld_find_unwind_sections(void* addr, | |
| 75 | dyld_unwind_sections* info) { | |
| 76 | // Find mach-o image containing address. | |
| 77 | Dl_info dlinfo; | |
| 78 | if (!dladdr(addr, &dlinfo)) | |
| 79 | return false; | |
| 80 | #if __LP64__ | |
| 81 | const struct mach_header_64 *mh = (const struct mach_header_64 *)dlinfo.dli_fbase; | |
| 82 | #else | |
| 83 | const struct mach_header *mh = (const struct mach_header *)dlinfo.dli_fbase; | |
| 84 | #endif | |
| 85 | 58 | |
| 86 | // Initialize the return struct | |
| 87 | info->mh = (const struct mach_header *)mh; | |
| 88 | info->dwarf_section = getsectiondata(mh, "__TEXT", "__eh_frame", &info->dwarf_section_length); | |
| 89 | info->compact_unwind_section = getsectiondata(mh, "__TEXT", "__unwind_info", &info->compact_unwind_section_length); | |
| 90 | ||
| 91 | if (!info->dwarf_section) { | |
| 92 | info->dwarf_section_length = 0; | |
| 93 | } | |
| 94 | ||
| 95 | if (!info->compact_unwind_section) { | |
| 96 | info->compact_unwind_section_length = 0; | |
| 97 | } | |
| 98 | ||
| 99 | return true; | |
| 100 | } | |
| 101 | #endif | |
| 59 | // In 10.7.0 or later, libSystem.dylib implements this function. | |
| 60 | extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *); | |
| 102 | 61 | |
| 103 | 62 | #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) |
| 104 | 63 | |
| ... | ... | @@ -139,22 +98,15 @@ extern char __eh_frame_hdr_end; |
| 139 | 98 | extern char __exidx_start; |
| 140 | 99 | extern char __exidx_end; |
| 141 | 100 | |
| 142 | #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | |
| 101 | #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32) | |
| 143 | 102 | |
| 144 | // ELF-based systems may use dl_iterate_phdr() to access sections | |
| 145 | // containing unwinding information. The ElfW() macro for pointer-size | |
| 146 | // independent ELF header traversal is not provided by <link.h> on some | |
| 147 | // systems (e.g., FreeBSD). On these systems the data structures are | |
| 148 | // just called Elf_XXX. Define ElfW() locally. | |
| 149 | #ifndef _WIN32 | |
| 150 | #include <link.h> | |
| 151 | #else | |
| 152 | 103 | #include <windows.h> |
| 153 | 104 | #include <psapi.h> |
| 154 | #endif | |
| 155 | #if !defined(ElfW) | |
| 156 | #define ElfW(type) Elf_##type | |
| 157 | #endif | |
| 105 | ||
| 106 | #elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) || \ | |
| 107 | defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX) | |
| 108 | ||
| 109 | #include <link.h> | |
| 158 | 110 | |
| 159 | 111 | #endif |
| 160 | 112 | |
| ... | ... | @@ -162,11 +114,15 @@ namespace libunwind { |
| 162 | 114 | |
| 163 | 115 | /// Used by findUnwindSections() to return info about needed sections. |
| 164 | 116 | struct UnwindInfoSections { |
| 165 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \ | |
| 166 | defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) | |
| 167 | // No dso_base for SEH or ARM EHABI. | |
| 117 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || \ | |
| 118 | defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) || \ | |
| 119 | defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) | |
| 120 | // No dso_base for SEH. | |
| 168 | 121 | uintptr_t dso_base; |
| 169 | 122 | #endif |
| 123 | #if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) | |
| 124 | uintptr_t text_segment_length; | |
| 125 | #endif | |
| 170 | 126 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
| 171 | 127 | uintptr_t dwarf_section; |
| 172 | 128 | uintptr_t dwarf_section_length; |
| ... | ... | @@ -290,11 +246,11 @@ inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { |
| 290 | 246 | if (p == pend) |
| 291 | 247 | _LIBUNWIND_ABORT("truncated sleb128 expression"); |
| 292 | 248 | byte = *p++; |
| 293 | result |= ((byte & 0x7f) << bit); | |
| 249 | result |= (uint64_t)(byte & 0x7f) << bit; | |
| 294 | 250 | bit += 7; |
| 295 | 251 | } while (byte & 0x80); |
| 296 | 252 | // sign extend negative numbers |
| 297 | if ((byte & 0x40) != 0) | |
| 253 | if ((byte & 0x40) != 0 && bit < 64) | |
| 298 | 254 | result |= (-1ULL) << bit; |
| 299 | 255 | addr = (pint_t) p; |
| 300 | 256 | return result; |
| ... | ... | @@ -392,23 +348,14 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, |
| 392 | 348 | return result; |
| 393 | 349 | } |
| 394 | 350 | |
| 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) | |
| 351 | #if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) | |
| 411 | 352 | |
| 353 | // The ElfW() macro for pointer-size independent ELF header traversal is not | |
| 354 | // provided by <link.h> on some systems (e.g., FreeBSD). On these systems the | |
| 355 | // data structures are just called Elf_XXX. Define ElfW() locally. | |
| 356 | #if !defined(ElfW) | |
| 357 | #define ElfW(type) Elf_##type | |
| 358 | #endif | |
| 412 | 359 | #if !defined(Elf_Half) |
| 413 | 360 | typedef ElfW(Half) Elf_Half; |
| 414 | 361 | #endif |
| ... | ... | @@ -447,16 +394,12 @@ struct _LIBUNWIND_HIDDEN dl_iterate_cb_data { |
| 447 | 394 | uintptr_t targetAddr; |
| 448 | 395 | }; |
| 449 | 396 | |
| 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 | 397 | #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE) |
| 456 | 398 | #include "FrameHeaderCache.hpp" |
| 457 | 399 | |
| 458 | // There should be just one of these per process. | |
| 459 | static FrameHeaderCache ProcessFrameHeaderCache; | |
| 400 | // Typically there is one cache per process, but when libunwind is built as a | |
| 401 | // hermetic static library, then each shared object may have its own cache. | |
| 402 | static FrameHeaderCache TheFrameHeaderCache; | |
| 460 | 403 | #endif |
| 461 | 404 | |
| 462 | 405 | static bool checkAddrInSegment(const Elf_Phdr *phdr, size_t image_base, |
| ... | ... | @@ -466,95 +409,93 @@ static bool checkAddrInSegment(const Elf_Phdr *phdr, size_t image_base, |
| 466 | 409 | uintptr_t end = begin + phdr->p_memsz; |
| 467 | 410 | if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) { |
| 468 | 411 | cbdata->sects->dso_base = begin; |
| 469 | cbdata->sects->dwarf_section_length = phdr->p_memsz; | |
| 412 | cbdata->sects->text_segment_length = phdr->p_memsz; | |
| 470 | 413 | return true; |
| 471 | 414 | } |
| 472 | 415 | } |
| 473 | 416 | return false; |
| 474 | 417 | } |
| 475 | 418 | |
| 419 | static bool checkForUnwindInfoSegment(const Elf_Phdr *phdr, size_t image_base, | |
| 420 | dl_iterate_cb_data *cbdata) { | |
| 421 | #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) | |
| 422 | if (phdr->p_type == PT_GNU_EH_FRAME) { | |
| 423 | EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo; | |
| 424 | uintptr_t eh_frame_hdr_start = image_base + phdr->p_vaddr; | |
| 425 | cbdata->sects->dwarf_index_section = eh_frame_hdr_start; | |
| 426 | cbdata->sects->dwarf_index_section_length = phdr->p_memsz; | |
| 427 | if (EHHeaderParser<LocalAddressSpace>::decodeEHHdr( | |
| 428 | *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, | |
| 429 | hdrInfo)) { | |
| 430 | // .eh_frame_hdr records the start of .eh_frame, but not its size. | |
| 431 | // Rely on a zero terminator to find the end of the section. | |
| 432 | cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; | |
| 433 | cbdata->sects->dwarf_section_length = UINTPTR_MAX; | |
| 434 | return true; | |
| 435 | } | |
| 436 | } | |
| 437 | return false; | |
| 438 | #elif defined(_LIBUNWIND_ARM_EHABI) | |
| 439 | if (phdr->p_type == PT_ARM_EXIDX) { | |
| 440 | uintptr_t exidx_start = image_base + phdr->p_vaddr; | |
| 441 | cbdata->sects->arm_section = exidx_start; | |
| 442 | cbdata->sects->arm_section_length = phdr->p_memsz; | |
| 443 | return true; | |
| 444 | } | |
| 445 | return false; | |
| 446 | #else | |
| 447 | #error Need one of _LIBUNWIND_SUPPORT_DWARF_INDEX or _LIBUNWIND_ARM_EHABI | |
| 448 | #endif | |
| 449 | } | |
| 450 | ||
| 476 | 451 | static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, |
| 477 | 452 | size_t pinfo_size, void *data) { |
| 478 | 453 | auto cbdata = static_cast<dl_iterate_cb_data *>(data); |
| 479 | 454 | if (pinfo->dlpi_phnum == 0 || cbdata->targetAddr < pinfo->dlpi_addr) |
| 480 | 455 | return 0; |
| 481 | 456 | #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE) |
| 482 | if (ProcessFrameHeaderCache.find(pinfo, pinfo_size, data)) | |
| 457 | if (TheFrameHeaderCache.find(pinfo, pinfo_size, data)) | |
| 483 | 458 | return 1; |
| 459 | #else | |
| 460 | // Avoid warning about unused variable. | |
| 461 | (void)pinfo_size; | |
| 484 | 462 | #endif |
| 485 | 463 | |
| 486 | 464 | Elf_Addr image_base = calculateImageBase(pinfo); |
| 487 | bool found_obj = false; | |
| 488 | bool found_hdr = false; | |
| 489 | 465 | |
| 490 | // Third phdr is usually the executable phdr. | |
| 491 | if (pinfo->dlpi_phnum > 2) | |
| 492 | found_obj = checkAddrInSegment(&pinfo->dlpi_phdr[2], image_base, cbdata); | |
| 466 | // Most shared objects seen in this callback function likely don't contain the | |
| 467 | // target address, so optimize for that. Scan for a matching PT_LOAD segment | |
| 468 | // first and bail when it isn't found. | |
| 469 | bool found_text = false; | |
| 470 | for (Elf_Half i = 0; i < pinfo->dlpi_phnum; ++i) { | |
| 471 | if (checkAddrInSegment(&pinfo->dlpi_phdr[i], image_base, cbdata)) { | |
| 472 | found_text = true; | |
| 473 | break; | |
| 474 | } | |
| 475 | } | |
| 476 | if (!found_text) | |
| 477 | return 0; | |
| 493 | 478 | |
| 494 | // PT_GNU_EH_FRAME is usually near the end. Iterate backward. We already know | |
| 495 | // that there is one or more phdrs. | |
| 479 | // PT_GNU_EH_FRAME and PT_ARM_EXIDX are usually near the end. Iterate | |
| 480 | // backward. | |
| 481 | bool found_unwind = false; | |
| 496 | 482 | for (Elf_Half i = pinfo->dlpi_phnum; i > 0; i--) { |
| 497 | 483 | const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i - 1]; |
| 498 | if (!found_hdr && phdr->p_type == PT_GNU_EH_FRAME) { | |
| 499 | EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo; | |
| 500 | uintptr_t eh_frame_hdr_start = image_base + phdr->p_vaddr; | |
| 501 | cbdata->sects->dwarf_index_section = eh_frame_hdr_start; | |
| 502 | cbdata->sects->dwarf_index_section_length = phdr->p_memsz; | |
| 503 | found_hdr = EHHeaderParser<LocalAddressSpace>::decodeEHHdr( | |
| 504 | *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, | |
| 505 | hdrInfo); | |
| 506 | if (found_hdr) | |
| 507 | cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; | |
| 508 | } else if (!found_obj) { | |
| 509 | found_obj = checkAddrInSegment(phdr, image_base, cbdata); | |
| 510 | } | |
| 511 | if (found_obj && found_hdr) { | |
| 512 | #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE) | |
| 513 | ProcessFrameHeaderCache.add(cbdata->sects); | |
| 514 | #endif | |
| 515 | return 1; | |
| 484 | if (checkForUnwindInfoSegment(phdr, image_base, cbdata)) { | |
| 485 | found_unwind = true; | |
| 486 | break; | |
| 516 | 487 | } |
| 517 | 488 | } |
| 518 | cbdata->sects->dwarf_section_length = 0; | |
| 519 | return 0; | |
| 520 | } | |
| 521 | ||
| 522 | #else // defined(LIBUNWIND_SUPPORT_DWARF_UNWIND) | |
| 523 | // Given all the #ifdef's above, the code here is for | |
| 524 | // defined(LIBUNWIND_ARM_EHABI) | |
| 525 | ||
| 526 | static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, size_t, | |
| 527 | void *data) { | |
| 528 | auto *cbdata = static_cast<dl_iterate_cb_data *>(data); | |
| 529 | bool found_obj = false; | |
| 530 | bool found_hdr = false; | |
| 531 | ||
| 532 | assert(cbdata); | |
| 533 | assert(cbdata->sects); | |
| 534 | ||
| 535 | if (cbdata->targetAddr < pinfo->dlpi_addr) | |
| 489 | if (!found_unwind) | |
| 536 | 490 | return 0; |
| 537 | 491 | |
| 538 | Elf_Addr image_base = calculateImageBase(pinfo); | |
| 539 | ||
| 540 | for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { | |
| 541 | const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; | |
| 542 | if (phdr->p_type == PT_LOAD) { | |
| 543 | uintptr_t begin = image_base + phdr->p_vaddr; | |
| 544 | uintptr_t end = begin + phdr->p_memsz; | |
| 545 | if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) | |
| 546 | found_obj = true; | |
| 547 | } else if (phdr->p_type == PT_ARM_EXIDX) { | |
| 548 | uintptr_t exidx_start = image_base + phdr->p_vaddr; | |
| 549 | cbdata->sects->arm_section = exidx_start; | |
| 550 | cbdata->sects->arm_section_length = phdr->p_memsz; | |
| 551 | found_hdr = true; | |
| 552 | } | |
| 553 | } | |
| 554 | return found_obj && found_hdr; | |
| 492 | #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE) | |
| 493 | TheFrameHeaderCache.add(cbdata->sects); | |
| 494 | #endif | |
| 495 | return 1; | |
| 555 | 496 | } |
| 556 | #endif // defined(LIBUNWIND_SUPPORT_DWARF_UNWIND) | |
| 557 | #endif // defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | |
| 497 | ||
| 498 | #endif // defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) | |
| 558 | 499 | |
| 559 | 500 | |
| 560 | 501 | inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, |
| ... | ... | @@ -572,6 +513,7 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, |
| 572 | 513 | return true; |
| 573 | 514 | } |
| 574 | 515 | #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) |
| 516 | info.dso_base = 0; | |
| 575 | 517 | // Bare metal is statically linked, so no need to ask the dynamic loader |
| 576 | 518 | info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start); |
| 577 | 519 | info.dwarf_section = (uintptr_t)(&__eh_frame_start); |
| ... | ... | @@ -638,16 +580,14 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, |
| 638 | 580 | (void)targetAddr; |
| 639 | 581 | (void)info; |
| 640 | 582 | return true; |
| 641 | #elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) | |
| 642 | // For ARM EHABI, Bionic didn't implement dl_iterate_phdr until API 21. After | |
| 643 | // API 21, dl_iterate_phdr exists, but dl_unwind_find_exidx is much faster. | |
| 583 | #elif defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX) | |
| 644 | 584 | int length = 0; |
| 645 | 585 | info.arm_section = |
| 646 | 586 | (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length); |
| 647 | 587 | info.arm_section_length = (uintptr_t)length * sizeof(EHABIIndexEntry); |
| 648 | 588 | if (info.arm_section && info.arm_section_length) |
| 649 | 589 | return true; |
| 650 | #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | |
| 590 | #elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) | |
| 651 | 591 | dl_iterate_cb_data cb_data = {this, &info, targetAddr}; |
| 652 | 592 | int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data); |
| 653 | 593 | return static_cast<bool>(found); |
| ... | ... | @@ -658,14 +598,10 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, |
| 658 | 598 | |
| 659 | 599 | |
| 660 | 600 | inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { |
| 661 | #ifdef __APPLE__ | |
| 662 | return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde)); | |
| 663 | #else | |
| 664 | 601 | // TO DO: if OS has way to dynamically register FDEs, check that. |
| 665 | 602 | (void)targetAddr; |
| 666 | 603 | (void)fde; |
| 667 | 604 | return false; |
| 668 | #endif | |
| 669 | 605 | } |
| 670 | 606 | |
| 671 | 607 | inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, |
lib/libunwind/src/DwarfInstructions.hpp+8-1| ... | ... | @@ -93,7 +93,8 @@ typename A::pint_t DwarfInstructions<A, R>::getSavedRegister( |
| 93 | 93 | |
| 94 | 94 | case CFI_Parser<A>::kRegisterInRegister: |
| 95 | 95 | return registers.getRegister((int)savedReg.value); |
| 96 | ||
| 96 | case CFI_Parser<A>::kRegisterUndefined: | |
| 97 | return 0; | |
| 97 | 98 | case CFI_Parser<A>::kRegisterUnused: |
| 98 | 99 | case CFI_Parser<A>::kRegisterOffsetFromCFA: |
| 99 | 100 | // FIX ME |
| ... | ... | @@ -117,6 +118,7 @@ double DwarfInstructions<A, R>::getSavedFloatRegister( |
| 117 | 118 | |
| 118 | 119 | case CFI_Parser<A>::kRegisterIsExpression: |
| 119 | 120 | case CFI_Parser<A>::kRegisterUnused: |
| 121 | case CFI_Parser<A>::kRegisterUndefined: | |
| 120 | 122 | case CFI_Parser<A>::kRegisterOffsetFromCFA: |
| 121 | 123 | case CFI_Parser<A>::kRegisterInRegister: |
| 122 | 124 | // FIX ME |
| ... | ... | @@ -140,6 +142,7 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister( |
| 140 | 142 | |
| 141 | 143 | case CFI_Parser<A>::kRegisterIsExpression: |
| 142 | 144 | case CFI_Parser<A>::kRegisterUnused: |
| 145 | case CFI_Parser<A>::kRegisterUndefined: | |
| 143 | 146 | case CFI_Parser<A>::kRegisterOffsetFromCFA: |
| 144 | 147 | case CFI_Parser<A>::kRegisterInRegister: |
| 145 | 148 | // FIX ME |
| ... | ... | @@ -190,6 +193,10 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, |
| 190 | 193 | prolog.savedRegisters[i])); |
| 191 | 194 | else |
| 192 | 195 | return UNW_EBADREG; |
| 196 | } else if (i == (int)cieInfo.returnAddressRegister) { | |
| 197 | // Leaf function keeps the return address in register and there is no | |
| 198 | // explicit intructions how to restore it. | |
| 199 | returnAddress = registers.getRegister(cieInfo.returnAddressRegister); | |
| 193 | 200 | } |
| 194 | 201 | } |
| 195 | 202 |
lib/libunwind/src/DwarfParser.hpp+407-404| ... | ... | @@ -69,6 +69,7 @@ public: |
| 69 | 69 | }; |
| 70 | 70 | enum RegisterSavedWhere { |
| 71 | 71 | kRegisterUnused, |
| 72 | kRegisterUndefined, | |
| 72 | 73 | kRegisterInCFA, |
| 73 | 74 | kRegisterOffsetFromCFA, |
| 74 | 75 | kRegisterInRegister, |
| ... | ... | @@ -87,9 +88,6 @@ public: |
| 87 | 88 | int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset |
| 88 | 89 | int64_t cfaExpression; // CFA = expression |
| 89 | 90 | uint32_t spExtraArgSize; |
| 90 | uint32_t codeOffsetAtStackDecrement; | |
| 91 | bool registersInOtherRegisters; | |
| 92 | bool sameValueUsed; | |
| 93 | 91 | RegisterLocation savedRegisters[kMaxRegisterNumber + 1]; |
| 94 | 92 | enum class InitializeTime { kLazy, kNormal }; |
| 95 | 93 | |
| ... | ... | @@ -134,8 +132,26 @@ public: |
| 134 | 132 | PrologInfo info; |
| 135 | 133 | }; |
| 136 | 134 | |
| 135 | struct RememberStack { | |
| 136 | PrologInfoStackEntry *entry; | |
| 137 | RememberStack() : entry(nullptr) {} | |
| 138 | ~RememberStack() { | |
| 139 | #if defined(_LIBUNWIND_REMEMBER_CLEANUP_NEEDED) | |
| 140 | // Clean up rememberStack. Even in the case where every | |
| 141 | // DW_CFA_remember_state is paired with a DW_CFA_restore_state, | |
| 142 | // parseInstructions can skip restore opcodes if it reaches the target PC | |
| 143 | // and stops interpreting, so we have to make sure we don't leak memory. | |
| 144 | while (entry) { | |
| 145 | PrologInfoStackEntry *next = entry->next; | |
| 146 | _LIBUNWIND_REMEMBER_FREE(entry); | |
| 147 | entry = next; | |
| 148 | } | |
| 149 | #endif | |
| 150 | } | |
| 151 | }; | |
| 152 | ||
| 137 | 153 | static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, |
| 138 | uint32_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo, | |
| 154 | uintptr_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo, | |
| 139 | 155 | CIE_Info *cieInfo); |
| 140 | 156 | static const char *decodeFDE(A &addressSpace, pint_t fdeStart, |
| 141 | 157 | FDE_Info *fdeInfo, CIE_Info *cieInfo); |
| ... | ... | @@ -144,13 +160,6 @@ public: |
| 144 | 160 | int arch, PrologInfo *results); |
| 145 | 161 | |
| 146 | 162 | static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo); |
| 147 | ||
| 148 | private: | |
| 149 | static bool parseInstructions(A &addressSpace, pint_t instructions, | |
| 150 | pint_t instructionsEnd, const CIE_Info &cieInfo, | |
| 151 | pint_t pcoffset, | |
| 152 | PrologInfoStackEntry *&rememberStack, int arch, | |
| 153 | PrologInfo *results); | |
| 154 | 163 | }; |
| 155 | 164 | |
| 156 | 165 | /// Parse a FDE into a CIE_Info and an FDE_Info |
| ... | ... | @@ -166,7 +175,7 @@ const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart, |
| 166 | 175 | p += 8; |
| 167 | 176 | } |
| 168 | 177 | if (cfiLength == 0) |
| 169 | return "FDE has zero length"; // end marker | |
| 178 | return "FDE has zero length"; // zero terminator | |
| 170 | 179 | uint32_t ciePointer = addressSpace.get32(p); |
| 171 | 180 | if (ciePointer == 0) |
| 172 | 181 | return "FDE is really a CIE"; // this is a CIE not an FDE |
| ... | ... | @@ -211,11 +220,13 @@ const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart, |
| 211 | 220 | /// Scan an eh_frame section to find an FDE for a pc |
| 212 | 221 | template <typename A> |
| 213 | 222 | bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, |
| 214 | uint32_t sectionLength, pint_t fdeHint, | |
| 223 | uintptr_t sectionLength, pint_t fdeHint, | |
| 215 | 224 | FDE_Info *fdeInfo, CIE_Info *cieInfo) { |
| 216 | 225 | //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc); |
| 217 | 226 | pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart; |
| 218 | const pint_t ehSectionEnd = p + sectionLength; | |
| 227 | const pint_t ehSectionEnd = (sectionLength == UINTPTR_MAX) | |
| 228 | ? static_cast<pint_t>(-1) | |
| 229 | : (ehSectionStart + sectionLength); | |
| 219 | 230 | while (p < ehSectionEnd) { |
| 220 | 231 | pint_t currentCFI = p; |
| 221 | 232 | //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p); |
| ... | ... | @@ -227,7 +238,7 @@ bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, |
| 227 | 238 | p += 8; |
| 228 | 239 | } |
| 229 | 240 | if (cfiLength == 0) |
| 230 | return false; // end marker | |
| 241 | return false; // zero terminator | |
| 231 | 242 | uint32_t id = addressSpace.get32(p); |
| 232 | 243 | if (id == 0) { |
| 233 | 244 | // Skip over CIEs. |
| ... | ... | @@ -336,7 +347,8 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie, |
| 336 | 347 | // parse data alignment factor |
| 337 | 348 | cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd); |
| 338 | 349 | // parse return address register |
| 339 | uint64_t raReg = addressSpace.getULEB128(p, cieContentEnd); | |
| 350 | uint64_t raReg = (version == 1) ? addressSpace.get8(p++) | |
| 351 | : addressSpace.getULEB128(p, cieContentEnd); | |
| 340 | 352 | assert(raReg < 255 && "return address register too large"); |
| 341 | 353 | cieInfo->returnAddressRegister = (uint8_t)raReg; |
| 342 | 354 | // parse augmentation data based on augmentation string |
| ... | ... | @@ -390,418 +402,409 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, |
| 390 | 402 | const FDE_Info &fdeInfo, |
| 391 | 403 | const CIE_Info &cieInfo, pint_t upToPC, |
| 392 | 404 | int arch, PrologInfo *results) { |
| 393 | PrologInfoStackEntry *rememberStack = NULL; | |
| 394 | ||
| 395 | // parse CIE then FDE instructions | |
| 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; | |
| 417 | } | |
| 405 | // Alloca is used for the allocation of the rememberStack entries. It removes | |
| 406 | // the dependency on new/malloc but the below for loop can not be refactored | |
| 407 | // into functions. Entry could be saved during the processing of a CIE and | |
| 408 | // restored by an FDE. | |
| 409 | RememberStack rememberStack; | |
| 410 | ||
| 411 | struct ParseInfo { | |
| 412 | pint_t instructions; | |
| 413 | pint_t instructionsEnd; | |
| 414 | pint_t pcoffset; | |
| 415 | }; | |
| 418 | 416 | |
| 419 | /// "run" the DWARF instructions | |
| 420 | template <typename A> | |
| 421 | bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, | |
| 422 | pint_t instructionsEnd, | |
| 423 | const CIE_Info &cieInfo, pint_t pcoffset, | |
| 424 | PrologInfoStackEntry *&rememberStack, | |
| 425 | int arch, PrologInfo *results) { | |
| 426 | pint_t p = instructions; | |
| 427 | pint_t codeOffset = 0; | |
| 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); | |
| 431 | ||
| 432 | _LIBUNWIND_TRACE_DWARF("parseInstructions(instructions=0x%0" PRIx64 ")\n", | |
| 433 | static_cast<uint64_t>(instructionsEnd)); | |
| 434 | ||
| 435 | // see DWARF Spec, section 6.4.2 for details on unwind opcodes | |
| 436 | while ((p < instructionsEnd) && (codeOffset < pcoffset)) { | |
| 437 | uint64_t reg; | |
| 438 | uint64_t reg2; | |
| 439 | int64_t offset; | |
| 440 | uint64_t length; | |
| 441 | uint8_t opcode = addressSpace.get8(p); | |
| 442 | uint8_t operand; | |
| 443 | #if !defined(_LIBUNWIND_NO_HEAP) | |
| 444 | PrologInfoStackEntry *entry; | |
| 445 | #endif | |
| 446 | ++p; | |
| 447 | switch (opcode) { | |
| 448 | case DW_CFA_nop: | |
| 449 | _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n"); | |
| 450 | break; | |
| 451 | case DW_CFA_set_loc: | |
| 452 | codeOffset = | |
| 453 | addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding); | |
| 454 | _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n"); | |
| 455 | break; | |
| 456 | case DW_CFA_advance_loc1: | |
| 457 | codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor); | |
| 458 | p += 1; | |
| 459 | _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc1: new offset=%" PRIu64 "\n", | |
| 460 | static_cast<uint64_t>(codeOffset)); | |
| 461 | break; | |
| 462 | case DW_CFA_advance_loc2: | |
| 463 | codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor); | |
| 464 | p += 2; | |
| 465 | _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc2: new offset=%" PRIu64 "\n", | |
| 466 | static_cast<uint64_t>(codeOffset)); | |
| 467 | break; | |
| 468 | case DW_CFA_advance_loc4: | |
| 469 | codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor); | |
| 470 | p += 4; | |
| 471 | _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc4: new offset=%" PRIu64 "\n", | |
| 472 | static_cast<uint64_t>(codeOffset)); | |
| 473 | break; | |
| 474 | case DW_CFA_offset_extended: | |
| 475 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 476 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) | |
| 477 | * cieInfo.dataAlignFactor; | |
| 478 | if (reg > kMaxRegisterNumber) { | |
| 479 | _LIBUNWIND_LOG0( | |
| 480 | "malformed DW_CFA_offset_extended DWARF unwind, reg too big"); | |
| 481 | return false; | |
| 482 | } | |
| 483 | results->setRegister(reg, kRegisterInCFA, offset, initialState); | |
| 484 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", " | |
| 485 | "offset=%" PRId64 ")\n", | |
| 486 | reg, offset); | |
| 487 | break; | |
| 488 | case DW_CFA_restore_extended: | |
| 489 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 490 | if (reg > kMaxRegisterNumber) { | |
| 491 | _LIBUNWIND_LOG0( | |
| 492 | "malformed DW_CFA_restore_extended DWARF unwind, reg too big"); | |
| 493 | return false; | |
| 494 | } | |
| 495 | results->restoreRegisterToInitialState(reg, initialState); | |
| 496 | _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg); | |
| 497 | break; | |
| 498 | case DW_CFA_undefined: | |
| 499 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 500 | if (reg > kMaxRegisterNumber) { | |
| 501 | _LIBUNWIND_LOG0( | |
| 502 | "malformed DW_CFA_undefined DWARF unwind, reg too big"); | |
| 503 | return false; | |
| 504 | } | |
| 505 | results->setRegisterLocation(reg, kRegisterUnused, initialState); | |
| 506 | _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg); | |
| 507 | break; | |
| 508 | case DW_CFA_same_value: | |
| 509 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 510 | if (reg > kMaxRegisterNumber) { | |
| 511 | _LIBUNWIND_LOG0( | |
| 512 | "malformed DW_CFA_same_value DWARF unwind, reg too big"); | |
| 513 | return false; | |
| 514 | } | |
| 515 | // <rdar://problem/8456377> DW_CFA_same_value unsupported | |
| 516 | // "same value" means register was stored in frame, but its current | |
| 517 | // value has not changed, so no need to restore from frame. | |
| 518 | // We model this as if the register was never saved. | |
| 519 | results->setRegisterLocation(reg, kRegisterUnused, initialState); | |
| 520 | // set flag to disable conversion to compact unwind | |
| 521 | results->sameValueUsed = true; | |
| 522 | _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg); | |
| 523 | break; | |
| 524 | case DW_CFA_register: | |
| 525 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 526 | reg2 = addressSpace.getULEB128(p, instructionsEnd); | |
| 527 | if (reg > kMaxRegisterNumber) { | |
| 528 | _LIBUNWIND_LOG0( | |
| 529 | "malformed DW_CFA_register DWARF unwind, reg too big"); | |
| 530 | return false; | |
| 531 | } | |
| 532 | if (reg2 > kMaxRegisterNumber) { | |
| 533 | _LIBUNWIND_LOG0( | |
| 534 | "malformed DW_CFA_register DWARF unwind, reg2 too big"); | |
| 535 | return false; | |
| 536 | } | |
| 537 | results->setRegister(reg, kRegisterInRegister, (int64_t)reg2, | |
| 538 | initialState); | |
| 539 | // set flag to disable conversion to compact unwind | |
| 540 | results->registersInOtherRegisters = true; | |
| 541 | _LIBUNWIND_TRACE_DWARF( | |
| 542 | "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", reg, reg2); | |
| 543 | break; | |
| 544 | #if !defined(_LIBUNWIND_NO_HEAP) | |
| 545 | case DW_CFA_remember_state: | |
| 546 | // avoid operator new, because that would be an upward dependency | |
| 547 | entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry)); | |
| 548 | if (entry != NULL) { | |
| 549 | entry->next = rememberStack; | |
| 550 | entry->info = *results; | |
| 551 | rememberStack = entry; | |
| 552 | } else { | |
| 553 | return false; | |
| 554 | } | |
| 555 | _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n"); | |
| 556 | break; | |
| 557 | case DW_CFA_restore_state: | |
| 558 | if (rememberStack != NULL) { | |
| 559 | PrologInfoStackEntry *top = rememberStack; | |
| 560 | *results = top->info; | |
| 561 | rememberStack = top->next; | |
| 562 | free((char *)top); | |
| 563 | } else { | |
| 564 | return false; | |
| 565 | } | |
| 566 | _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_state\n"); | |
| 567 | break; | |
| 568 | #endif | |
| 569 | case DW_CFA_def_cfa: | |
| 570 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 571 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd); | |
| 572 | if (reg > kMaxRegisterNumber) { | |
| 573 | _LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big"); | |
| 574 | return false; | |
| 575 | } | |
| 576 | results->cfaRegister = (uint32_t)reg; | |
| 577 | results->cfaRegisterOffset = (int32_t)offset; | |
| 578 | _LIBUNWIND_TRACE_DWARF( | |
| 579 | "DW_CFA_def_cfa(reg=%" PRIu64 ", offset=%" PRIu64 ")\n", reg, offset); | |
| 580 | break; | |
| 581 | case DW_CFA_def_cfa_register: | |
| 582 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 583 | if (reg > kMaxRegisterNumber) { | |
| 584 | _LIBUNWIND_LOG0( | |
| 585 | "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big"); | |
| 586 | return false; | |
| 587 | } | |
| 588 | results->cfaRegister = (uint32_t)reg; | |
| 589 | _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_register(%" PRIu64 ")\n", reg); | |
| 590 | break; | |
| 591 | case DW_CFA_def_cfa_offset: | |
| 592 | results->cfaRegisterOffset = (int32_t) | |
| 593 | addressSpace.getULEB128(p, instructionsEnd); | |
| 594 | results->codeOffsetAtStackDecrement = (uint32_t)codeOffset; | |
| 595 | _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset(%d)\n", | |
| 596 | results->cfaRegisterOffset); | |
| 597 | break; | |
| 598 | case DW_CFA_def_cfa_expression: | |
| 599 | results->cfaRegister = 0; | |
| 600 | results->cfaExpression = (int64_t)p; | |
| 601 | length = addressSpace.getULEB128(p, instructionsEnd); | |
| 602 | assert(length < static_cast<pint_t>(~0) && "pointer overflow"); | |
| 603 | p += static_cast<pint_t>(length); | |
| 604 | _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_expression(expression=0x%" PRIx64 | |
| 605 | ", length=%" PRIu64 ")\n", | |
| 606 | results->cfaExpression, length); | |
| 607 | break; | |
| 608 | case DW_CFA_expression: | |
| 609 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 610 | if (reg > kMaxRegisterNumber) { | |
| 611 | _LIBUNWIND_LOG0( | |
| 612 | "malformed DW_CFA_expression DWARF unwind, reg too big"); | |
| 613 | return false; | |
| 614 | } | |
| 615 | results->setRegister(reg, kRegisterAtExpression, (int64_t)p, | |
| 616 | initialState); | |
| 617 | length = addressSpace.getULEB128(p, instructionsEnd); | |
| 618 | assert(length < static_cast<pint_t>(~0) && "pointer overflow"); | |
| 619 | p += static_cast<pint_t>(length); | |
| 620 | _LIBUNWIND_TRACE_DWARF("DW_CFA_expression(reg=%" PRIu64 ", " | |
| 621 | "expression=0x%" PRIx64 ", " | |
| 622 | "length=%" PRIu64 ")\n", | |
| 623 | reg, results->savedRegisters[reg].value, length); | |
| 624 | break; | |
| 625 | case DW_CFA_offset_extended_sf: | |
| 626 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 627 | if (reg > kMaxRegisterNumber) { | |
| 628 | _LIBUNWIND_LOG0( | |
| 629 | "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big"); | |
| 630 | return false; | |
| 631 | } | |
| 632 | offset = | |
| 633 | addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; | |
| 634 | results->setRegister(reg, kRegisterInCFA, offset, initialState); | |
| 635 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64 ", " | |
| 636 | "offset=%" PRId64 ")\n", | |
| 637 | reg, offset); | |
| 638 | break; | |
| 639 | case DW_CFA_def_cfa_sf: | |
| 640 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 641 | offset = | |
| 642 | addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; | |
| 643 | if (reg > kMaxRegisterNumber) { | |
| 644 | _LIBUNWIND_LOG0( | |
| 645 | "malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big"); | |
| 646 | return false; | |
| 647 | } | |
| 648 | results->cfaRegister = (uint32_t)reg; | |
| 649 | results->cfaRegisterOffset = (int32_t)offset; | |
| 650 | _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_sf(reg=%" PRIu64 ", " | |
| 651 | "offset=%" PRId64 ")\n", | |
| 652 | reg, offset); | |
| 653 | break; | |
| 654 | case DW_CFA_def_cfa_offset_sf: | |
| 655 | results->cfaRegisterOffset = (int32_t) | |
| 656 | (addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor); | |
| 657 | results->codeOffsetAtStackDecrement = (uint32_t)codeOffset; | |
| 658 | _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset_sf(%d)\n", | |
| 659 | results->cfaRegisterOffset); | |
| 660 | break; | |
| 661 | case DW_CFA_val_offset: | |
| 662 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 663 | if (reg > kMaxRegisterNumber) { | |
| 664 | _LIBUNWIND_LOG( | |
| 665 | "malformed DW_CFA_val_offset DWARF unwind, reg (%" PRIu64 | |
| 666 | ") out of range\n", | |
| 667 | reg); | |
| 668 | return false; | |
| 669 | } | |
| 670 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) | |
| 671 | * cieInfo.dataAlignFactor; | |
| 672 | results->setRegister(reg, kRegisterOffsetFromCFA, offset, initialState); | |
| 673 | _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64 ", " | |
| 674 | "offset=%" PRId64 "\n", | |
| 675 | reg, offset); | |
| 676 | break; | |
| 677 | case DW_CFA_val_offset_sf: | |
| 678 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 679 | if (reg > kMaxRegisterNumber) { | |
| 680 | _LIBUNWIND_LOG0( | |
| 681 | "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big"); | |
| 682 | return false; | |
| 683 | } | |
| 684 | offset = | |
| 685 | addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; | |
| 686 | results->setRegister(reg, kRegisterOffsetFromCFA, offset, initialState); | |
| 687 | _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64 ", " | |
| 688 | "offset=%" PRId64 "\n", | |
| 689 | reg, offset); | |
| 690 | break; | |
| 691 | case DW_CFA_val_expression: | |
| 692 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 693 | if (reg > kMaxRegisterNumber) { | |
| 694 | _LIBUNWIND_LOG0( | |
| 695 | "malformed DW_CFA_val_expression DWARF unwind, reg too big"); | |
| 696 | return false; | |
| 697 | } | |
| 698 | results->setRegister(reg, kRegisterIsExpression, (int64_t)p, | |
| 699 | initialState); | |
| 700 | length = addressSpace.getULEB128(p, instructionsEnd); | |
| 701 | assert(length < static_cast<pint_t>(~0) && "pointer overflow"); | |
| 702 | p += static_cast<pint_t>(length); | |
| 703 | _LIBUNWIND_TRACE_DWARF("DW_CFA_val_expression(reg=%" PRIu64 ", " | |
| 704 | "expression=0x%" PRIx64 ", length=%" PRIu64 ")\n", | |
| 705 | reg, results->savedRegisters[reg].value, length); | |
| 706 | break; | |
| 707 | case DW_CFA_GNU_args_size: | |
| 708 | length = addressSpace.getULEB128(p, instructionsEnd); | |
| 709 | results->spExtraArgSize = (uint32_t)length; | |
| 710 | _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_args_size(%" PRIu64 ")\n", length); | |
| 711 | break; | |
| 712 | case DW_CFA_GNU_negative_offset_extended: | |
| 713 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 714 | if (reg > kMaxRegisterNumber) { | |
| 715 | _LIBUNWIND_LOG0("malformed DW_CFA_GNU_negative_offset_extended DWARF " | |
| 716 | "unwind, reg too big"); | |
| 717 | return false; | |
| 417 | ParseInfo parseInfoArray[] = { | |
| 418 | {cieInfo.cieInstructions, cieInfo.cieStart + cieInfo.cieLength, | |
| 419 | (pint_t)(-1)}, | |
| 420 | {fdeInfo.fdeInstructions, fdeInfo.fdeStart + fdeInfo.fdeLength, | |
| 421 | upToPC - fdeInfo.pcStart}}; | |
| 422 | ||
| 423 | for (const auto &info : parseInfoArray) { | |
| 424 | pint_t p = info.instructions; | |
| 425 | pint_t instructionsEnd = info.instructionsEnd; | |
| 426 | pint_t pcoffset = info.pcoffset; | |
| 427 | pint_t codeOffset = 0; | |
| 428 | ||
| 429 | // initialState initialized as registers in results are modified. Use | |
| 430 | // PrologInfo accessor functions to avoid reading uninitialized data. | |
| 431 | PrologInfo initialState(PrologInfo::InitializeTime::kLazy); | |
| 432 | ||
| 433 | _LIBUNWIND_TRACE_DWARF("parseFDEInstructions(instructions=0x%0" PRIx64 | |
| 434 | ")\n", | |
| 435 | static_cast<uint64_t>(instructionsEnd)); | |
| 436 | ||
| 437 | // see DWARF Spec, section 6.4.2 for details on unwind opcodes | |
| 438 | while ((p < instructionsEnd) && (codeOffset < pcoffset)) { | |
| 439 | uint64_t reg; | |
| 440 | uint64_t reg2; | |
| 441 | int64_t offset; | |
| 442 | uint64_t length; | |
| 443 | uint8_t opcode = addressSpace.get8(p); | |
| 444 | uint8_t operand; | |
| 445 | ||
| 446 | ++p; | |
| 447 | switch (opcode) { | |
| 448 | case DW_CFA_nop: | |
| 449 | _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n"); | |
| 450 | break; | |
| 451 | case DW_CFA_set_loc: | |
| 452 | codeOffset = addressSpace.getEncodedP(p, instructionsEnd, | |
| 453 | cieInfo.pointerEncoding); | |
| 454 | _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n"); | |
| 455 | break; | |
| 456 | case DW_CFA_advance_loc1: | |
| 457 | codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor); | |
| 458 | p += 1; | |
| 459 | _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc1: new offset=%" PRIu64 "\n", | |
| 460 | static_cast<uint64_t>(codeOffset)); | |
| 461 | break; | |
| 462 | case DW_CFA_advance_loc2: | |
| 463 | codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor); | |
| 464 | p += 2; | |
| 465 | _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc2: new offset=%" PRIu64 "\n", | |
| 466 | static_cast<uint64_t>(codeOffset)); | |
| 467 | break; | |
| 468 | case DW_CFA_advance_loc4: | |
| 469 | codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor); | |
| 470 | p += 4; | |
| 471 | _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc4: new offset=%" PRIu64 "\n", | |
| 472 | static_cast<uint64_t>(codeOffset)); | |
| 473 | break; | |
| 474 | case DW_CFA_offset_extended: | |
| 475 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 476 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) * | |
| 477 | cieInfo.dataAlignFactor; | |
| 478 | if (reg > kMaxRegisterNumber) { | |
| 479 | _LIBUNWIND_LOG0( | |
| 480 | "malformed DW_CFA_offset_extended DWARF unwind, reg too big"); | |
| 481 | return false; | |
| 482 | } | |
| 483 | results->setRegister(reg, kRegisterInCFA, offset, initialState); | |
| 484 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", " | |
| 485 | "offset=%" PRId64 ")\n", | |
| 486 | reg, offset); | |
| 487 | break; | |
| 488 | case DW_CFA_restore_extended: | |
| 489 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 490 | if (reg > kMaxRegisterNumber) { | |
| 491 | _LIBUNWIND_LOG0( | |
| 492 | "malformed DW_CFA_restore_extended DWARF unwind, reg too big"); | |
| 493 | return false; | |
| 494 | } | |
| 495 | results->restoreRegisterToInitialState(reg, initialState); | |
| 496 | _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", | |
| 497 | reg); | |
| 498 | break; | |
| 499 | case DW_CFA_undefined: | |
| 500 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 501 | if (reg > kMaxRegisterNumber) { | |
| 502 | _LIBUNWIND_LOG0( | |
| 503 | "malformed DW_CFA_undefined DWARF unwind, reg too big"); | |
| 504 | return false; | |
| 505 | } | |
| 506 | results->setRegisterLocation(reg, kRegisterUndefined, initialState); | |
| 507 | _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg); | |
| 508 | break; | |
| 509 | case DW_CFA_same_value: | |
| 510 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 511 | if (reg > kMaxRegisterNumber) { | |
| 512 | _LIBUNWIND_LOG0( | |
| 513 | "malformed DW_CFA_same_value DWARF unwind, reg too big"); | |
| 514 | return false; | |
| 515 | } | |
| 516 | // <rdar://problem/8456377> DW_CFA_same_value unsupported | |
| 517 | // "same value" means register was stored in frame, but its current | |
| 518 | // value has not changed, so no need to restore from frame. | |
| 519 | // We model this as if the register was never saved. | |
| 520 | results->setRegisterLocation(reg, kRegisterUnused, initialState); | |
| 521 | _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg); | |
| 522 | break; | |
| 523 | case DW_CFA_register: | |
| 524 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 525 | reg2 = addressSpace.getULEB128(p, instructionsEnd); | |
| 526 | if (reg > kMaxRegisterNumber) { | |
| 527 | _LIBUNWIND_LOG0( | |
| 528 | "malformed DW_CFA_register DWARF unwind, reg too big"); | |
| 529 | return false; | |
| 530 | } | |
| 531 | if (reg2 > kMaxRegisterNumber) { | |
| 532 | _LIBUNWIND_LOG0( | |
| 533 | "malformed DW_CFA_register DWARF unwind, reg2 too big"); | |
| 534 | return false; | |
| 535 | } | |
| 536 | results->setRegister(reg, kRegisterInRegister, (int64_t)reg2, | |
| 537 | initialState); | |
| 538 | _LIBUNWIND_TRACE_DWARF( | |
| 539 | "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", reg, reg2); | |
| 540 | break; | |
| 541 | case DW_CFA_remember_state: { | |
| 542 | // Avoid operator new because that would be an upward dependency. | |
| 543 | // Avoid malloc because it needs heap allocation. | |
| 544 | PrologInfoStackEntry *entry = | |
| 545 | (PrologInfoStackEntry *)_LIBUNWIND_REMEMBER_ALLOC( | |
| 546 | sizeof(PrologInfoStackEntry)); | |
| 547 | if (entry != NULL) { | |
| 548 | entry->next = rememberStack.entry; | |
| 549 | entry->info = *results; | |
| 550 | rememberStack.entry = entry; | |
| 551 | } else { | |
| 552 | return false; | |
| 553 | } | |
| 554 | _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n"); | |
| 555 | break; | |
| 718 | 556 | } |
| 719 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) | |
| 720 | * cieInfo.dataAlignFactor; | |
| 721 | results->setRegister(reg, kRegisterInCFA, -offset, initialState); | |
| 722 | _LIBUNWIND_TRACE_DWARF( | |
| 723 | "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset); | |
| 724 | break; | |
| 557 | case DW_CFA_restore_state: | |
| 558 | if (rememberStack.entry != NULL) { | |
| 559 | PrologInfoStackEntry *top = rememberStack.entry; | |
| 560 | *results = top->info; | |
| 561 | rememberStack.entry = top->next; | |
| 562 | _LIBUNWIND_REMEMBER_FREE(top); | |
| 563 | } else { | |
| 564 | return false; | |
| 565 | } | |
| 566 | _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_state\n"); | |
| 567 | break; | |
| 568 | case DW_CFA_def_cfa: | |
| 569 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 570 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd); | |
| 571 | if (reg > kMaxRegisterNumber) { | |
| 572 | _LIBUNWIND_LOG0("malformed DW_CFA_def_cfa DWARF unwind, reg too big"); | |
| 573 | return false; | |
| 574 | } | |
| 575 | results->cfaRegister = (uint32_t)reg; | |
| 576 | results->cfaRegisterOffset = (int32_t)offset; | |
| 577 | _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa(reg=%" PRIu64 ", offset=%" PRIu64 | |
| 578 | ")\n", | |
| 579 | reg, offset); | |
| 580 | break; | |
| 581 | case DW_CFA_def_cfa_register: | |
| 582 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 583 | if (reg > kMaxRegisterNumber) { | |
| 584 | _LIBUNWIND_LOG0( | |
| 585 | "malformed DW_CFA_def_cfa_register DWARF unwind, reg too big"); | |
| 586 | return false; | |
| 587 | } | |
| 588 | results->cfaRegister = (uint32_t)reg; | |
| 589 | _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_register(%" PRIu64 ")\n", reg); | |
| 590 | break; | |
| 591 | case DW_CFA_def_cfa_offset: | |
| 592 | results->cfaRegisterOffset = | |
| 593 | (int32_t)addressSpace.getULEB128(p, instructionsEnd); | |
| 594 | _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset(%d)\n", | |
| 595 | results->cfaRegisterOffset); | |
| 596 | break; | |
| 597 | case DW_CFA_def_cfa_expression: | |
| 598 | results->cfaRegister = 0; | |
| 599 | results->cfaExpression = (int64_t)p; | |
| 600 | length = addressSpace.getULEB128(p, instructionsEnd); | |
| 601 | assert(length < static_cast<pint_t>(~0) && "pointer overflow"); | |
| 602 | p += static_cast<pint_t>(length); | |
| 603 | _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_expression(expression=0x%" PRIx64 | |
| 604 | ", length=%" PRIu64 ")\n", | |
| 605 | results->cfaExpression, length); | |
| 606 | break; | |
| 607 | case DW_CFA_expression: | |
| 608 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 609 | if (reg > kMaxRegisterNumber) { | |
| 610 | _LIBUNWIND_LOG0( | |
| 611 | "malformed DW_CFA_expression DWARF unwind, reg too big"); | |
| 612 | return false; | |
| 613 | } | |
| 614 | results->setRegister(reg, kRegisterAtExpression, (int64_t)p, | |
| 615 | initialState); | |
| 616 | length = addressSpace.getULEB128(p, instructionsEnd); | |
| 617 | assert(length < static_cast<pint_t>(~0) && "pointer overflow"); | |
| 618 | p += static_cast<pint_t>(length); | |
| 619 | _LIBUNWIND_TRACE_DWARF("DW_CFA_expression(reg=%" PRIu64 ", " | |
| 620 | "expression=0x%" PRIx64 ", " | |
| 621 | "length=%" PRIu64 ")\n", | |
| 622 | reg, results->savedRegisters[reg].value, length); | |
| 623 | break; | |
| 624 | case DW_CFA_offset_extended_sf: | |
| 625 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 626 | if (reg > kMaxRegisterNumber) { | |
| 627 | _LIBUNWIND_LOG0( | |
| 628 | "malformed DW_CFA_offset_extended_sf DWARF unwind, reg too big"); | |
| 629 | return false; | |
| 630 | } | |
| 631 | offset = addressSpace.getSLEB128(p, instructionsEnd) * | |
| 632 | cieInfo.dataAlignFactor; | |
| 633 | results->setRegister(reg, kRegisterInCFA, offset, initialState); | |
| 634 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64 ", " | |
| 635 | "offset=%" PRId64 ")\n", | |
| 636 | reg, offset); | |
| 637 | break; | |
| 638 | case DW_CFA_def_cfa_sf: | |
| 639 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 640 | offset = addressSpace.getSLEB128(p, instructionsEnd) * | |
| 641 | cieInfo.dataAlignFactor; | |
| 642 | if (reg > kMaxRegisterNumber) { | |
| 643 | _LIBUNWIND_LOG0( | |
| 644 | "malformed DW_CFA_def_cfa_sf DWARF unwind, reg too big"); | |
| 645 | return false; | |
| 646 | } | |
| 647 | results->cfaRegister = (uint32_t)reg; | |
| 648 | results->cfaRegisterOffset = (int32_t)offset; | |
| 649 | _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_sf(reg=%" PRIu64 ", " | |
| 650 | "offset=%" PRId64 ")\n", | |
| 651 | reg, offset); | |
| 652 | break; | |
| 653 | case DW_CFA_def_cfa_offset_sf: | |
| 654 | results->cfaRegisterOffset = | |
| 655 | (int32_t)(addressSpace.getSLEB128(p, instructionsEnd) * | |
| 656 | cieInfo.dataAlignFactor); | |
| 657 | _LIBUNWIND_TRACE_DWARF("DW_CFA_def_cfa_offset_sf(%d)\n", | |
| 658 | results->cfaRegisterOffset); | |
| 659 | break; | |
| 660 | case DW_CFA_val_offset: | |
| 661 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 662 | if (reg > kMaxRegisterNumber) { | |
| 663 | _LIBUNWIND_LOG( | |
| 664 | "malformed DW_CFA_val_offset DWARF unwind, reg (%" PRIu64 | |
| 665 | ") out of range\n", | |
| 666 | reg); | |
| 667 | return false; | |
| 668 | } | |
| 669 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) * | |
| 670 | cieInfo.dataAlignFactor; | |
| 671 | results->setRegister(reg, kRegisterOffsetFromCFA, offset, initialState); | |
| 672 | _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64 ", " | |
| 673 | "offset=%" PRId64 "\n", | |
| 674 | reg, offset); | |
| 675 | break; | |
| 676 | case DW_CFA_val_offset_sf: | |
| 677 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 678 | if (reg > kMaxRegisterNumber) { | |
| 679 | _LIBUNWIND_LOG0( | |
| 680 | "malformed DW_CFA_val_offset_sf DWARF unwind, reg too big"); | |
| 681 | return false; | |
| 682 | } | |
| 683 | offset = addressSpace.getSLEB128(p, instructionsEnd) * | |
| 684 | cieInfo.dataAlignFactor; | |
| 685 | results->setRegister(reg, kRegisterOffsetFromCFA, offset, initialState); | |
| 686 | _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64 ", " | |
| 687 | "offset=%" PRId64 "\n", | |
| 688 | reg, offset); | |
| 689 | break; | |
| 690 | case DW_CFA_val_expression: | |
| 691 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 692 | if (reg > kMaxRegisterNumber) { | |
| 693 | _LIBUNWIND_LOG0( | |
| 694 | "malformed DW_CFA_val_expression DWARF unwind, reg too big"); | |
| 695 | return false; | |
| 696 | } | |
| 697 | results->setRegister(reg, kRegisterIsExpression, (int64_t)p, | |
| 698 | initialState); | |
| 699 | length = addressSpace.getULEB128(p, instructionsEnd); | |
| 700 | assert(length < static_cast<pint_t>(~0) && "pointer overflow"); | |
| 701 | p += static_cast<pint_t>(length); | |
| 702 | _LIBUNWIND_TRACE_DWARF("DW_CFA_val_expression(reg=%" PRIu64 ", " | |
| 703 | "expression=0x%" PRIx64 ", length=%" PRIu64 | |
| 704 | ")\n", | |
| 705 | reg, results->savedRegisters[reg].value, length); | |
| 706 | break; | |
| 707 | case DW_CFA_GNU_args_size: | |
| 708 | length = addressSpace.getULEB128(p, instructionsEnd); | |
| 709 | results->spExtraArgSize = (uint32_t)length; | |
| 710 | _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_args_size(%" PRIu64 ")\n", length); | |
| 711 | break; | |
| 712 | case DW_CFA_GNU_negative_offset_extended: | |
| 713 | reg = addressSpace.getULEB128(p, instructionsEnd); | |
| 714 | if (reg > kMaxRegisterNumber) { | |
| 715 | _LIBUNWIND_LOG0("malformed DW_CFA_GNU_negative_offset_extended DWARF " | |
| 716 | "unwind, reg too big"); | |
| 717 | return false; | |
| 718 | } | |
| 719 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) * | |
| 720 | cieInfo.dataAlignFactor; | |
| 721 | results->setRegister(reg, kRegisterInCFA, -offset, initialState); | |
| 722 | _LIBUNWIND_TRACE_DWARF( | |
| 723 | "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset); | |
| 724 | break; | |
| 725 | 725 | |
| 726 | 726 | #if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC) |
| 727 | // The same constant is used to represent different instructions on | |
| 728 | // AArch64 (negate_ra_state) and SPARC (window_save). | |
| 729 | static_assert(DW_CFA_AARCH64_negate_ra_state == DW_CFA_GNU_window_save, | |
| 730 | "uses the same constant"); | |
| 731 | case DW_CFA_AARCH64_negate_ra_state: | |
| 732 | switch (arch) { | |
| 727 | // The same constant is used to represent different instructions on | |
| 728 | // AArch64 (negate_ra_state) and SPARC (window_save). | |
| 729 | static_assert(DW_CFA_AARCH64_negate_ra_state == DW_CFA_GNU_window_save, | |
| 730 | "uses the same constant"); | |
| 731 | case DW_CFA_AARCH64_negate_ra_state: | |
| 732 | switch (arch) { | |
| 733 | 733 | #if defined(_LIBUNWIND_TARGET_AARCH64) |
| 734 | 734 | case REGISTERS_ARM64: { |
| 735 | 735 | int64_t value = |
| 736 | 736 | results->savedRegisters[UNW_ARM64_RA_SIGN_STATE].value ^ 0x1; |
| 737 | results->setRegisterValue(UNW_ARM64_RA_SIGN_STATE, value, initialState); | |
| 737 | results->setRegisterValue(UNW_ARM64_RA_SIGN_STATE, value, | |
| 738 | initialState); | |
| 738 | 739 | _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n"); |
| 739 | 740 | } break; |
| 740 | 741 | #endif |
| 741 | 742 | |
| 742 | 743 | #if defined(_LIBUNWIND_TARGET_SPARC) |
| 743 | // case DW_CFA_GNU_window_save: | |
| 744 | case REGISTERS_SPARC: | |
| 745 | _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n"); | |
| 746 | for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) { | |
| 747 | results->setRegister(reg, kRegisterInRegister, | |
| 748 | ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0, | |
| 749 | initialState); | |
| 750 | } | |
| 744 | // case DW_CFA_GNU_window_save: | |
| 745 | case REGISTERS_SPARC: | |
| 746 | _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n"); | |
| 747 | for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) { | |
| 748 | results->setRegister(reg, kRegisterInRegister, | |
| 749 | ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0, | |
| 750 | initialState); | |
| 751 | } | |
| 751 | 752 | |
| 752 | for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) { | |
| 753 | results->setRegister(reg, kRegisterInCFA, | |
| 754 | ((int64_t)reg - UNW_SPARC_L0) * 4, initialState); | |
| 753 | for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) { | |
| 754 | results->setRegister(reg, kRegisterInCFA, | |
| 755 | ((int64_t)reg - UNW_SPARC_L0) * 4, | |
| 756 | initialState); | |
| 757 | } | |
| 758 | break; | |
| 759 | #endif | |
| 755 | 760 | } |
| 756 | 761 | break; |
| 757 | #endif | |
| 758 | } | |
| 759 | break; | |
| 760 | 762 | #else |
| 761 | (void)arch; | |
| 763 | (void)arch; | |
| 762 | 764 | #endif |
| 763 | 765 | |
| 764 | default: | |
| 765 | operand = opcode & 0x3F; | |
| 766 | switch (opcode & 0xC0) { | |
| 767 | case DW_CFA_offset: | |
| 768 | reg = operand; | |
| 769 | if (reg > kMaxRegisterNumber) { | |
| 770 | _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64 | |
| 771 | ") out of range", | |
| 772 | reg); | |
| 773 | return false; | |
| 774 | } | |
| 775 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) | |
| 776 | * cieInfo.dataAlignFactor; | |
| 777 | results->setRegister(reg, kRegisterInCFA, offset, initialState); | |
| 778 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n", | |
| 779 | operand, offset); | |
| 780 | break; | |
| 781 | case DW_CFA_advance_loc: | |
| 782 | codeOffset += operand * cieInfo.codeAlignFactor; | |
| 783 | _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc: new offset=%" PRIu64 "\n", | |
| 784 | static_cast<uint64_t>(codeOffset)); | |
| 785 | break; | |
| 786 | case DW_CFA_restore: | |
| 787 | reg = operand; | |
| 788 | if (reg > kMaxRegisterNumber) { | |
| 789 | _LIBUNWIND_LOG("malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64 | |
| 790 | ") out of range", | |
| 791 | reg); | |
| 766 | default: | |
| 767 | operand = opcode & 0x3F; | |
| 768 | switch (opcode & 0xC0) { | |
| 769 | case DW_CFA_offset: | |
| 770 | reg = operand; | |
| 771 | if (reg > kMaxRegisterNumber) { | |
| 772 | _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64 | |
| 773 | ") out of range", | |
| 774 | reg); | |
| 775 | return false; | |
| 776 | } | |
| 777 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) * | |
| 778 | cieInfo.dataAlignFactor; | |
| 779 | results->setRegister(reg, kRegisterInCFA, offset, initialState); | |
| 780 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n", | |
| 781 | operand, offset); | |
| 782 | break; | |
| 783 | case DW_CFA_advance_loc: | |
| 784 | codeOffset += operand * cieInfo.codeAlignFactor; | |
| 785 | _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc: new offset=%" PRIu64 "\n", | |
| 786 | static_cast<uint64_t>(codeOffset)); | |
| 787 | break; | |
| 788 | case DW_CFA_restore: | |
| 789 | reg = operand; | |
| 790 | if (reg > kMaxRegisterNumber) { | |
| 791 | _LIBUNWIND_LOG( | |
| 792 | "malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64 | |
| 793 | ") out of range", | |
| 794 | reg); | |
| 795 | return false; | |
| 796 | } | |
| 797 | results->restoreRegisterToInitialState(reg, initialState); | |
| 798 | _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n", | |
| 799 | static_cast<uint64_t>(operand)); | |
| 800 | break; | |
| 801 | default: | |
| 802 | _LIBUNWIND_TRACE_DWARF("unknown CFA opcode 0x%02X\n", opcode); | |
| 792 | 803 | return false; |
| 793 | 804 | } |
| 794 | results->restoreRegisterToInitialState(reg, initialState); | |
| 795 | _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n", | |
| 796 | static_cast<uint64_t>(operand)); | |
| 797 | break; | |
| 798 | default: | |
| 799 | _LIBUNWIND_TRACE_DWARF("unknown CFA opcode 0x%02X\n", opcode); | |
| 800 | return false; | |
| 801 | 805 | } |
| 802 | 806 | } |
| 803 | 807 | } |
| 804 | ||
| 805 | 808 | return true; |
| 806 | 809 | } |
| 807 | 810 |
lib/libunwind/src/FrameHeaderCache.hpp+1-1| ... | ... | @@ -32,7 +32,7 @@ |
| 32 | 32 | class _LIBUNWIND_HIDDEN FrameHeaderCache { |
| 33 | 33 | struct CacheEntry { |
| 34 | 34 | uintptr_t LowPC() { return Info.dso_base; }; |
| 35 | uintptr_t HighPC() { return Info.dso_base + Info.dwarf_section_length; }; | |
| 35 | uintptr_t HighPC() { return Info.dso_base + Info.text_segment_length; }; | |
| 36 | 36 | UnwindInfoSections Info; |
| 37 | 37 | CacheEntry *Next; |
| 38 | 38 | }; |
lib/libunwind/src/Registers.hpp+11-5| ... | ... | @@ -39,6 +39,8 @@ enum { |
| 39 | 39 | }; |
| 40 | 40 | |
| 41 | 41 | #if defined(_LIBUNWIND_TARGET_I386) |
| 42 | class _LIBUNWIND_HIDDEN Registers_x86; | |
| 43 | extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *); | |
| 42 | 44 | /// Registers_x86 holds the register state of a thread in a 32-bit intel |
| 43 | 45 | /// process. |
| 44 | 46 | class _LIBUNWIND_HIDDEN Registers_x86 { |
| ... | ... | @@ -56,7 +58,7 @@ public: |
| 56 | 58 | v128 getVectorRegister(int num) const; |
| 57 | 59 | void setVectorRegister(int num, v128 value); |
| 58 | 60 | static const char *getRegisterName(int num); |
| 59 | void jumpto(); | |
| 61 | void jumpto() { __libunwind_Registers_x86_jumpto(this); } | |
| 60 | 62 | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; } |
| 61 | 63 | static int getArch() { return REGISTERS_X86; } |
| 62 | 64 | |
| ... | ... | @@ -248,6 +250,8 @@ inline void Registers_x86::setVectorRegister(int, v128) { |
| 248 | 250 | #if defined(_LIBUNWIND_TARGET_X86_64) |
| 249 | 251 | /// Registers_x86_64 holds the register state of a thread in a 64-bit intel |
| 250 | 252 | /// process. |
| 253 | class _LIBUNWIND_HIDDEN Registers_x86_64; | |
| 254 | extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *); | |
| 251 | 255 | class _LIBUNWIND_HIDDEN Registers_x86_64 { |
| 252 | 256 | public: |
| 253 | 257 | Registers_x86_64(); |
| ... | ... | @@ -263,7 +267,7 @@ public: |
| 263 | 267 | v128 getVectorRegister(int num) const; |
| 264 | 268 | void setVectorRegister(int num, v128 value); |
| 265 | 269 | static const char *getRegisterName(int num); |
| 266 | void jumpto(); | |
| 270 | void jumpto() { __libunwind_Registers_x86_64_jumpto(this); } | |
| 267 | 271 | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; } |
| 268 | 272 | static int getArch() { return REGISTERS_X86_64; } |
| 269 | 273 | |
| ... | ... | @@ -1510,12 +1514,12 @@ inline void Registers_ppc64::setFloatRegister(int regNum, double value) { |
| 1510 | 1514 | } |
| 1511 | 1515 | |
| 1512 | 1516 | inline bool Registers_ppc64::validVectorRegister(int regNum) const { |
| 1513 | #ifdef PPC64_HAS_VMX | |
| 1517 | #if defined(__VSX__) | |
| 1514 | 1518 | if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31) |
| 1515 | 1519 | return true; |
| 1516 | 1520 | if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63) |
| 1517 | 1521 | return true; |
| 1518 | #else | |
| 1522 | #elif defined(__ALTIVEC__) | |
| 1519 | 1523 | if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31) |
| 1520 | 1524 | return true; |
| 1521 | 1525 | #endif |
| ... | ... | @@ -1771,6 +1775,8 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) { |
| 1771 | 1775 | #if defined(_LIBUNWIND_TARGET_AARCH64) |
| 1772 | 1776 | /// Registers_arm64 holds the register state of a thread in a 64-bit arm |
| 1773 | 1777 | /// process. |
| 1778 | class _LIBUNWIND_HIDDEN Registers_arm64; | |
| 1779 | extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *); | |
| 1774 | 1780 | class _LIBUNWIND_HIDDEN Registers_arm64 { |
| 1775 | 1781 | public: |
| 1776 | 1782 | Registers_arm64(); |
| ... | ... | @@ -1786,7 +1792,7 @@ public: |
| 1786 | 1792 | v128 getVectorRegister(int num) const; |
| 1787 | 1793 | void setVectorRegister(int num, v128 value); |
| 1788 | 1794 | static const char *getRegisterName(int num); |
| 1789 | void jumpto(); | |
| 1795 | void jumpto() { __libunwind_Registers_arm64_jumpto(this); } | |
| 1790 | 1796 | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; } |
| 1791 | 1797 | static int getArch() { return REGISTERS_ARM64; } |
| 1792 | 1798 |
lib/libunwind/src/Unwind-seh.cpp+4-16| ... | ... | @@ -46,18 +46,6 @@ using namespace libunwind; |
| 46 | 46 | /// handling. |
| 47 | 47 | #define STATUS_GCC_UNWIND MAKE_GCC_EXCEPTION(1) // 0x21474343 |
| 48 | 48 | |
| 49 | /// Class of foreign exceptions based on unrecognized SEH exceptions. | |
| 50 | static const uint64_t kSEHExceptionClass = 0x434C4E4753454800; // CLNGSEH\0 | |
| 51 | ||
| 52 | /// Exception cleanup routine used by \c _GCC_specific_handler to | |
| 53 | /// free foreign exceptions. | |
| 54 | static void seh_exc_cleanup(_Unwind_Reason_Code urc, _Unwind_Exception *exc) { | |
| 55 | (void)urc; | |
| 56 | if (exc->exception_class != kSEHExceptionClass) | |
| 57 | _LIBUNWIND_ABORT("SEH cleanup called on non-SEH exception"); | |
| 58 | free(exc); | |
| 59 | } | |
| 60 | ||
| 61 | 49 | static int __unw_init_seh(unw_cursor_t *cursor, CONTEXT *ctx); |
| 62 | 50 | static DISPATCHER_CONTEXT *__unw_seh_get_disp_ctx(unw_cursor_t *cursor); |
| 63 | 51 | static void __unw_seh_set_disp_ctx(unw_cursor_t *cursor, |
| ... | ... | @@ -108,10 +96,10 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, |
| 108 | 96 | } |
| 109 | 97 | } else { |
| 110 | 98 | // Foreign exception. |
| 111 | exc = (_Unwind_Exception *)malloc(sizeof(_Unwind_Exception)); | |
| 112 | exc->exception_class = kSEHExceptionClass; | |
| 113 | exc->exception_cleanup = seh_exc_cleanup; | |
| 114 | memset(exc->private_, 0, sizeof(exc->private_)); | |
| 99 | // We can't interact with them (we don't know the original target frame | |
| 100 | // that we should pass on to RtlUnwindEx in _Unwind_Resume), so just | |
| 101 | // pass without calling our destructors here. | |
| 102 | return ExceptionContinueSearch; | |
| 115 | 103 | } |
| 116 | 104 | if (!ctx) { |
| 117 | 105 | __unw_init_seh(&cursor, disp->ContextRecord); |
lib/libunwind/src/UnwindCursor.hpp+51-64| ... | ... | @@ -81,6 +81,7 @@ template <typename A> |
| 81 | 81 | class _LIBUNWIND_HIDDEN DwarfFDECache { |
| 82 | 82 | typedef typename A::pint_t pint_t; |
| 83 | 83 | public: |
| 84 | static constexpr pint_t kSearchAll = static_cast<pint_t>(-1); | |
| 84 | 85 | static pint_t findFDE(pint_t mh, pint_t pc); |
| 85 | 86 | static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde); |
| 86 | 87 | static void removeAllIn(pint_t mh); |
| ... | ... | @@ -138,7 +139,7 @@ typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) { |
| 138 | 139 | pint_t result = 0; |
| 139 | 140 | _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared()); |
| 140 | 141 | for (entry *p = _buffer; p < _bufferUsed; ++p) { |
| 141 | if ((mh == p->mh) || (mh == 0)) { | |
| 142 | if ((mh == p->mh) || (mh == kSearchAll)) { | |
| 142 | 143 | if ((p->ip_start <= pc) && (pc < p->ip_end)) { |
| 143 | 144 | result = p->fde; |
| 144 | 145 | break; |
| ... | ... | @@ -530,6 +531,8 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as) |
| 530 | 531 | : _addressSpace(as), _unwindInfoMissing(false) { |
| 531 | 532 | static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit), |
| 532 | 533 | "UnwindCursor<> does not fit in unw_cursor_t"); |
| 534 | static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)), | |
| 535 | "UnwindCursor<> requires more alignment than unw_cursor_t"); | |
| 533 | 536 | memset(&_info, 0, sizeof(_info)); |
| 534 | 537 | memset(&_histTable, 0, sizeof(_histTable)); |
| 535 | 538 | _dispContext.ContextRecord = &_msContext; |
| ... | ... | @@ -923,6 +926,9 @@ private: |
| 923 | 926 | #endif |
| 924 | 927 | |
| 925 | 928 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
| 929 | bool getInfoFromFdeCie(const typename CFI_Parser<A>::FDE_Info &fdeInfo, | |
| 930 | const typename CFI_Parser<A>::CIE_Info &cieInfo, | |
| 931 | pint_t pc, uintptr_t dso_base); | |
| 926 | 932 | bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections &sects, |
| 927 | 933 | uint32_t fdeSectionOffsetHint=0); |
| 928 | 934 | int stepWithDwarfFDE() { |
| ... | ... | @@ -1182,6 +1188,8 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as) |
| 1182 | 1188 | _isSignalFrame(false) { |
| 1183 | 1189 | static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit), |
| 1184 | 1190 | "UnwindCursor<> does not fit in unw_cursor_t"); |
| 1191 | static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)), | |
| 1192 | "UnwindCursor<> requires more alignment than unw_cursor_t"); | |
| 1185 | 1193 | memset(&_info, 0, sizeof(_info)); |
| 1186 | 1194 | } |
| 1187 | 1195 | |
| ... | ... | @@ -1472,6 +1480,32 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection( |
| 1472 | 1480 | #endif |
| 1473 | 1481 | |
| 1474 | 1482 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
| 1483 | template <typename A, typename R> | |
| 1484 | bool UnwindCursor<A, R>::getInfoFromFdeCie( | |
| 1485 | const typename CFI_Parser<A>::FDE_Info &fdeInfo, | |
| 1486 | const typename CFI_Parser<A>::CIE_Info &cieInfo, pint_t pc, | |
| 1487 | uintptr_t dso_base) { | |
| 1488 | typename CFI_Parser<A>::PrologInfo prolog; | |
| 1489 | if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc, | |
| 1490 | R::getArch(), &prolog)) { | |
| 1491 | // Save off parsed FDE info | |
| 1492 | _info.start_ip = fdeInfo.pcStart; | |
| 1493 | _info.end_ip = fdeInfo.pcEnd; | |
| 1494 | _info.lsda = fdeInfo.lsda; | |
| 1495 | _info.handler = cieInfo.personality; | |
| 1496 | // Some frameless functions need SP altered when resuming in function, so | |
| 1497 | // propagate spExtraArgSize. | |
| 1498 | _info.gp = prolog.spExtraArgSize; | |
| 1499 | _info.flags = 0; | |
| 1500 | _info.format = dwarfEncoding(); | |
| 1501 | _info.unwind_info = fdeInfo.fdeStart; | |
| 1502 | _info.unwind_info_size = static_cast<uint32_t>(fdeInfo.fdeLength); | |
| 1503 | _info.extra = static_cast<unw_word_t>(dso_base); | |
| 1504 | return true; | |
| 1505 | } | |
| 1506 | return false; | |
| 1507 | } | |
| 1508 | ||
| 1475 | 1509 | template <typename A, typename R> |
| 1476 | 1510 | bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, |
| 1477 | 1511 | const UnwindInfoSections &sects, |
| ... | ... | @@ -1483,7 +1517,7 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, |
| 1483 | 1517 | // If compact encoding table gave offset into dwarf section, go directly there |
| 1484 | 1518 | if (fdeSectionOffsetHint != 0) { |
| 1485 | 1519 | foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section, |
| 1486 | (uint32_t)sects.dwarf_section_length, | |
| 1520 | sects.dwarf_section_length, | |
| 1487 | 1521 | sects.dwarf_section + fdeSectionOffsetHint, |
| 1488 | 1522 | &fdeInfo, &cieInfo); |
| 1489 | 1523 | } |
| ... | ... | @@ -1500,7 +1534,7 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, |
| 1500 | 1534 | if (cachedFDE != 0) { |
| 1501 | 1535 | foundFDE = |
| 1502 | 1536 | CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section, |
| 1503 | (uint32_t)sects.dwarf_section_length, | |
| 1537 | sects.dwarf_section_length, | |
| 1504 | 1538 | cachedFDE, &fdeInfo, &cieInfo); |
| 1505 | 1539 | foundInCache = foundFDE; |
| 1506 | 1540 | } |
| ... | ... | @@ -1508,25 +1542,11 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, |
| 1508 | 1542 | if (!foundFDE) { |
| 1509 | 1543 | // Still not found, do full scan of __eh_frame section. |
| 1510 | 1544 | foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section, |
| 1511 | (uint32_t)sects.dwarf_section_length, 0, | |
| 1545 | sects.dwarf_section_length, 0, | |
| 1512 | 1546 | &fdeInfo, &cieInfo); |
| 1513 | 1547 | } |
| 1514 | 1548 | if (foundFDE) { |
| 1515 | typename CFI_Parser<A>::PrologInfo prolog; | |
| 1516 | if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc, | |
| 1517 | R::getArch(), &prolog)) { | |
| 1518 | // Save off parsed FDE info | |
| 1519 | _info.start_ip = fdeInfo.pcStart; | |
| 1520 | _info.end_ip = fdeInfo.pcEnd; | |
| 1521 | _info.lsda = fdeInfo.lsda; | |
| 1522 | _info.handler = cieInfo.personality; | |
| 1523 | _info.gp = prolog.spExtraArgSize; | |
| 1524 | _info.flags = 0; | |
| 1525 | _info.format = dwarfEncoding(); | |
| 1526 | _info.unwind_info = fdeInfo.fdeStart; | |
| 1527 | _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength; | |
| 1528 | _info.extra = (unw_word_t) sects.dso_base; | |
| 1529 | ||
| 1549 | if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, sects.dso_base)) { | |
| 1530 | 1550 | // Add to cache (to make next lookup faster) if we had no hint |
| 1531 | 1551 | // and there was no index. |
| 1532 | 1552 | if (!foundInCache && (fdeSectionOffsetHint == 0)) { |
| ... | ... | @@ -1759,12 +1779,12 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc, |
| 1759 | 1779 | } |
| 1760 | 1780 | } |
| 1761 | 1781 | |
| 1762 | // extact personality routine, if encoding says function has one | |
| 1782 | // extract personality routine, if encoding says function has one | |
| 1763 | 1783 | uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >> |
| 1764 | 1784 | (__builtin_ctz(UNWIND_PERSONALITY_MASK)); |
| 1765 | 1785 | if (personalityIndex != 0) { |
| 1766 | 1786 | --personalityIndex; // change 1-based to zero-based index |
| 1767 | if (personalityIndex > sectionHeader.personalityArrayCount()) { | |
| 1787 | if (personalityIndex >= sectionHeader.personalityArrayCount()) { | |
| 1768 | 1788 | _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, " |
| 1769 | 1789 | "but personality table has only %d entries", |
| 1770 | 1790 | encoding, personalityIndex, |
| ... | ... | @@ -1926,60 +1946,27 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { |
| 1926 | 1946 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
| 1927 | 1947 | // There is no static unwind info for this pc. Look to see if an FDE was |
| 1928 | 1948 | // dynamically registered for it. |
| 1929 | pint_t cachedFDE = DwarfFDECache<A>::findFDE(0, pc); | |
| 1949 | pint_t cachedFDE = DwarfFDECache<A>::findFDE(DwarfFDECache<A>::kSearchAll, | |
| 1950 | pc); | |
| 1930 | 1951 | if (cachedFDE != 0) { |
| 1931 | CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo; | |
| 1932 | CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo; | |
| 1933 | const char *msg = CFI_Parser<A>::decodeFDE(_addressSpace, | |
| 1934 | cachedFDE, &fdeInfo, &cieInfo); | |
| 1935 | if (msg == NULL) { | |
| 1936 | typename CFI_Parser<A>::PrologInfo prolog; | |
| 1937 | if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, | |
| 1938 | pc, R::getArch(), &prolog)) { | |
| 1939 | // save off parsed FDE info | |
| 1940 | _info.start_ip = fdeInfo.pcStart; | |
| 1941 | _info.end_ip = fdeInfo.pcEnd; | |
| 1942 | _info.lsda = fdeInfo.lsda; | |
| 1943 | _info.handler = cieInfo.personality; | |
| 1944 | _info.gp = prolog.spExtraArgSize; | |
| 1945 | // Some frameless functions need SP | |
| 1946 | // altered when resuming in function. | |
| 1947 | _info.flags = 0; | |
| 1948 | _info.format = dwarfEncoding(); | |
| 1949 | _info.unwind_info = fdeInfo.fdeStart; | |
| 1950 | _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength; | |
| 1951 | _info.extra = 0; | |
| 1952 | typename CFI_Parser<A>::FDE_Info fdeInfo; | |
| 1953 | typename CFI_Parser<A>::CIE_Info cieInfo; | |
| 1954 | if (!CFI_Parser<A>::decodeFDE(_addressSpace, cachedFDE, &fdeInfo, &cieInfo)) | |
| 1955 | if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, 0)) | |
| 1952 | 1956 | return; |
| 1953 | } | |
| 1954 | } | |
| 1955 | 1957 | } |
| 1956 | 1958 | |
| 1957 | 1959 | // Lastly, ask AddressSpace object about platform specific ways to locate |
| 1958 | 1960 | // other FDEs. |
| 1959 | 1961 | pint_t fde; |
| 1960 | 1962 | if (_addressSpace.findOtherFDE(pc, fde)) { |
| 1961 | CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo; | |
| 1962 | CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo; | |
| 1963 | typename CFI_Parser<A>::FDE_Info fdeInfo; | |
| 1964 | typename CFI_Parser<A>::CIE_Info cieInfo; | |
| 1963 | 1965 | if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) { |
| 1964 | 1966 | // Double check this FDE is for a function that includes the pc. |
| 1965 | if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) { | |
| 1966 | typename CFI_Parser<A>::PrologInfo prolog; | |
| 1967 | if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, | |
| 1968 | pc, R::getArch(), &prolog)) { | |
| 1969 | // save off parsed FDE info | |
| 1970 | _info.start_ip = fdeInfo.pcStart; | |
| 1971 | _info.end_ip = fdeInfo.pcEnd; | |
| 1972 | _info.lsda = fdeInfo.lsda; | |
| 1973 | _info.handler = cieInfo.personality; | |
| 1974 | _info.gp = prolog.spExtraArgSize; | |
| 1975 | _info.flags = 0; | |
| 1976 | _info.format = dwarfEncoding(); | |
| 1977 | _info.unwind_info = fdeInfo.fdeStart; | |
| 1978 | _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength; | |
| 1979 | _info.extra = 0; | |
| 1967 | if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) | |
| 1968 | if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, 0)) | |
| 1980 | 1969 | return; |
| 1981 | } | |
| 1982 | } | |
| 1983 | 1970 | } |
| 1984 | 1971 | } |
| 1985 | 1972 | #endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
lib/libunwind/src/UnwindLevel1.c+1-3| ... | ... | @@ -39,8 +39,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 39 | 39 | __unw_init_local(cursor, uc); |
| 40 | 40 | |
| 41 | 41 | // Walk each frame looking for a place to stop. |
| 42 | bool handlerNotFound = true; | |
| 43 | while (handlerNotFound) { | |
| 42 | while (true) { | |
| 44 | 43 | // Ask libunwind to get next frame (skip over first which is |
| 45 | 44 | // _Unwind_RaiseException). |
| 46 | 45 | int stepResult = __unw_step(cursor); |
| ... | ... | @@ -102,7 +101,6 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 102 | 101 | case _URC_HANDLER_FOUND: |
| 103 | 102 | // found a catch clause or locals that need destructing in this frame |
| 104 | 103 | // stop search and remember stack pointer at the frame |
| 105 | handlerNotFound = false; | |
| 106 | 104 | __unw_get_reg(cursor, UNW_REG_SP, &sp); |
| 107 | 105 | exception_object->private_2 = (uintptr_t)sp; |
| 108 | 106 | _LIBUNWIND_TRACE_UNWINDING( |
lib/libunwind/src/UnwindRegistersRestore.S+13-12| ... | ... | @@ -13,14 +13,10 @@ |
| 13 | 13 | #if !defined(__USING_SJLJ_EXCEPTIONS__) |
| 14 | 14 | |
| 15 | 15 | #if defined(__i386__) |
| 16 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv) | |
| 16 | DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_jumpto) | |
| 17 | 17 | # |
| 18 | # void libunwind::Registers_x86::jumpto() | |
| 18 | # extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *); | |
| 19 | 19 | # |
| 20 | #if defined(_WIN32) | |
| 21 | # On windows, the 'this' pointer is passed in ecx instead of on the stack | |
| 22 | movl %ecx, %eax | |
| 23 | #else | |
| 24 | 20 | # On entry: |
| 25 | 21 | # + + |
| 26 | 22 | # +-----------------------+ |
| ... | ... | @@ -30,7 +26,6 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv) |
| 30 | 26 | # +-----------------------+ <-- SP |
| 31 | 27 | # + + |
| 32 | 28 | movl 4(%esp), %eax |
| 33 | #endif | |
| 34 | 29 | # set up eax and ret on new stack location |
| 35 | 30 | movl 28(%eax), %edx # edx holds new stack pointer |
| 36 | 31 | subl $8,%edx |
| ... | ... | @@ -60,9 +55,9 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv) |
| 60 | 55 | |
| 61 | 56 | #elif defined(__x86_64__) |
| 62 | 57 | |
| 63 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind16Registers_x86_646jumptoEv) | |
| 58 | DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto) | |
| 64 | 59 | # |
| 65 | # void libunwind::Registers_x86_64::jumpto() | |
| 60 | # extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *); | |
| 66 | 61 | # |
| 67 | 62 | #if defined(_WIN64) |
| 68 | 63 | # On entry, thread_state pointer is in rcx; move it into rdi |
| ... | ... | @@ -175,7 +170,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv) |
| 175 | 170 | PPC64_LR(30) |
| 176 | 171 | PPC64_LR(31) |
| 177 | 172 | |
| 178 | #ifdef PPC64_HAS_VMX | |
| 173 | #if defined(__VSX__) | |
| 179 | 174 | |
| 180 | 175 | // restore VS registers |
| 181 | 176 | // (note that this also restores floating point registers and V registers, |
| ... | ... | @@ -317,6 +312,7 @@ PPC64_CLVS_BOTTOM(n) |
| 317 | 312 | PPC64_LF(30) |
| 318 | 313 | PPC64_LF(31) |
| 319 | 314 | |
| 315 | #if defined(__ALTIVEC__) | |
| 320 | 316 | // restore vector registers if any are in use |
| 321 | 317 | ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave |
| 322 | 318 | cmpwi %r5, 0 |
| ... | ... | @@ -378,6 +374,7 @@ PPC64_CLV_UNALIGNED_BOTTOM(n) |
| 378 | 374 | PPC64_CLV_UNALIGNEDh(31) |
| 379 | 375 | |
| 380 | 376 | #endif |
| 377 | #endif | |
| 381 | 378 | |
| 382 | 379 | Lnovec: |
| 383 | 380 | ld %r0, PPC64_OFFS_CR(%r3) |
| ... | ... | @@ -436,6 +433,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) |
| 436 | 433 | lwz %r30,128(%r3) |
| 437 | 434 | lwz %r31,132(%r3) |
| 438 | 435 | |
| 436 | #ifndef __NO_FPRS__ | |
| 439 | 437 | // restore float registers |
| 440 | 438 | lfd %f0, 160(%r3) |
| 441 | 439 | lfd %f1, 168(%r3) |
| ... | ... | @@ -469,7 +467,9 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) |
| 469 | 467 | lfd %f29,392(%r3) |
| 470 | 468 | lfd %f30,400(%r3) |
| 471 | 469 | lfd %f31,408(%r3) |
| 470 | #endif | |
| 472 | 471 | |
| 472 | #if defined(__ALTIVEC__) | |
| 473 | 473 | // restore vector registers if any are in use |
| 474 | 474 | lwz %r5, 156(%r3) // test VRsave |
| 475 | 475 | cmpwi %r5, 0 |
| ... | ... | @@ -542,6 +542,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) |
| 542 | 542 | LOAD_VECTOR_UNALIGNEDh(29) |
| 543 | 543 | LOAD_VECTOR_UNALIGNEDh(30) |
| 544 | 544 | LOAD_VECTOR_UNALIGNEDh(31) |
| 545 | #endif | |
| 545 | 546 | |
| 546 | 547 | Lnovec: |
| 547 | 548 | lwz %r0, 136(%r3) // __cr |
| ... | ... | @@ -560,13 +561,13 @@ Lnovec: |
| 560 | 561 | #elif defined(__aarch64__) |
| 561 | 562 | |
| 562 | 563 | // |
| 563 | // void libunwind::Registers_arm64::jumpto() | |
| 564 | // extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *); | |
| 564 | 565 | // |
| 565 | 566 | // On entry: |
| 566 | 567 | // thread_state pointer is in x0 |
| 567 | 568 | // |
| 568 | 569 | .p2align 2 |
| 569 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv) | |
| 570 | DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) | |
| 570 | 571 | // skip restore of x0,x1 for now |
| 571 | 572 | ldp x2, x3, [x0, #0x010] |
| 572 | 573 | ldp x4, x5, [x0, #0x020] |
lib/libunwind/src/UnwindRegistersSave.S+7-2| ... | ... | @@ -384,7 +384,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 384 | 384 | mfvrsave %r0 |
| 385 | 385 | std %r0, PPC64_OFFS_VRSAVE(%r3) |
| 386 | 386 | |
| 387 | #ifdef PPC64_HAS_VMX | |
| 387 | #if defined(__VSX__) | |
| 388 | 388 | // save VS registers |
| 389 | 389 | // (note that this also saves floating point registers and V registers, |
| 390 | 390 | // because part of VS is mapped to these registers) |
| ... | ... | @@ -501,6 +501,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 501 | 501 | PPC64_STF(30) |
| 502 | 502 | PPC64_STF(31) |
| 503 | 503 | |
| 504 | #if defined(__ALTIVEC__) | |
| 504 | 505 | // save vector registers |
| 505 | 506 | |
| 506 | 507 | // Use 16-bytes below the stack pointer as an |
| ... | ... | @@ -548,6 +549,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 548 | 549 | PPC64_STV_UNALIGNED(30) |
| 549 | 550 | PPC64_STV_UNALIGNED(31) |
| 550 | 551 | |
| 552 | #endif | |
| 551 | 553 | #endif |
| 552 | 554 | |
| 553 | 555 | li %r3, 0 // return UNW_ESUCCESS |
| ... | ... | @@ -608,6 +610,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 608 | 610 | mfctr %r0 |
| 609 | 611 | stw %r0, 148(%r3) |
| 610 | 612 | |
| 613 | #if !defined(__NO_FPRS__) | |
| 611 | 614 | // save float registers |
| 612 | 615 | stfd %f0, 160(%r3) |
| 613 | 616 | stfd %f1, 168(%r3) |
| ... | ... | @@ -641,8 +644,9 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 641 | 644 | stfd %f29,392(%r3) |
| 642 | 645 | stfd %f30,400(%r3) |
| 643 | 646 | stfd %f31,408(%r3) |
| 647 | #endif | |
| 644 | 648 | |
| 645 | ||
| 649 | #if defined(__ALTIVEC__) | |
| 646 | 650 | // save vector registers |
| 647 | 651 | |
| 648 | 652 | subi %r4, %r1, 16 |
| ... | ... | @@ -692,6 +696,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 692 | 696 | SAVE_VECTOR_UNALIGNED(%v29, 424+0x1D0) |
| 693 | 697 | SAVE_VECTOR_UNALIGNED(%v30, 424+0x1E0) |
| 694 | 698 | SAVE_VECTOR_UNALIGNED(%v31, 424+0x1F0) |
| 699 | #endif | |
| 695 | 700 | |
| 696 | 701 | li %r3, 0 // return UNW_ESUCCESS |
| 697 | 702 | blr |
lib/libunwind/src/Unwind_AppleExtras.cpp-70| ... | ... | @@ -8,35 +8,6 @@ |
| 8 | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | |
| 10 | 10 | #include "config.h" |
| 11 | #include "AddressSpace.hpp" | |
| 12 | #include "DwarfParser.hpp" | |
| 13 | ||
| 14 | ||
| 15 | // private keymgr stuff | |
| 16 | #define KEYMGR_GCC3_DW2_OBJ_LIST 302 | |
| 17 | extern "C" { | |
| 18 | extern void _keymgr_set_and_unlock_processwide_ptr(int key, void *ptr); | |
| 19 | extern void *_keymgr_get_and_lock_processwide_ptr(int key); | |
| 20 | } | |
| 21 | ||
| 22 | // undocumented libgcc "struct object" | |
| 23 | struct libgcc_object { | |
| 24 | void *start; | |
| 25 | void *unused1; | |
| 26 | void *unused2; | |
| 27 | void *fde; | |
| 28 | unsigned long encoding; | |
| 29 | void *fde_end; | |
| 30 | libgcc_object *next; | |
| 31 | }; | |
| 32 | ||
| 33 | // undocumented libgcc "struct km_object_info" referenced by | |
| 34 | // KEYMGR_GCC3_DW2_OBJ_LIST | |
| 35 | struct libgcc_object_info { | |
| 36 | libgcc_object *seen_objects; | |
| 37 | libgcc_object *unseen_objects; | |
| 38 | unsigned spare[2]; | |
| 39 | }; | |
| 40 | 11 | |
| 41 | 12 | |
| 42 | 13 | // static linker symbols to prevent wrong two level namespace for _Unwind symbols |
| ... | ... | @@ -140,44 +111,3 @@ NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume_or_Rethrow) |
| 140 | 111 | NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Unregister) |
| 141 | 112 | |
| 142 | 113 | #endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS) |
| 143 | ||
| 144 | ||
| 145 | namespace libunwind { | |
| 146 | ||
| 147 | _LIBUNWIND_HIDDEN | |
| 148 | bool checkKeyMgrRegisteredFDEs(uintptr_t pc, void *&fde) { | |
| 149 | #if __MAC_OS_X_VERSION_MIN_REQUIRED | |
| 150 | // lastly check for old style keymgr registration of dynamically generated | |
| 151 | // FDEs acquire exclusive access to libgcc_object_info | |
| 152 | libgcc_object_info *head = (libgcc_object_info *) | |
| 153 | _keymgr_get_and_lock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST); | |
| 154 | if (head != NULL) { | |
| 155 | // look at each FDE in keymgr | |
| 156 | for (libgcc_object *ob = head->unseen_objects; ob != NULL; ob = ob->next) { | |
| 157 | CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo; | |
| 158 | CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo; | |
| 159 | const char *msg = CFI_Parser<LocalAddressSpace>::decodeFDE( | |
| 160 | LocalAddressSpace::sThisAddressSpace, | |
| 161 | (uintptr_t)ob->fde, &fdeInfo, &cieInfo); | |
| 162 | if (msg == NULL) { | |
| 163 | // Check if this FDE is for a function that includes the pc | |
| 164 | if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) { | |
| 165 | fde = (void*)fdeInfo.pcStart; | |
| 166 | _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, | |
| 167 | head); | |
| 168 | return true; | |
| 169 | } | |
| 170 | } | |
| 171 | } | |
| 172 | } | |
| 173 | // release libgcc_object_info | |
| 174 | _keymgr_set_and_unlock_processwide_ptr(KEYMGR_GCC3_DW2_OBJ_LIST, head); | |
| 175 | #else | |
| 176 | (void)pc; | |
| 177 | (void)fde; | |
| 178 | #endif | |
| 179 | return false; | |
| 180 | } | |
| 181 | ||
| 182 | } | |
| 183 |
lib/libunwind/src/assembly.h+20-4| ... | ... | @@ -25,9 +25,6 @@ |
| 25 | 25 | #define PPC64_OFFS_VRSAVE 304 |
| 26 | 26 | #define PPC64_OFFS_FP 312 |
| 27 | 27 | #define PPC64_OFFS_V 824 |
| 28 | #ifdef _ARCH_PWR8 | |
| 29 | #define PPC64_HAS_VMX | |
| 30 | #endif | |
| 31 | 28 | #elif defined(__APPLE__) && defined(__aarch64__) |
| 32 | 29 | #define SEPARATOR %% |
| 33 | 30 | #else |
| ... | ... | @@ -48,6 +45,24 @@ |
| 48 | 45 | #define PPC64_OPD2 |
| 49 | 46 | #endif |
| 50 | 47 | |
| 48 | #if defined(__ARM_FEATURE_BTI_DEFAULT) | |
| 49 | .pushsection ".note.gnu.property", "a" SEPARATOR \ | |
| 50 | .balign 8 SEPARATOR \ | |
| 51 | .long 4 SEPARATOR \ | |
| 52 | .long 0x10 SEPARATOR \ | |
| 53 | .long 0x5 SEPARATOR \ | |
| 54 | .asciz "GNU" SEPARATOR \ | |
| 55 | .long 0xc0000000 SEPARATOR /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */ \ | |
| 56 | .long 4 SEPARATOR \ | |
| 57 | .long 3 SEPARATOR /* GNU_PROPERTY_AARCH64_FEATURE_1_BTI AND */ \ | |
| 58 | /* GNU_PROPERTY_AARCH64_FEATURE_1_PAC */ \ | |
| 59 | .long 0 SEPARATOR \ | |
| 60 | .popsection SEPARATOR | |
| 61 | #define AARCH64_BTI bti c | |
| 62 | #else | |
| 63 | #define AARCH64_BTI | |
| 64 | #endif | |
| 65 | ||
| 51 | 66 | #define GLUE2(a, b) a ## b |
| 52 | 67 | #define GLUE(a, b) GLUE2(a, b) |
| 53 | 68 | #define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name) |
| ... | ... | @@ -144,7 +159,8 @@ |
| 144 | 159 | SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ |
| 145 | 160 | PPC64_OPD1 \ |
| 146 | 161 | SYMBOL_NAME(name): \ |
| 147 | PPC64_OPD2 | |
| 162 | PPC64_OPD2 \ | |
| 163 | AARCH64_BTI | |
| 148 | 164 | |
| 149 | 165 | #if defined(__arm__) |
| 150 | 166 | #if !defined(__ARM_ARCH) |
lib/libunwind/src/config.h+39-15| ... | ... | @@ -18,23 +18,15 @@ |
| 18 | 18 | #include <stdint.h> |
| 19 | 19 | #include <stdlib.h> |
| 20 | 20 | |
| 21 | // Define static_assert() unless already defined by compiler. | |
| 22 | #ifndef __has_feature | |
| 23 | #define __has_feature(__x) 0 | |
| 24 | #endif | |
| 25 | #if !(__has_feature(cxx_static_assert)) && !defined(static_assert) | |
| 26 | #define static_assert(__b, __m) \ | |
| 27 | extern int compile_time_assert_failed[ ( __b ) ? 1 : -1 ] \ | |
| 28 | __attribute__( ( unused ) ); | |
| 29 | #endif | |
| 21 | #include <__libunwind_config.h> | |
| 30 | 22 | |
| 31 | 23 | // Platform specific configuration defines. |
| 32 | 24 | #ifdef __APPLE__ |
| 33 | 25 | #if defined(FOR_DYLD) |
| 34 | #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND | |
| 26 | #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1 | |
| 35 | 27 | #else |
| 36 | #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND | |
| 37 | #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 | |
| 28 | #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1 | |
| 29 | #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 | |
| 38 | 30 | #endif |
| 39 | 31 | #elif defined(_WIN32) |
| 40 | 32 | #ifdef __SEH__ |
| ... | ... | @@ -42,8 +34,19 @@ |
| 42 | 34 | #else |
| 43 | 35 | #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 |
| 44 | 36 | #endif |
| 37 | #elif defined(_LIBUNWIND_IS_BAREMETAL) | |
| 38 | #if !defined(_LIBUNWIND_ARM_EHABI) | |
| 39 | #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 | |
| 40 | #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1 | |
| 41 | #endif | |
| 42 | #elif defined(__BIONIC__) && defined(_LIBUNWIND_ARM_EHABI) | |
| 43 | // For ARM EHABI, Bionic didn't implement dl_iterate_phdr until API 21. After | |
| 44 | // API 21, dl_iterate_phdr exists, but dl_unwind_find_exidx is much faster. | |
| 45 | #define _LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX 1 | |
| 45 | 46 | #else |
| 46 | #if defined(__ARM_DWARF_EH__) || !defined(__arm__) | |
| 47 | // Assume an ELF system with a dl_iterate_phdr function. | |
| 48 | #define _LIBUNWIND_USE_DL_ITERATE_PHDR 1 | |
| 49 | #if !defined(_LIBUNWIND_ARM_EHABI) | |
| 47 | 50 | #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 |
| 48 | 51 | #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1 |
| 49 | 52 | #endif |
| ... | ... | @@ -91,6 +94,8 @@ |
| 91 | 94 | #error Unsupported target |
| 92 | 95 | #endif |
| 93 | 96 | |
| 97 | // Apple/armv7k defaults to DWARF/Compact unwinding, but its libunwind also | |
| 98 | // needs to include the SJLJ APIs. | |
| 94 | 99 | #if (defined(__APPLE__) && defined(__arm__)) || defined(__USING_SJLJ_EXCEPTIONS__) |
| 95 | 100 | #define _LIBUNWIND_BUILD_SJLJ_APIS |
| 96 | 101 | #endif |
| ... | ... | @@ -111,8 +116,27 @@ |
| 111 | 116 | #endif |
| 112 | 117 | #endif |
| 113 | 118 | |
| 114 | #if defined(__powerpc64__) && defined(_ARCH_PWR8) | |
| 115 | #define PPC64_HAS_VMX | |
| 119 | #ifndef _LIBUNWIND_REMEMBER_HEAP_ALLOC | |
| 120 | #if defined(_LIBUNWIND_REMEMBER_STACK_ALLOC) || defined(__APPLE__) || \ | |
| 121 | defined(__linux__) || defined(__ANDROID__) || defined(__MINGW32__) || \ | |
| 122 | defined(_LIBUNWIND_IS_BAREMETAL) | |
| 123 | #define _LIBUNWIND_REMEMBER_ALLOC(_size) alloca(_size) | |
| 124 | #define _LIBUNWIND_REMEMBER_FREE(_ptr) \ | |
| 125 | do { \ | |
| 126 | } while (0) | |
| 127 | #elif defined(_WIN32) | |
| 128 | #define _LIBUNWIND_REMEMBER_ALLOC(_size) _malloca(_size) | |
| 129 | #define _LIBUNWIND_REMEMBER_FREE(_ptr) _freea(_ptr) | |
| 130 | #define _LIBUNWIND_REMEMBER_CLEANUP_NEEDED | |
| 131 | #else | |
| 132 | #define _LIBUNWIND_REMEMBER_ALLOC(_size) malloc(_size) | |
| 133 | #define _LIBUNWIND_REMEMBER_FREE(_ptr) free(_ptr) | |
| 134 | #define _LIBUNWIND_REMEMBER_CLEANUP_NEEDED | |
| 135 | #endif | |
| 136 | #else /* _LIBUNWIND_REMEMBER_HEAP_ALLOC */ | |
| 137 | #define _LIBUNWIND_REMEMBER_ALLOC(_size) malloc(_size) | |
| 138 | #define _LIBUNWIND_REMEMBER_FREE(_ptr) free(_ptr) | |
| 139 | #define _LIBUNWIND_REMEMBER_CLEANUP_NEEDED | |
| 116 | 140 | #endif |
| 117 | 141 | |
| 118 | 142 | #if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL) |