| 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,6 +43,12 @@ |
| 43 | #define LIBUNWIND_AVAIL | 43 | #define LIBUNWIND_AVAIL |
| 44 | #endif | 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 | /* error codes */ | 52 | /* error codes */ |
| 47 | enum { | 53 | enum { |
| 48 | UNW_ESUCCESS = 0, /* no error */ | 54 | UNW_ESUCCESS = 0, /* no error */ |
| ... | @@ -68,7 +74,7 @@ typedef struct unw_context_t unw_context_t; | ... | @@ -68,7 +74,7 @@ typedef struct unw_context_t unw_context_t; |
| 68 | 74 | ||
| 69 | struct unw_cursor_t { | 75 | struct unw_cursor_t { |
| 70 | uint64_t data[_LIBUNWIND_CURSOR_SIZE]; | 76 | uint64_t data[_LIBUNWIND_CURSOR_SIZE]; |
| 71 | }; | 77 | } LIBUNWIND_CURSOR_ALIGNMENT_ATTR; |
| 72 | typedef struct unw_cursor_t unw_cursor_t; | 78 | typedef struct unw_cursor_t unw_cursor_t; |
| 73 | 79 | ||
| 74 | typedef struct unw_addr_space *unw_addr_space_t; | 80 | typedef struct unw_addr_space *unw_addr_space_t; |
lib/libunwind/src/AddressSpace.hpp+98-162| ... | @@ -17,6 +17,12 @@ | ... | @@ -17,6 +17,12 @@ |
| 17 | #include <stdlib.h> | 17 | #include <stdlib.h> |
| 18 | #include <string.h> | 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 | #ifndef _LIBUNWIND_USE_DLADDR | 26 | #ifndef _LIBUNWIND_USE_DLADDR |
| 21 | #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32) | 27 | #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32) |
| 22 | #define _LIBUNWIND_USE_DLADDR 1 | 28 | #define _LIBUNWIND_USE_DLADDR 1 |
| ... | @@ -39,19 +45,6 @@ struct EHABIIndexEntry { | ... | @@ -39,19 +45,6 @@ struct EHABIIndexEntry { |
| 39 | }; | 45 | }; |
| 40 | #endif | 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 | #ifdef __APPLE__ | 48 | #ifdef __APPLE__ |
| 56 | 49 | ||
| 57 | struct dyld_unwind_sections | 50 | struct dyld_unwind_sections |
| ... | @@ -62,43 +55,9 @@ namespace libunwind { | ... | @@ -62,43 +55,9 @@ namespace libunwind { |
| 62 | const void* compact_unwind_section; | 55 | const void* compact_unwind_section; |
| 63 | uintptr_t compact_unwind_section_length; | 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 | 59 | // In 10.7.0 or later, libSystem.dylib implements this function. |
| 87 | info->mh = (const struct mach_header *)mh; | 60 | extern "C" bool _dyld_find_unwind_sections(void *, dyld_unwind_sections *); |
| 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 | ||
| 102 | 61 | ||
| 103 | #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) | 62 | #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) |
| 104 | 63 | ||
| ... | @@ -139,22 +98,15 @@ extern char __eh_frame_hdr_end; | ... | @@ -139,22 +98,15 @@ extern char __eh_frame_hdr_end; |
| 139 | extern char __exidx_start; | 98 | extern char __exidx_start; |
| 140 | extern char __exidx_end; | 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 | #include <windows.h> | 103 | #include <windows.h> |
| 153 | #include <psapi.h> | 104 | #include <psapi.h> |
| 154 | #endif | 105 | |
| 155 | #if !defined(ElfW) | 106 | #elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) || \ |
| 156 | #define ElfW(type) Elf_##type | 107 | defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX) |
| 157 | #endif | 108 | |
| 109 | #include <link.h> | ||
| 158 | 110 | ||
| 159 | #endif | 111 | #endif |
| 160 | 112 | ||
| ... | @@ -162,11 +114,15 @@ namespace libunwind { | ... | @@ -162,11 +114,15 @@ namespace libunwind { |
| 162 | 114 | ||
| 163 | /// Used by findUnwindSections() to return info about needed sections. | 115 | /// Used by findUnwindSections() to return info about needed sections. |
| 164 | struct UnwindInfoSections { | 116 | struct UnwindInfoSections { |
| 165 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) || \ | 117 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || \ |
| 166 | defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) | 118 | defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) || \ |
| 167 | // No dso_base for SEH or ARM EHABI. | 119 | defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) |
| 120 | // No dso_base for SEH. | ||
| 168 | uintptr_t dso_base; | 121 | uintptr_t dso_base; |
| 169 | #endif | 122 | #endif |
| 123 | #if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) | ||
| 124 | uintptr_t text_segment_length; | ||
| 125 | #endif | ||
| 170 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | 126 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
| 171 | uintptr_t dwarf_section; | 127 | uintptr_t dwarf_section; |
| 172 | uintptr_t dwarf_section_length; | 128 | uintptr_t dwarf_section_length; |
| ... | @@ -290,11 +246,11 @@ inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { | ... | @@ -290,11 +246,11 @@ inline int64_t LocalAddressSpace::getSLEB128(pint_t &addr, pint_t end) { |
| 290 | if (p == pend) | 246 | if (p == pend) |
| 291 | _LIBUNWIND_ABORT("truncated sleb128 expression"); | 247 | _LIBUNWIND_ABORT("truncated sleb128 expression"); |
| 292 | byte = *p++; | 248 | byte = *p++; |
| 293 | result |= ((byte & 0x7f) << bit); | 249 | result |= (uint64_t)(byte & 0x7f) << bit; |
| 294 | bit += 7; | 250 | bit += 7; |
| 295 | } while (byte & 0x80); | 251 | } while (byte & 0x80); |
| 296 | // sign extend negative numbers | 252 | // sign extend negative numbers |
| 297 | if ((byte & 0x40) != 0) | 253 | if ((byte & 0x40) != 0 && bit < 64) |
| 298 | result |= (-1ULL) << bit; | 254 | result |= (-1ULL) << bit; |
| 299 | addr = (pint_t) p; | 255 | addr = (pint_t) p; |
| 300 | return result; | 256 | return result; |
| ... | @@ -392,23 +348,14 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, | ... | @@ -392,23 +348,14 @@ LocalAddressSpace::getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, |
| 392 | return result; | 348 | return result; |
| 393 | } | 349 | } |
| 394 | 350 | ||
| 395 | #ifdef __APPLE__ | 351 | #if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) |
| 396 | #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) | ||
| 397 | #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) | ||
| 398 | #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32) | ||
| 399 | #elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32) | ||
| 400 | #elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) | ||
| 401 | // Code inside findUnwindSections handles all these cases. | ||
| 402 | // | ||
| 403 | // Although the above ifdef chain is ugly, there doesn't seem to be a cleaner | ||
| 404 | // way to handle it. The generalized boolean expression is: | ||
| 405 | // | ||
| 406 | // A OR (B AND C) OR (D AND C) OR (B AND E) OR (F AND E) OR (D AND G) | ||
| 407 | // | ||
| 408 | // Running it through various boolean expression simplifiers gives expressions | ||
| 409 | // that don't help at all. | ||
| 410 | #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | ||
| 411 | 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 | #if !defined(Elf_Half) | 359 | #if !defined(Elf_Half) |
| 413 | typedef ElfW(Half) Elf_Half; | 360 | typedef ElfW(Half) Elf_Half; |
| 414 | #endif | 361 | #endif |
| ... | @@ -447,16 +394,12 @@ struct _LIBUNWIND_HIDDEN dl_iterate_cb_data { | ... | @@ -447,16 +394,12 @@ struct _LIBUNWIND_HIDDEN dl_iterate_cb_data { |
| 447 | uintptr_t targetAddr; | 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 | #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE) | 397 | #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE) |
| 456 | #include "FrameHeaderCache.hpp" | 398 | #include "FrameHeaderCache.hpp" |
| 457 | 399 | ||
| 458 | // There should be just one of these per process. | 400 | // Typically there is one cache per process, but when libunwind is built as a |
| 459 | static FrameHeaderCache ProcessFrameHeaderCache; | 401 | // hermetic static library, then each shared object may have its own cache. |
| 402 | static FrameHeaderCache TheFrameHeaderCache; | ||
| 460 | #endif | 403 | #endif |
| 461 | 404 | ||
| 462 | static bool checkAddrInSegment(const Elf_Phdr *phdr, size_t image_base, | 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,95 +409,93 @@ static bool checkAddrInSegment(const Elf_Phdr *phdr, size_t image_base, |
| 466 | uintptr_t end = begin + phdr->p_memsz; | 409 | uintptr_t end = begin + phdr->p_memsz; |
| 467 | if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) { | 410 | if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) { |
| 468 | cbdata->sects->dso_base = begin; | 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 | return true; | 413 | return true; |
| 471 | } | 414 | } |
| 472 | } | 415 | } |
| 473 | return false; | 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 | static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, | 451 | static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, |
| 477 | size_t pinfo_size, void *data) { | 452 | size_t pinfo_size, void *data) { |
| 478 | auto cbdata = static_cast<dl_iterate_cb_data *>(data); | 453 | auto cbdata = static_cast<dl_iterate_cb_data *>(data); |
| 479 | if (pinfo->dlpi_phnum == 0 || cbdata->targetAddr < pinfo->dlpi_addr) | 454 | if (pinfo->dlpi_phnum == 0 || cbdata->targetAddr < pinfo->dlpi_addr) |
| 480 | return 0; | 455 | return 0; |
| 481 | #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE) | 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 | return 1; | 458 | return 1; |
| 459 | #else | ||
| 460 | // Avoid warning about unused variable. | ||
| 461 | (void)pinfo_size; | ||
| 484 | #endif | 462 | #endif |
| 485 | 463 | ||
| 486 | Elf_Addr image_base = calculateImageBase(pinfo); | 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. | 466 | // Most shared objects seen in this callback function likely don't contain the |
| 491 | if (pinfo->dlpi_phnum > 2) | 467 | // target address, so optimize for that. Scan for a matching PT_LOAD segment |
| 492 | found_obj = checkAddrInSegment(&pinfo->dlpi_phdr[2], image_base, cbdata); | 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 | 479 | // PT_GNU_EH_FRAME and PT_ARM_EXIDX are usually near the end. Iterate |
| 495 | // that there is one or more phdrs. | 480 | // backward. |
| 481 | bool found_unwind = false; | ||
| 496 | for (Elf_Half i = pinfo->dlpi_phnum; i > 0; i--) { | 482 | for (Elf_Half i = pinfo->dlpi_phnum; i > 0; i--) { |
| 497 | const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i - 1]; | 483 | const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i - 1]; |
| 498 | if (!found_hdr && phdr->p_type == PT_GNU_EH_FRAME) { | 484 | if (checkForUnwindInfoSegment(phdr, image_base, cbdata)) { |
| 499 | EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo; | 485 | found_unwind = true; |
| 500 | uintptr_t eh_frame_hdr_start = image_base + phdr->p_vaddr; | 486 | break; |
| 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; | ||
| 516 | } | 487 | } |
| 517 | } | 488 | } |
| 518 | cbdata->sects->dwarf_section_length = 0; | 489 | if (!found_unwind) |
| 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) | ||
| 536 | return 0; | 490 | return 0; |
| 537 | 491 | ||
| 538 | Elf_Addr image_base = calculateImageBase(pinfo); | 492 | #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE) |
| 539 | 493 | TheFrameHeaderCache.add(cbdata->sects); | |
| 540 | for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { | 494 | #endif |
| 541 | const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; | 495 | return 1; |
| 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; | ||
| 555 | } | 496 | } |
| 556 | #endif // defined(LIBUNWIND_SUPPORT_DWARF_UNWIND) | 497 | |
| 557 | #endif // defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | 498 | #endif // defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) |
| 558 | 499 | ||
| 559 | 500 | ||
| 560 | inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, | 501 | inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, |
| ... | @@ -572,6 +513,7 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, | ... | @@ -572,6 +513,7 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, |
| 572 | return true; | 513 | return true; |
| 573 | } | 514 | } |
| 574 | #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) | 515 | #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) |
| 516 | info.dso_base = 0; | ||
| 575 | // Bare metal is statically linked, so no need to ask the dynamic loader | 517 | // Bare metal is statically linked, so no need to ask the dynamic loader |
| 576 | info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start); | 518 | info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start); |
| 577 | info.dwarf_section = (uintptr_t)(&__eh_frame_start); | 519 | info.dwarf_section = (uintptr_t)(&__eh_frame_start); |
| ... | @@ -638,16 +580,14 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, | ... | @@ -638,16 +580,14 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, |
| 638 | (void)targetAddr; | 580 | (void)targetAddr; |
| 639 | (void)info; | 581 | (void)info; |
| 640 | return true; | 582 | return true; |
| 641 | #elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) | 583 | #elif defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX) |
| 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. | ||
| 644 | int length = 0; | 584 | int length = 0; |
| 645 | info.arm_section = | 585 | info.arm_section = |
| 646 | (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length); | 586 | (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length); |
| 647 | info.arm_section_length = (uintptr_t)length * sizeof(EHABIIndexEntry); | 587 | info.arm_section_length = (uintptr_t)length * sizeof(EHABIIndexEntry); |
| 648 | if (info.arm_section && info.arm_section_length) | 588 | if (info.arm_section && info.arm_section_length) |
| 649 | return true; | 589 | return true; |
| 650 | #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | 590 | #elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) |
| 651 | dl_iterate_cb_data cb_data = {this, &info, targetAddr}; | 591 | dl_iterate_cb_data cb_data = {this, &info, targetAddr}; |
| 652 | int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data); | 592 | int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data); |
| 653 | return static_cast<bool>(found); | 593 | return static_cast<bool>(found); |
| ... | @@ -658,14 +598,10 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, | ... | @@ -658,14 +598,10 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, |
| 658 | 598 | ||
| 659 | 599 | ||
| 660 | inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { | 600 | inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { |
| 661 | #ifdef __APPLE__ | ||
| 662 | return checkKeyMgrRegisteredFDEs(targetAddr, *((void**)&fde)); | ||
| 663 | #else | ||
| 664 | // TO DO: if OS has way to dynamically register FDEs, check that. | 601 | // TO DO: if OS has way to dynamically register FDEs, check that. |
| 665 | (void)targetAddr; | 602 | (void)targetAddr; |
| 666 | (void)fde; | 603 | (void)fde; |
| 667 | return false; | 604 | return false; |
| 668 | #endif | ||
| 669 | } | 605 | } |
| 670 | 606 | ||
| 671 | inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, | 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,7 +93,8 @@ typename A::pint_t DwarfInstructions<A, R>::getSavedRegister( |
| 93 | 93 | ||
| 94 | case CFI_Parser<A>::kRegisterInRegister: | 94 | case CFI_Parser<A>::kRegisterInRegister: |
| 95 | return registers.getRegister((int)savedReg.value); | 95 | return registers.getRegister((int)savedReg.value); |
| 96 | 96 | case CFI_Parser<A>::kRegisterUndefined: | |
| 97 | return 0; | ||
| 97 | case CFI_Parser<A>::kRegisterUnused: | 98 | case CFI_Parser<A>::kRegisterUnused: |
| 98 | case CFI_Parser<A>::kRegisterOffsetFromCFA: | 99 | case CFI_Parser<A>::kRegisterOffsetFromCFA: |
| 99 | // FIX ME | 100 | // FIX ME |
| ... | @@ -117,6 +118,7 @@ double DwarfInstructions<A, R>::getSavedFloatRegister( | ... | @@ -117,6 +118,7 @@ double DwarfInstructions<A, R>::getSavedFloatRegister( |
| 117 | 118 | ||
| 118 | case CFI_Parser<A>::kRegisterIsExpression: | 119 | case CFI_Parser<A>::kRegisterIsExpression: |
| 119 | case CFI_Parser<A>::kRegisterUnused: | 120 | case CFI_Parser<A>::kRegisterUnused: |
| 121 | case CFI_Parser<A>::kRegisterUndefined: | ||
| 120 | case CFI_Parser<A>::kRegisterOffsetFromCFA: | 122 | case CFI_Parser<A>::kRegisterOffsetFromCFA: |
| 121 | case CFI_Parser<A>::kRegisterInRegister: | 123 | case CFI_Parser<A>::kRegisterInRegister: |
| 122 | // FIX ME | 124 | // FIX ME |
| ... | @@ -140,6 +142,7 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister( | ... | @@ -140,6 +142,7 @@ v128 DwarfInstructions<A, R>::getSavedVectorRegister( |
| 140 | 142 | ||
| 141 | case CFI_Parser<A>::kRegisterIsExpression: | 143 | case CFI_Parser<A>::kRegisterIsExpression: |
| 142 | case CFI_Parser<A>::kRegisterUnused: | 144 | case CFI_Parser<A>::kRegisterUnused: |
| 145 | case CFI_Parser<A>::kRegisterUndefined: | ||
| 143 | case CFI_Parser<A>::kRegisterOffsetFromCFA: | 146 | case CFI_Parser<A>::kRegisterOffsetFromCFA: |
| 144 | case CFI_Parser<A>::kRegisterInRegister: | 147 | case CFI_Parser<A>::kRegisterInRegister: |
| 145 | // FIX ME | 148 | // FIX ME |
| ... | @@ -190,6 +193,10 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, | ... | @@ -190,6 +193,10 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, |
| 190 | prolog.savedRegisters[i])); | 193 | prolog.savedRegisters[i])); |
| 191 | else | 194 | else |
| 192 | return UNW_EBADREG; | 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,6 +69,7 @@ public: |
| 69 | }; | 69 | }; |
| 70 | enum RegisterSavedWhere { | 70 | enum RegisterSavedWhere { |
| 71 | kRegisterUnused, | 71 | kRegisterUnused, |
| 72 | kRegisterUndefined, | ||
| 72 | kRegisterInCFA, | 73 | kRegisterInCFA, |
| 73 | kRegisterOffsetFromCFA, | 74 | kRegisterOffsetFromCFA, |
| 74 | kRegisterInRegister, | 75 | kRegisterInRegister, |
| ... | @@ -87,9 +88,6 @@ public: | ... | @@ -87,9 +88,6 @@ public: |
| 87 | int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset | 88 | int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset |
| 88 | int64_t cfaExpression; // CFA = expression | 89 | int64_t cfaExpression; // CFA = expression |
| 89 | uint32_t spExtraArgSize; | 90 | uint32_t spExtraArgSize; |
| 90 | uint32_t codeOffsetAtStackDecrement; | ||
| 91 | bool registersInOtherRegisters; | ||
| 92 | bool sameValueUsed; | ||
| 93 | RegisterLocation savedRegisters[kMaxRegisterNumber + 1]; | 91 | RegisterLocation savedRegisters[kMaxRegisterNumber + 1]; |
| 94 | enum class InitializeTime { kLazy, kNormal }; | 92 | enum class InitializeTime { kLazy, kNormal }; |
| 95 | 93 | ||
| ... | @@ -134,8 +132,26 @@ public: | ... | @@ -134,8 +132,26 @@ public: |
| 134 | PrologInfo info; | 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 | static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, | 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 | CIE_Info *cieInfo); | 155 | CIE_Info *cieInfo); |
| 140 | static const char *decodeFDE(A &addressSpace, pint_t fdeStart, | 156 | static const char *decodeFDE(A &addressSpace, pint_t fdeStart, |
| 141 | FDE_Info *fdeInfo, CIE_Info *cieInfo); | 157 | FDE_Info *fdeInfo, CIE_Info *cieInfo); |
| ... | @@ -144,13 +160,6 @@ public: | ... | @@ -144,13 +160,6 @@ public: |
| 144 | int arch, PrologInfo *results); | 160 | int arch, PrologInfo *results); |
| 145 | 161 | ||
| 146 | static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo); | 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 | /// Parse a FDE into a CIE_Info and an FDE_Info | 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,7 +175,7 @@ const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart, |
| 166 | p += 8; | 175 | p += 8; |
| 167 | } | 176 | } |
| 168 | if (cfiLength == 0) | 177 | if (cfiLength == 0) |
| 169 | return "FDE has zero length"; // end marker | 178 | return "FDE has zero length"; // zero terminator |
| 170 | uint32_t ciePointer = addressSpace.get32(p); | 179 | uint32_t ciePointer = addressSpace.get32(p); |
| 171 | if (ciePointer == 0) | 180 | if (ciePointer == 0) |
| 172 | return "FDE is really a CIE"; // this is a CIE not an FDE | 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,11 +220,13 @@ const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart, |
| 211 | /// Scan an eh_frame section to find an FDE for a pc | 220 | /// Scan an eh_frame section to find an FDE for a pc |
| 212 | template <typename A> | 221 | template <typename A> |
| 213 | bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, | 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 | FDE_Info *fdeInfo, CIE_Info *cieInfo) { | 224 | FDE_Info *fdeInfo, CIE_Info *cieInfo) { |
| 216 | //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc); | 225 | //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc); |
| 217 | pint_t p = (fdeHint != 0) ? fdeHint : ehSectionStart; | 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 | while (p < ehSectionEnd) { | 230 | while (p < ehSectionEnd) { |
| 220 | pint_t currentCFI = p; | 231 | pint_t currentCFI = p; |
| 221 | //fprintf(stderr, "findFDE() CFI at 0x%llX\n", (long long)p); | 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,7 +238,7 @@ bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, |
| 227 | p += 8; | 238 | p += 8; |
| 228 | } | 239 | } |
| 229 | if (cfiLength == 0) | 240 | if (cfiLength == 0) |
| 230 | return false; // end marker | 241 | return false; // zero terminator |
| 231 | uint32_t id = addressSpace.get32(p); | 242 | uint32_t id = addressSpace.get32(p); |
| 232 | if (id == 0) { | 243 | if (id == 0) { |
| 233 | // Skip over CIEs. | 244 | // Skip over CIEs. |
| ... | @@ -336,7 +347,8 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie, | ... | @@ -336,7 +347,8 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie, |
| 336 | // parse data alignment factor | 347 | // parse data alignment factor |
| 337 | cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd); | 348 | cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd); |
| 338 | // parse return address register | 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 | assert(raReg < 255 && "return address register too large"); | 352 | assert(raReg < 255 && "return address register too large"); |
| 341 | cieInfo->returnAddressRegister = (uint8_t)raReg; | 353 | cieInfo->returnAddressRegister = (uint8_t)raReg; |
| 342 | // parse augmentation data based on augmentation string | 354 | // parse augmentation data based on augmentation string |
| ... | @@ -390,418 +402,409 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, | ... | @@ -390,418 +402,409 @@ bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, |
| 390 | const FDE_Info &fdeInfo, | 402 | const FDE_Info &fdeInfo, |
| 391 | const CIE_Info &cieInfo, pint_t upToPC, | 403 | const CIE_Info &cieInfo, pint_t upToPC, |
| 392 | int arch, PrologInfo *results) { | 404 | int arch, PrologInfo *results) { |
| 393 | PrologInfoStackEntry *rememberStack = NULL; | 405 | // Alloca is used for the allocation of the rememberStack entries. It removes |
| 394 | 406 | // the dependency on new/malloc but the below for loop can not be refactored | |
| 395 | // parse CIE then FDE instructions | 407 | // into functions. Entry could be saved during the processing of a CIE and |
| 396 | bool returnValue = | 408 | // restored by an FDE. |
| 397 | parseInstructions(addressSpace, cieInfo.cieInstructions, | 409 | RememberStack rememberStack; |
| 398 | cieInfo.cieStart + cieInfo.cieLength, cieInfo, | 410 | |
| 399 | (pint_t)(-1), rememberStack, arch, results) && | 411 | struct ParseInfo { |
| 400 | parseInstructions(addressSpace, fdeInfo.fdeInstructions, | 412 | pint_t instructions; |
| 401 | fdeInfo.fdeStart + fdeInfo.fdeLength, cieInfo, | 413 | pint_t instructionsEnd; |
| 402 | upToPC - fdeInfo.pcStart, rememberStack, arch, results); | 414 | pint_t pcoffset; |
| 403 | 415 | }; | |
| 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 | } | ||
| 418 | 416 | ||
| 419 | /// "run" the DWARF instructions | 417 | ParseInfo parseInfoArray[] = { |
| 420 | template <typename A> | 418 | {cieInfo.cieInstructions, cieInfo.cieStart + cieInfo.cieLength, |
| 421 | bool CFI_Parser<A>::parseInstructions(A &addressSpace, pint_t instructions, | 419 | (pint_t)(-1)}, |
| 422 | pint_t instructionsEnd, | 420 | {fdeInfo.fdeInstructions, fdeInfo.fdeStart + fdeInfo.fdeLength, |
| 423 | const CIE_Info &cieInfo, pint_t pcoffset, | 421 | upToPC - fdeInfo.pcStart}}; |
| 424 | PrologInfoStackEntry *&rememberStack, | 422 | |
| 425 | int arch, PrologInfo *results) { | 423 | for (const auto &info : parseInfoArray) { |
| 426 | pint_t p = instructions; | 424 | pint_t p = info.instructions; |
| 427 | pint_t codeOffset = 0; | 425 | pint_t instructionsEnd = info.instructionsEnd; |
| 428 | // initialState initialized as registers in results are modified. Use | 426 | pint_t pcoffset = info.pcoffset; |
| 429 | // PrologInfo accessor functions to avoid reading uninitialized data. | 427 | pint_t codeOffset = 0; |
| 430 | PrologInfo initialState(PrologInfo::InitializeTime::kLazy); | 428 | |
| 431 | 429 | // initialState initialized as registers in results are modified. Use | |
| 432 | _LIBUNWIND_TRACE_DWARF("parseInstructions(instructions=0x%0" PRIx64 ")\n", | 430 | // PrologInfo accessor functions to avoid reading uninitialized data. |
| 433 | static_cast<uint64_t>(instructionsEnd)); | 431 | PrologInfo initialState(PrologInfo::InitializeTime::kLazy); |
| 434 | 432 | ||
| 435 | // see DWARF Spec, section 6.4.2 for details on unwind opcodes | 433 | _LIBUNWIND_TRACE_DWARF("parseFDEInstructions(instructions=0x%0" PRIx64 |
| 436 | while ((p < instructionsEnd) && (codeOffset < pcoffset)) { | 434 | ")\n", |
| 437 | uint64_t reg; | 435 | static_cast<uint64_t>(instructionsEnd)); |
| 438 | uint64_t reg2; | 436 | |
| 439 | int64_t offset; | 437 | // see DWARF Spec, section 6.4.2 for details on unwind opcodes |
| 440 | uint64_t length; | 438 | while ((p < instructionsEnd) && (codeOffset < pcoffset)) { |
| 441 | uint8_t opcode = addressSpace.get8(p); | 439 | uint64_t reg; |
| 442 | uint8_t operand; | 440 | uint64_t reg2; |
| 443 | #if !defined(_LIBUNWIND_NO_HEAP) | 441 | int64_t offset; |
| 444 | PrologInfoStackEntry *entry; | 442 | uint64_t length; |
| 445 | #endif | 443 | uint8_t opcode = addressSpace.get8(p); |
| 446 | ++p; | 444 | uint8_t operand; |
| 447 | switch (opcode) { | 445 | |
| 448 | case DW_CFA_nop: | 446 | ++p; |
| 449 | _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n"); | 447 | switch (opcode) { |
| 450 | break; | 448 | case DW_CFA_nop: |
| 451 | case DW_CFA_set_loc: | 449 | _LIBUNWIND_TRACE_DWARF("DW_CFA_nop\n"); |
| 452 | codeOffset = | 450 | break; |
| 453 | addressSpace.getEncodedP(p, instructionsEnd, cieInfo.pointerEncoding); | 451 | case DW_CFA_set_loc: |
| 454 | _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n"); | 452 | codeOffset = addressSpace.getEncodedP(p, instructionsEnd, |
| 455 | break; | 453 | cieInfo.pointerEncoding); |
| 456 | case DW_CFA_advance_loc1: | 454 | _LIBUNWIND_TRACE_DWARF("DW_CFA_set_loc\n"); |
| 457 | codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor); | 455 | break; |
| 458 | p += 1; | 456 | case DW_CFA_advance_loc1: |
| 459 | _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc1: new offset=%" PRIu64 "\n", | 457 | codeOffset += (addressSpace.get8(p) * cieInfo.codeAlignFactor); |
| 460 | static_cast<uint64_t>(codeOffset)); | 458 | p += 1; |
| 461 | break; | 459 | _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc1: new offset=%" PRIu64 "\n", |
| 462 | case DW_CFA_advance_loc2: | 460 | static_cast<uint64_t>(codeOffset)); |
| 463 | codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor); | 461 | break; |
| 464 | p += 2; | 462 | case DW_CFA_advance_loc2: |
| 465 | _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc2: new offset=%" PRIu64 "\n", | 463 | codeOffset += (addressSpace.get16(p) * cieInfo.codeAlignFactor); |
| 466 | static_cast<uint64_t>(codeOffset)); | 464 | p += 2; |
| 467 | break; | 465 | _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc2: new offset=%" PRIu64 "\n", |
| 468 | case DW_CFA_advance_loc4: | 466 | static_cast<uint64_t>(codeOffset)); |
| 469 | codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor); | 467 | break; |
| 470 | p += 4; | 468 | case DW_CFA_advance_loc4: |
| 471 | _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc4: new offset=%" PRIu64 "\n", | 469 | codeOffset += (addressSpace.get32(p) * cieInfo.codeAlignFactor); |
| 472 | static_cast<uint64_t>(codeOffset)); | 470 | p += 4; |
| 473 | break; | 471 | _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc4: new offset=%" PRIu64 "\n", |
| 474 | case DW_CFA_offset_extended: | 472 | static_cast<uint64_t>(codeOffset)); |
| 475 | reg = addressSpace.getULEB128(p, instructionsEnd); | 473 | break; |
| 476 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) | 474 | case DW_CFA_offset_extended: |
| 477 | * cieInfo.dataAlignFactor; | 475 | reg = addressSpace.getULEB128(p, instructionsEnd); |
| 478 | if (reg > kMaxRegisterNumber) { | 476 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) * |
| 479 | _LIBUNWIND_LOG0( | 477 | cieInfo.dataAlignFactor; |
| 480 | "malformed DW_CFA_offset_extended DWARF unwind, reg too big"); | 478 | if (reg > kMaxRegisterNumber) { |
| 481 | return false; | 479 | _LIBUNWIND_LOG0( |
| 482 | } | 480 | "malformed DW_CFA_offset_extended DWARF unwind, reg too big"); |
| 483 | results->setRegister(reg, kRegisterInCFA, offset, initialState); | 481 | return false; |
| 484 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", " | 482 | } |
| 485 | "offset=%" PRId64 ")\n", | 483 | results->setRegister(reg, kRegisterInCFA, offset, initialState); |
| 486 | reg, offset); | 484 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", " |
| 487 | break; | 485 | "offset=%" PRId64 ")\n", |
| 488 | case DW_CFA_restore_extended: | 486 | reg, offset); |
| 489 | reg = addressSpace.getULEB128(p, instructionsEnd); | 487 | break; |
| 490 | if (reg > kMaxRegisterNumber) { | 488 | case DW_CFA_restore_extended: |
| 491 | _LIBUNWIND_LOG0( | 489 | reg = addressSpace.getULEB128(p, instructionsEnd); |
| 492 | "malformed DW_CFA_restore_extended DWARF unwind, reg too big"); | 490 | if (reg > kMaxRegisterNumber) { |
| 493 | return false; | 491 | _LIBUNWIND_LOG0( |
| 494 | } | 492 | "malformed DW_CFA_restore_extended DWARF unwind, reg too big"); |
| 495 | results->restoreRegisterToInitialState(reg, initialState); | 493 | return false; |
| 496 | _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg); | 494 | } |
| 497 | break; | 495 | results->restoreRegisterToInitialState(reg, initialState); |
| 498 | case DW_CFA_undefined: | 496 | _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", |
| 499 | reg = addressSpace.getULEB128(p, instructionsEnd); | 497 | reg); |
| 500 | if (reg > kMaxRegisterNumber) { | 498 | break; |
| 501 | _LIBUNWIND_LOG0( | 499 | case DW_CFA_undefined: |
| 502 | "malformed DW_CFA_undefined DWARF unwind, reg too big"); | 500 | reg = addressSpace.getULEB128(p, instructionsEnd); |
| 503 | return false; | 501 | if (reg > kMaxRegisterNumber) { |
| 504 | } | 502 | _LIBUNWIND_LOG0( |
| 505 | results->setRegisterLocation(reg, kRegisterUnused, initialState); | 503 | "malformed DW_CFA_undefined DWARF unwind, reg too big"); |
| 506 | _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg); | 504 | return false; |
| 507 | break; | 505 | } |
| 508 | case DW_CFA_same_value: | 506 | results->setRegisterLocation(reg, kRegisterUndefined, initialState); |
| 509 | reg = addressSpace.getULEB128(p, instructionsEnd); | 507 | _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg); |
| 510 | if (reg > kMaxRegisterNumber) { | 508 | break; |
| 511 | _LIBUNWIND_LOG0( | 509 | case DW_CFA_same_value: |
| 512 | "malformed DW_CFA_same_value DWARF unwind, reg too big"); | 510 | reg = addressSpace.getULEB128(p, instructionsEnd); |
| 513 | return false; | 511 | if (reg > kMaxRegisterNumber) { |
| 514 | } | 512 | _LIBUNWIND_LOG0( |
| 515 | // <rdar://problem/8456377> DW_CFA_same_value unsupported | 513 | "malformed DW_CFA_same_value DWARF unwind, reg too big"); |
| 516 | // "same value" means register was stored in frame, but its current | 514 | return false; |
| 517 | // value has not changed, so no need to restore from frame. | 515 | } |
| 518 | // We model this as if the register was never saved. | 516 | // <rdar://problem/8456377> DW_CFA_same_value unsupported |
| 519 | results->setRegisterLocation(reg, kRegisterUnused, initialState); | 517 | // "same value" means register was stored in frame, but its current |
| 520 | // set flag to disable conversion to compact unwind | 518 | // value has not changed, so no need to restore from frame. |
| 521 | results->sameValueUsed = true; | 519 | // We model this as if the register was never saved. |
| 522 | _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg); | 520 | results->setRegisterLocation(reg, kRegisterUnused, initialState); |
| 523 | break; | 521 | _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg); |
| 524 | case DW_CFA_register: | 522 | break; |
| 525 | reg = addressSpace.getULEB128(p, instructionsEnd); | 523 | case DW_CFA_register: |
| 526 | reg2 = addressSpace.getULEB128(p, instructionsEnd); | 524 | reg = addressSpace.getULEB128(p, instructionsEnd); |
| 527 | if (reg > kMaxRegisterNumber) { | 525 | reg2 = addressSpace.getULEB128(p, instructionsEnd); |
| 528 | _LIBUNWIND_LOG0( | 526 | if (reg > kMaxRegisterNumber) { |
| 529 | "malformed DW_CFA_register DWARF unwind, reg too big"); | 527 | _LIBUNWIND_LOG0( |
| 530 | return false; | 528 | "malformed DW_CFA_register DWARF unwind, reg too big"); |
| 531 | } | 529 | return false; |
| 532 | if (reg2 > kMaxRegisterNumber) { | 530 | } |
| 533 | _LIBUNWIND_LOG0( | 531 | if (reg2 > kMaxRegisterNumber) { |
| 534 | "malformed DW_CFA_register DWARF unwind, reg2 too big"); | 532 | _LIBUNWIND_LOG0( |
| 535 | return false; | 533 | "malformed DW_CFA_register DWARF unwind, reg2 too big"); |
| 536 | } | 534 | return false; |
| 537 | results->setRegister(reg, kRegisterInRegister, (int64_t)reg2, | 535 | } |
| 538 | initialState); | 536 | results->setRegister(reg, kRegisterInRegister, (int64_t)reg2, |
| 539 | // set flag to disable conversion to compact unwind | 537 | initialState); |
| 540 | results->registersInOtherRegisters = true; | 538 | _LIBUNWIND_TRACE_DWARF( |
| 541 | _LIBUNWIND_TRACE_DWARF( | 539 | "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", reg, reg2); |
| 542 | "DW_CFA_register(reg=%" PRIu64 ", reg2=%" PRIu64 ")\n", reg, reg2); | 540 | break; |
| 543 | break; | 541 | case DW_CFA_remember_state: { |
| 544 | #if !defined(_LIBUNWIND_NO_HEAP) | 542 | // Avoid operator new because that would be an upward dependency. |
| 545 | case DW_CFA_remember_state: | 543 | // Avoid malloc because it needs heap allocation. |
| 546 | // avoid operator new, because that would be an upward dependency | 544 | PrologInfoStackEntry *entry = |
| 547 | entry = (PrologInfoStackEntry *)malloc(sizeof(PrologInfoStackEntry)); | 545 | (PrologInfoStackEntry *)_LIBUNWIND_REMEMBER_ALLOC( |
| 548 | if (entry != NULL) { | 546 | sizeof(PrologInfoStackEntry)); |
| 549 | entry->next = rememberStack; | 547 | if (entry != NULL) { |
| 550 | entry->info = *results; | 548 | entry->next = rememberStack.entry; |
| 551 | rememberStack = entry; | 549 | entry->info = *results; |
| 552 | } else { | 550 | rememberStack.entry = entry; |
| 553 | return false; | 551 | } else { |
| 554 | } | 552 | return false; |
| 555 | _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n"); | 553 | } |
| 556 | break; | 554 | _LIBUNWIND_TRACE_DWARF("DW_CFA_remember_state\n"); |
| 557 | case DW_CFA_restore_state: | 555 | break; |
| 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; | ||
| 718 | } | 556 | } |
| 719 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) | 557 | case DW_CFA_restore_state: |
| 720 | * cieInfo.dataAlignFactor; | 558 | if (rememberStack.entry != NULL) { |
| 721 | results->setRegister(reg, kRegisterInCFA, -offset, initialState); | 559 | PrologInfoStackEntry *top = rememberStack.entry; |
| 722 | _LIBUNWIND_TRACE_DWARF( | 560 | *results = top->info; |
| 723 | "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset); | 561 | rememberStack.entry = top->next; |
| 724 | break; | 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 | #if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC) | 726 | #if defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_SPARC) |
| 727 | // The same constant is used to represent different instructions on | 727 | // The same constant is used to represent different instructions on |
| 728 | // AArch64 (negate_ra_state) and SPARC (window_save). | 728 | // AArch64 (negate_ra_state) and SPARC (window_save). |
| 729 | static_assert(DW_CFA_AARCH64_negate_ra_state == DW_CFA_GNU_window_save, | 729 | static_assert(DW_CFA_AARCH64_negate_ra_state == DW_CFA_GNU_window_save, |
| 730 | "uses the same constant"); | 730 | "uses the same constant"); |
| 731 | case DW_CFA_AARCH64_negate_ra_state: | 731 | case DW_CFA_AARCH64_negate_ra_state: |
| 732 | switch (arch) { | 732 | switch (arch) { |
| 733 | #if defined(_LIBUNWIND_TARGET_AARCH64) | 733 | #if defined(_LIBUNWIND_TARGET_AARCH64) |
| 734 | case REGISTERS_ARM64: { | 734 | case REGISTERS_ARM64: { |
| 735 | int64_t value = | 735 | int64_t value = |
| 736 | results->savedRegisters[UNW_ARM64_RA_SIGN_STATE].value ^ 0x1; | 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 | _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n"); | 739 | _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n"); |
| 739 | } break; | 740 | } break; |
| 740 | #endif | 741 | #endif |
| 741 | 742 | ||
| 742 | #if defined(_LIBUNWIND_TARGET_SPARC) | 743 | #if defined(_LIBUNWIND_TARGET_SPARC) |
| 743 | // case DW_CFA_GNU_window_save: | 744 | // case DW_CFA_GNU_window_save: |
| 744 | case REGISTERS_SPARC: | 745 | case REGISTERS_SPARC: |
| 745 | _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n"); | 746 | _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n"); |
| 746 | for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) { | 747 | for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) { |
| 747 | results->setRegister(reg, kRegisterInRegister, | 748 | results->setRegister(reg, kRegisterInRegister, |
| 748 | ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0, | 749 | ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0, |
| 749 | initialState); | 750 | initialState); |
| 750 | } | 751 | } |
| 751 | 752 | ||
| 752 | for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) { | 753 | for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) { |
| 753 | results->setRegister(reg, kRegisterInCFA, | 754 | results->setRegister(reg, kRegisterInCFA, |
| 754 | ((int64_t)reg - UNW_SPARC_L0) * 4, initialState); | 755 | ((int64_t)reg - UNW_SPARC_L0) * 4, |
| 756 | initialState); | ||
| 757 | } | ||
| 758 | break; | ||
| 759 | #endif | ||
| 755 | } | 760 | } |
| 756 | break; | 761 | break; |
| 757 | #endif | ||
| 758 | } | ||
| 759 | break; | ||
| 760 | #else | 762 | #else |
| 761 | (void)arch; | 763 | (void)arch; |
| 762 | #endif | 764 | #endif |
| 763 | 765 | ||
| 764 | default: | 766 | default: |
| 765 | operand = opcode & 0x3F; | 767 | operand = opcode & 0x3F; |
| 766 | switch (opcode & 0xC0) { | 768 | switch (opcode & 0xC0) { |
| 767 | case DW_CFA_offset: | 769 | case DW_CFA_offset: |
| 768 | reg = operand; | 770 | reg = operand; |
| 769 | if (reg > kMaxRegisterNumber) { | 771 | if (reg > kMaxRegisterNumber) { |
| 770 | _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64 | 772 | _LIBUNWIND_LOG("malformed DW_CFA_offset DWARF unwind, reg (%" PRIu64 |
| 771 | ") out of range", | 773 | ") out of range", |
| 772 | reg); | 774 | reg); |
| 773 | return false; | 775 | return false; |
| 774 | } | 776 | } |
| 775 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) | 777 | offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) * |
| 776 | * cieInfo.dataAlignFactor; | 778 | cieInfo.dataAlignFactor; |
| 777 | results->setRegister(reg, kRegisterInCFA, offset, initialState); | 779 | results->setRegister(reg, kRegisterInCFA, offset, initialState); |
| 778 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n", | 780 | _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n", |
| 779 | operand, offset); | 781 | operand, offset); |
| 780 | break; | 782 | break; |
| 781 | case DW_CFA_advance_loc: | 783 | case DW_CFA_advance_loc: |
| 782 | codeOffset += operand * cieInfo.codeAlignFactor; | 784 | codeOffset += operand * cieInfo.codeAlignFactor; |
| 783 | _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc: new offset=%" PRIu64 "\n", | 785 | _LIBUNWIND_TRACE_DWARF("DW_CFA_advance_loc: new offset=%" PRIu64 "\n", |
| 784 | static_cast<uint64_t>(codeOffset)); | 786 | static_cast<uint64_t>(codeOffset)); |
| 785 | break; | 787 | break; |
| 786 | case DW_CFA_restore: | 788 | case DW_CFA_restore: |
| 787 | reg = operand; | 789 | reg = operand; |
| 788 | if (reg > kMaxRegisterNumber) { | 790 | if (reg > kMaxRegisterNumber) { |
| 789 | _LIBUNWIND_LOG("malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64 | 791 | _LIBUNWIND_LOG( |
| 790 | ") out of range", | 792 | "malformed DW_CFA_restore DWARF unwind, reg (%" PRIu64 |
| 791 | reg); | 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 | return false; | 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 | return true; | 808 | return true; |
| 806 | } | 809 | } |
| 807 | 810 |
lib/libunwind/src/FrameHeaderCache.hpp+1-1| ... | @@ -32,7 +32,7 @@ | ... | @@ -32,7 +32,7 @@ |
| 32 | class _LIBUNWIND_HIDDEN FrameHeaderCache { | 32 | class _LIBUNWIND_HIDDEN FrameHeaderCache { |
| 33 | struct CacheEntry { | 33 | struct CacheEntry { |
| 34 | uintptr_t LowPC() { return Info.dso_base; }; | 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 | UnwindInfoSections Info; | 36 | UnwindInfoSections Info; |
| 37 | CacheEntry *Next; | 37 | CacheEntry *Next; |
| 38 | }; | 38 | }; |
lib/libunwind/src/Registers.hpp+11-5| ... | @@ -39,6 +39,8 @@ enum { | ... | @@ -39,6 +39,8 @@ enum { |
| 39 | }; | 39 | }; |
| 40 | 40 | ||
| 41 | #if defined(_LIBUNWIND_TARGET_I386) | 41 | #if defined(_LIBUNWIND_TARGET_I386) |
| 42 | class _LIBUNWIND_HIDDEN Registers_x86; | ||
| 43 | extern "C" void __libunwind_Registers_x86_jumpto(Registers_x86 *); | ||
| 42 | /// Registers_x86 holds the register state of a thread in a 32-bit intel | 44 | /// Registers_x86 holds the register state of a thread in a 32-bit intel |
| 43 | /// process. | 45 | /// process. |
| 44 | class _LIBUNWIND_HIDDEN Registers_x86 { | 46 | class _LIBUNWIND_HIDDEN Registers_x86 { |
| ... | @@ -56,7 +58,7 @@ public: | ... | @@ -56,7 +58,7 @@ public: |
| 56 | v128 getVectorRegister(int num) const; | 58 | v128 getVectorRegister(int num) const; |
| 57 | void setVectorRegister(int num, v128 value); | 59 | void setVectorRegister(int num, v128 value); |
| 58 | static const char *getRegisterName(int num); | 60 | static const char *getRegisterName(int num); |
| 59 | void jumpto(); | 61 | void jumpto() { __libunwind_Registers_x86_jumpto(this); } |
| 60 | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; } | 62 | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86; } |
| 61 | static int getArch() { return REGISTERS_X86; } | 63 | static int getArch() { return REGISTERS_X86; } |
| 62 | 64 | ||
| ... | @@ -248,6 +250,8 @@ inline void Registers_x86::setVectorRegister(int, v128) { | ... | @@ -248,6 +250,8 @@ inline void Registers_x86::setVectorRegister(int, v128) { |
| 248 | #if defined(_LIBUNWIND_TARGET_X86_64) | 250 | #if defined(_LIBUNWIND_TARGET_X86_64) |
| 249 | /// Registers_x86_64 holds the register state of a thread in a 64-bit intel | 251 | /// Registers_x86_64 holds the register state of a thread in a 64-bit intel |
| 250 | /// process. | 252 | /// process. |
| 253 | class _LIBUNWIND_HIDDEN Registers_x86_64; | ||
| 254 | extern "C" void __libunwind_Registers_x86_64_jumpto(Registers_x86_64 *); | ||
| 251 | class _LIBUNWIND_HIDDEN Registers_x86_64 { | 255 | class _LIBUNWIND_HIDDEN Registers_x86_64 { |
| 252 | public: | 256 | public: |
| 253 | Registers_x86_64(); | 257 | Registers_x86_64(); |
| ... | @@ -263,7 +267,7 @@ public: | ... | @@ -263,7 +267,7 @@ public: |
| 263 | v128 getVectorRegister(int num) const; | 267 | v128 getVectorRegister(int num) const; |
| 264 | void setVectorRegister(int num, v128 value); | 268 | void setVectorRegister(int num, v128 value); |
| 265 | static const char *getRegisterName(int num); | 269 | static const char *getRegisterName(int num); |
| 266 | void jumpto(); | 270 | void jumpto() { __libunwind_Registers_x86_64_jumpto(this); } |
| 267 | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; } | 271 | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_X86_64; } |
| 268 | static int getArch() { return REGISTERS_X86_64; } | 272 | static int getArch() { return REGISTERS_X86_64; } |
| 269 | 273 | ||
| ... | @@ -1510,12 +1514,12 @@ inline void Registers_ppc64::setFloatRegister(int regNum, double value) { | ... | @@ -1510,12 +1514,12 @@ inline void Registers_ppc64::setFloatRegister(int regNum, double value) { |
| 1510 | } | 1514 | } |
| 1511 | 1515 | ||
| 1512 | inline bool Registers_ppc64::validVectorRegister(int regNum) const { | 1516 | inline bool Registers_ppc64::validVectorRegister(int regNum) const { |
| 1513 | #ifdef PPC64_HAS_VMX | 1517 | #if defined(__VSX__) |
| 1514 | if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31) | 1518 | if (regNum >= UNW_PPC64_VS0 && regNum <= UNW_PPC64_VS31) |
| 1515 | return true; | 1519 | return true; |
| 1516 | if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63) | 1520 | if (regNum >= UNW_PPC64_VS32 && regNum <= UNW_PPC64_VS63) |
| 1517 | return true; | 1521 | return true; |
| 1518 | #else | 1522 | #elif defined(__ALTIVEC__) |
| 1519 | if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31) | 1523 | if (regNum >= UNW_PPC64_V0 && regNum <= UNW_PPC64_V31) |
| 1520 | return true; | 1524 | return true; |
| 1521 | #endif | 1525 | #endif |
| ... | @@ -1771,6 +1775,8 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) { | ... | @@ -1771,6 +1775,8 @@ inline const char *Registers_ppc64::getRegisterName(int regNum) { |
| 1771 | #if defined(_LIBUNWIND_TARGET_AARCH64) | 1775 | #if defined(_LIBUNWIND_TARGET_AARCH64) |
| 1772 | /// Registers_arm64 holds the register state of a thread in a 64-bit arm | 1776 | /// Registers_arm64 holds the register state of a thread in a 64-bit arm |
| 1773 | /// process. | 1777 | /// process. |
| 1778 | class _LIBUNWIND_HIDDEN Registers_arm64; | ||
| 1779 | extern "C" void __libunwind_Registers_arm64_jumpto(Registers_arm64 *); | ||
| 1774 | class _LIBUNWIND_HIDDEN Registers_arm64 { | 1780 | class _LIBUNWIND_HIDDEN Registers_arm64 { |
| 1775 | public: | 1781 | public: |
| 1776 | Registers_arm64(); | 1782 | Registers_arm64(); |
| ... | @@ -1786,7 +1792,7 @@ public: | ... | @@ -1786,7 +1792,7 @@ public: |
| 1786 | v128 getVectorRegister(int num) const; | 1792 | v128 getVectorRegister(int num) const; |
| 1787 | void setVectorRegister(int num, v128 value); | 1793 | void setVectorRegister(int num, v128 value); |
| 1788 | static const char *getRegisterName(int num); | 1794 | static const char *getRegisterName(int num); |
| 1789 | void jumpto(); | 1795 | void jumpto() { __libunwind_Registers_arm64_jumpto(this); } |
| 1790 | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; } | 1796 | static int lastDwarfRegNum() { return _LIBUNWIND_HIGHEST_DWARF_REGISTER_ARM64; } |
| 1791 | static int getArch() { return REGISTERS_ARM64; } | 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,18 +46,6 @@ using namespace libunwind; |
| 46 | /// handling. | 46 | /// handling. |
| 47 | #define STATUS_GCC_UNWIND MAKE_GCC_EXCEPTION(1) // 0x21474343 | 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 | static int __unw_init_seh(unw_cursor_t *cursor, CONTEXT *ctx); | 49 | static int __unw_init_seh(unw_cursor_t *cursor, CONTEXT *ctx); |
| 62 | static DISPATCHER_CONTEXT *__unw_seh_get_disp_ctx(unw_cursor_t *cursor); | 50 | static DISPATCHER_CONTEXT *__unw_seh_get_disp_ctx(unw_cursor_t *cursor); |
| 63 | static void __unw_seh_set_disp_ctx(unw_cursor_t *cursor, | 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,10 +96,10 @@ _GCC_specific_handler(PEXCEPTION_RECORD ms_exc, PVOID frame, PCONTEXT ms_ctx, |
| 108 | } | 96 | } |
| 109 | } else { | 97 | } else { |
| 110 | // Foreign exception. | 98 | // Foreign exception. |
| 111 | exc = (_Unwind_Exception *)malloc(sizeof(_Unwind_Exception)); | 99 | // We can't interact with them (we don't know the original target frame |
| 112 | exc->exception_class = kSEHExceptionClass; | 100 | // that we should pass on to RtlUnwindEx in _Unwind_Resume), so just |
| 113 | exc->exception_cleanup = seh_exc_cleanup; | 101 | // pass without calling our destructors here. |
| 114 | memset(exc->private_, 0, sizeof(exc->private_)); | 102 | return ExceptionContinueSearch; |
| 115 | } | 103 | } |
| 116 | if (!ctx) { | 104 | if (!ctx) { |
| 117 | __unw_init_seh(&cursor, disp->ContextRecord); | 105 | __unw_init_seh(&cursor, disp->ContextRecord); |
lib/libunwind/src/UnwindCursor.hpp+51-64| ... | @@ -81,6 +81,7 @@ template <typename A> | ... | @@ -81,6 +81,7 @@ template <typename A> |
| 81 | class _LIBUNWIND_HIDDEN DwarfFDECache { | 81 | class _LIBUNWIND_HIDDEN DwarfFDECache { |
| 82 | typedef typename A::pint_t pint_t; | 82 | typedef typename A::pint_t pint_t; |
| 83 | public: | 83 | public: |
| 84 | static constexpr pint_t kSearchAll = static_cast<pint_t>(-1); | ||
| 84 | static pint_t findFDE(pint_t mh, pint_t pc); | 85 | static pint_t findFDE(pint_t mh, pint_t pc); |
| 85 | static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde); | 86 | static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde); |
| 86 | static void removeAllIn(pint_t mh); | 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,7 +139,7 @@ typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) { |
| 138 | pint_t result = 0; | 139 | pint_t result = 0; |
| 139 | _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared()); | 140 | _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared()); |
| 140 | for (entry *p = _buffer; p < _bufferUsed; ++p) { | 141 | for (entry *p = _buffer; p < _bufferUsed; ++p) { |
| 141 | if ((mh == p->mh) || (mh == 0)) { | 142 | if ((mh == p->mh) || (mh == kSearchAll)) { |
| 142 | if ((p->ip_start <= pc) && (pc < p->ip_end)) { | 143 | if ((p->ip_start <= pc) && (pc < p->ip_end)) { |
| 143 | result = p->fde; | 144 | result = p->fde; |
| 144 | break; | 145 | break; |
| ... | @@ -530,6 +531,8 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as) | ... | @@ -530,6 +531,8 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as) |
| 530 | : _addressSpace(as), _unwindInfoMissing(false) { | 531 | : _addressSpace(as), _unwindInfoMissing(false) { |
| 531 | static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit), | 532 | static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit), |
| 532 | "UnwindCursor<> does not fit in unw_cursor_t"); | 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 | memset(&_info, 0, sizeof(_info)); | 536 | memset(&_info, 0, sizeof(_info)); |
| 534 | memset(&_histTable, 0, sizeof(_histTable)); | 537 | memset(&_histTable, 0, sizeof(_histTable)); |
| 535 | _dispContext.ContextRecord = &_msContext; | 538 | _dispContext.ContextRecord = &_msContext; |
| ... | @@ -923,6 +926,9 @@ private: | ... | @@ -923,6 +926,9 @@ private: |
| 923 | #endif | 926 | #endif |
| 924 | 927 | ||
| 925 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | 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 | bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections &sects, | 932 | bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections &sects, |
| 927 | uint32_t fdeSectionOffsetHint=0); | 933 | uint32_t fdeSectionOffsetHint=0); |
| 928 | int stepWithDwarfFDE() { | 934 | int stepWithDwarfFDE() { |
| ... | @@ -1182,6 +1188,8 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as) | ... | @@ -1182,6 +1188,8 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as) |
| 1182 | _isSignalFrame(false) { | 1188 | _isSignalFrame(false) { |
| 1183 | static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit), | 1189 | static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit), |
| 1184 | "UnwindCursor<> does not fit in unw_cursor_t"); | 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 | memset(&_info, 0, sizeof(_info)); | 1193 | memset(&_info, 0, sizeof(_info)); |
| 1186 | } | 1194 | } |
| 1187 | 1195 | ||
| ... | @@ -1472,6 +1480,32 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection( | ... | @@ -1472,6 +1480,32 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection( |
| 1472 | #endif | 1480 | #endif |
| 1473 | 1481 | ||
| 1474 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | 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 | template <typename A, typename R> | 1509 | template <typename A, typename R> |
| 1476 | bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, | 1510 | bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, |
| 1477 | const UnwindInfoSections &sects, | 1511 | const UnwindInfoSections &sects, |
| ... | @@ -1483,7 +1517,7 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, | ... | @@ -1483,7 +1517,7 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, |
| 1483 | // If compact encoding table gave offset into dwarf section, go directly there | 1517 | // If compact encoding table gave offset into dwarf section, go directly there |
| 1484 | if (fdeSectionOffsetHint != 0) { | 1518 | if (fdeSectionOffsetHint != 0) { |
| 1485 | foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section, | 1519 | foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section, |
| 1486 | (uint32_t)sects.dwarf_section_length, | 1520 | sects.dwarf_section_length, |
| 1487 | sects.dwarf_section + fdeSectionOffsetHint, | 1521 | sects.dwarf_section + fdeSectionOffsetHint, |
| 1488 | &fdeInfo, &cieInfo); | 1522 | &fdeInfo, &cieInfo); |
| 1489 | } | 1523 | } |
| ... | @@ -1500,7 +1534,7 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, | ... | @@ -1500,7 +1534,7 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, |
| 1500 | if (cachedFDE != 0) { | 1534 | if (cachedFDE != 0) { |
| 1501 | foundFDE = | 1535 | foundFDE = |
| 1502 | CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section, | 1536 | CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section, |
| 1503 | (uint32_t)sects.dwarf_section_length, | 1537 | sects.dwarf_section_length, |
| 1504 | cachedFDE, &fdeInfo, &cieInfo); | 1538 | cachedFDE, &fdeInfo, &cieInfo); |
| 1505 | foundInCache = foundFDE; | 1539 | foundInCache = foundFDE; |
| 1506 | } | 1540 | } |
| ... | @@ -1508,25 +1542,11 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, | ... | @@ -1508,25 +1542,11 @@ bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, |
| 1508 | if (!foundFDE) { | 1542 | if (!foundFDE) { |
| 1509 | // Still not found, do full scan of __eh_frame section. | 1543 | // Still not found, do full scan of __eh_frame section. |
| 1510 | foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section, | 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 | &fdeInfo, &cieInfo); | 1546 | &fdeInfo, &cieInfo); |
| 1513 | } | 1547 | } |
| 1514 | if (foundFDE) { | 1548 | if (foundFDE) { |
| 1515 | typename CFI_Parser<A>::PrologInfo prolog; | 1549 | if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, sects.dso_base)) { |
| 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 | |||
| 1530 | // Add to cache (to make next lookup faster) if we had no hint | 1550 | // Add to cache (to make next lookup faster) if we had no hint |
| 1531 | // and there was no index. | 1551 | // and there was no index. |
| 1532 | if (!foundInCache && (fdeSectionOffsetHint == 0)) { | 1552 | if (!foundInCache && (fdeSectionOffsetHint == 0)) { |
| ... | @@ -1759,12 +1779,12 @@ bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc, | ... | @@ -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 | uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >> | 1783 | uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >> |
| 1764 | (__builtin_ctz(UNWIND_PERSONALITY_MASK)); | 1784 | (__builtin_ctz(UNWIND_PERSONALITY_MASK)); |
| 1765 | if (personalityIndex != 0) { | 1785 | if (personalityIndex != 0) { |
| 1766 | --personalityIndex; // change 1-based to zero-based index | 1786 | --personalityIndex; // change 1-based to zero-based index |
| 1767 | if (personalityIndex > sectionHeader.personalityArrayCount()) { | 1787 | if (personalityIndex >= sectionHeader.personalityArrayCount()) { |
| 1768 | _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, " | 1788 | _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, " |
| 1769 | "but personality table has only %d entries", | 1789 | "but personality table has only %d entries", |
| 1770 | encoding, personalityIndex, | 1790 | encoding, personalityIndex, |
| ... | @@ -1926,60 +1946,27 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { | ... | @@ -1926,60 +1946,27 @@ void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { |
| 1926 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | 1946 | #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
| 1927 | // There is no static unwind info for this pc. Look to see if an FDE was | 1947 | // There is no static unwind info for this pc. Look to see if an FDE was |
| 1928 | // dynamically registered for it. | 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 | if (cachedFDE != 0) { | 1951 | if (cachedFDE != 0) { |
| 1931 | CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo; | 1952 | typename CFI_Parser<A>::FDE_Info fdeInfo; |
| 1932 | CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo; | 1953 | typename CFI_Parser<A>::CIE_Info cieInfo; |
| 1933 | const char *msg = CFI_Parser<A>::decodeFDE(_addressSpace, | 1954 | if (!CFI_Parser<A>::decodeFDE(_addressSpace, cachedFDE, &fdeInfo, &cieInfo)) |
| 1934 | cachedFDE, &fdeInfo, &cieInfo); | 1955 | if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, 0)) |
| 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 | return; | 1956 | return; |
| 1953 | } | ||
| 1954 | } | ||
| 1955 | } | 1957 | } |
| 1956 | 1958 | ||
| 1957 | // Lastly, ask AddressSpace object about platform specific ways to locate | 1959 | // Lastly, ask AddressSpace object about platform specific ways to locate |
| 1958 | // other FDEs. | 1960 | // other FDEs. |
| 1959 | pint_t fde; | 1961 | pint_t fde; |
| 1960 | if (_addressSpace.findOtherFDE(pc, fde)) { | 1962 | if (_addressSpace.findOtherFDE(pc, fde)) { |
| 1961 | CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo; | 1963 | typename CFI_Parser<A>::FDE_Info fdeInfo; |
| 1962 | CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo; | 1964 | typename CFI_Parser<A>::CIE_Info cieInfo; |
| 1963 | if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) { | 1965 | if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) { |
| 1964 | // Double check this FDE is for a function that includes the pc. | 1966 | // Double check this FDE is for a function that includes the pc. |
| 1965 | if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) { | 1967 | if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) |
| 1966 | typename CFI_Parser<A>::PrologInfo prolog; | 1968 | if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, 0)) |
| 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; | ||
| 1980 | return; | 1969 | return; |
| 1981 | } | ||
| 1982 | } | ||
| 1983 | } | 1970 | } |
| 1984 | } | 1971 | } |
| 1985 | #endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | 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,8 +39,7 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 39 | __unw_init_local(cursor, uc); | 39 | __unw_init_local(cursor, uc); |
| 40 | 40 | ||
| 41 | // Walk each frame looking for a place to stop. | 41 | // Walk each frame looking for a place to stop. |
| 42 | bool handlerNotFound = true; | 42 | while (true) { |
| 43 | while (handlerNotFound) { | ||
| 44 | // Ask libunwind to get next frame (skip over first which is | 43 | // Ask libunwind to get next frame (skip over first which is |
| 45 | // _Unwind_RaiseException). | 44 | // _Unwind_RaiseException). |
| 46 | int stepResult = __unw_step(cursor); | 45 | int stepResult = __unw_step(cursor); |
| ... | @@ -102,7 +101,6 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except | ... | @@ -102,7 +101,6 @@ unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *except |
| 102 | case _URC_HANDLER_FOUND: | 101 | case _URC_HANDLER_FOUND: |
| 103 | // found a catch clause or locals that need destructing in this frame | 102 | // found a catch clause or locals that need destructing in this frame |
| 104 | // stop search and remember stack pointer at the frame | 103 | // stop search and remember stack pointer at the frame |
| 105 | handlerNotFound = false; | ||
| 106 | __unw_get_reg(cursor, UNW_REG_SP, &sp); | 104 | __unw_get_reg(cursor, UNW_REG_SP, &sp); |
| 107 | exception_object->private_2 = (uintptr_t)sp; | 105 | exception_object->private_2 = (uintptr_t)sp; |
| 108 | _LIBUNWIND_TRACE_UNWINDING( | 106 | _LIBUNWIND_TRACE_UNWINDING( |
lib/libunwind/src/UnwindRegistersRestore.S+13-12| ... | @@ -13,14 +13,10 @@ | ... | @@ -13,14 +13,10 @@ |
| 13 | #if !defined(__USING_SJLJ_EXCEPTIONS__) | 13 | #if !defined(__USING_SJLJ_EXCEPTIONS__) |
| 14 | 14 | ||
| 15 | #if defined(__i386__) | 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 | # On entry: | 20 | # On entry: |
| 25 | # + + | 21 | # + + |
| 26 | # +-----------------------+ | 22 | # +-----------------------+ |
| ... | @@ -30,7 +26,6 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv) | ... | @@ -30,7 +26,6 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv) |
| 30 | # +-----------------------+ <-- SP | 26 | # +-----------------------+ <-- SP |
| 31 | # + + | 27 | # + + |
| 32 | movl 4(%esp), %eax | 28 | movl 4(%esp), %eax |
| 33 | #endif | ||
| 34 | # set up eax and ret on new stack location | 29 | # set up eax and ret on new stack location |
| 35 | movl 28(%eax), %edx # edx holds new stack pointer | 30 | movl 28(%eax), %edx # edx holds new stack pointer |
| 36 | subl $8,%edx | 31 | subl $8,%edx |
| ... | @@ -60,9 +55,9 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv) | ... | @@ -60,9 +55,9 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_x866jumptoEv) |
| 60 | 55 | ||
| 61 | #elif defined(__x86_64__) | 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 | #if defined(_WIN64) | 62 | #if defined(_WIN64) |
| 68 | # On entry, thread_state pointer is in rcx; move it into rdi | 63 | # On entry, thread_state pointer is in rcx; move it into rdi |
| ... | @@ -175,7 +170,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv) | ... | @@ -175,7 +170,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_ppc646jumptoEv) |
| 175 | PPC64_LR(30) | 170 | PPC64_LR(30) |
| 176 | PPC64_LR(31) | 171 | PPC64_LR(31) |
| 177 | 172 | ||
| 178 | #ifdef PPC64_HAS_VMX | 173 | #if defined(__VSX__) |
| 179 | 174 | ||
| 180 | // restore VS registers | 175 | // restore VS registers |
| 181 | // (note that this also restores floating point registers and V registers, | 176 | // (note that this also restores floating point registers and V registers, |
| ... | @@ -317,6 +312,7 @@ PPC64_CLVS_BOTTOM(n) | ... | @@ -317,6 +312,7 @@ PPC64_CLVS_BOTTOM(n) |
| 317 | PPC64_LF(30) | 312 | PPC64_LF(30) |
| 318 | PPC64_LF(31) | 313 | PPC64_LF(31) |
| 319 | 314 | ||
| 315 | #if defined(__ALTIVEC__) | ||
| 320 | // restore vector registers if any are in use | 316 | // restore vector registers if any are in use |
| 321 | ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave | 317 | ld %r5, PPC64_OFFS_VRSAVE(%r3) // test VRsave |
| 322 | cmpwi %r5, 0 | 318 | cmpwi %r5, 0 |
| ... | @@ -378,6 +374,7 @@ PPC64_CLV_UNALIGNED_BOTTOM(n) | ... | @@ -378,6 +374,7 @@ PPC64_CLV_UNALIGNED_BOTTOM(n) |
| 378 | PPC64_CLV_UNALIGNEDh(31) | 374 | PPC64_CLV_UNALIGNEDh(31) |
| 379 | 375 | ||
| 380 | #endif | 376 | #endif |
| 377 | #endif | ||
| 381 | 378 | ||
| 382 | Lnovec: | 379 | Lnovec: |
| 383 | ld %r0, PPC64_OFFS_CR(%r3) | 380 | ld %r0, PPC64_OFFS_CR(%r3) |
| ... | @@ -436,6 +433,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) | ... | @@ -436,6 +433,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) |
| 436 | lwz %r30,128(%r3) | 433 | lwz %r30,128(%r3) |
| 437 | lwz %r31,132(%r3) | 434 | lwz %r31,132(%r3) |
| 438 | 435 | ||
| 436 | #ifndef __NO_FPRS__ | ||
| 439 | // restore float registers | 437 | // restore float registers |
| 440 | lfd %f0, 160(%r3) | 438 | lfd %f0, 160(%r3) |
| 441 | lfd %f1, 168(%r3) | 439 | lfd %f1, 168(%r3) |
| ... | @@ -469,7 +467,9 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) | ... | @@ -469,7 +467,9 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) |
| 469 | lfd %f29,392(%r3) | 467 | lfd %f29,392(%r3) |
| 470 | lfd %f30,400(%r3) | 468 | lfd %f30,400(%r3) |
| 471 | lfd %f31,408(%r3) | 469 | lfd %f31,408(%r3) |
| 470 | #endif | ||
| 472 | 471 | ||
| 472 | #if defined(__ALTIVEC__) | ||
| 473 | // restore vector registers if any are in use | 473 | // restore vector registers if any are in use |
| 474 | lwz %r5, 156(%r3) // test VRsave | 474 | lwz %r5, 156(%r3) // test VRsave |
| 475 | cmpwi %r5, 0 | 475 | cmpwi %r5, 0 |
| ... | @@ -542,6 +542,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) | ... | @@ -542,6 +542,7 @@ DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind13Registers_ppc6jumptoEv) |
| 542 | LOAD_VECTOR_UNALIGNEDh(29) | 542 | LOAD_VECTOR_UNALIGNEDh(29) |
| 543 | LOAD_VECTOR_UNALIGNEDh(30) | 543 | LOAD_VECTOR_UNALIGNEDh(30) |
| 544 | LOAD_VECTOR_UNALIGNEDh(31) | 544 | LOAD_VECTOR_UNALIGNEDh(31) |
| 545 | #endif | ||
| 545 | 546 | ||
| 546 | Lnovec: | 547 | Lnovec: |
| 547 | lwz %r0, 136(%r3) // __cr | 548 | lwz %r0, 136(%r3) // __cr |
| ... | @@ -560,13 +561,13 @@ Lnovec: | ... | @@ -560,13 +561,13 @@ Lnovec: |
| 560 | #elif defined(__aarch64__) | 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 | // On entry: | 566 | // On entry: |
| 566 | // thread_state pointer is in x0 | 567 | // thread_state pointer is in x0 |
| 567 | // | 568 | // |
| 568 | .p2align 2 | 569 | .p2align 2 |
| 569 | DEFINE_LIBUNWIND_FUNCTION(_ZN9libunwind15Registers_arm646jumptoEv) | 570 | DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto) |
| 570 | // skip restore of x0,x1 for now | 571 | // skip restore of x0,x1 for now |
| 571 | ldp x2, x3, [x0, #0x010] | 572 | ldp x2, x3, [x0, #0x010] |
| 572 | ldp x4, x5, [x0, #0x020] | 573 | ldp x4, x5, [x0, #0x020] |
lib/libunwind/src/UnwindRegistersSave.S+7-2| ... | @@ -384,7 +384,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) | ... | @@ -384,7 +384,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 384 | mfvrsave %r0 | 384 | mfvrsave %r0 |
| 385 | std %r0, PPC64_OFFS_VRSAVE(%r3) | 385 | std %r0, PPC64_OFFS_VRSAVE(%r3) |
| 386 | 386 | ||
| 387 | #ifdef PPC64_HAS_VMX | 387 | #if defined(__VSX__) |
| 388 | // save VS registers | 388 | // save VS registers |
| 389 | // (note that this also saves floating point registers and V registers, | 389 | // (note that this also saves floating point registers and V registers, |
| 390 | // because part of VS is mapped to these registers) | 390 | // because part of VS is mapped to these registers) |
| ... | @@ -501,6 +501,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) | ... | @@ -501,6 +501,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 501 | PPC64_STF(30) | 501 | PPC64_STF(30) |
| 502 | PPC64_STF(31) | 502 | PPC64_STF(31) |
| 503 | 503 | ||
| 504 | #if defined(__ALTIVEC__) | ||
| 504 | // save vector registers | 505 | // save vector registers |
| 505 | 506 | ||
| 506 | // Use 16-bytes below the stack pointer as an | 507 | // Use 16-bytes below the stack pointer as an |
| ... | @@ -548,6 +549,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) | ... | @@ -548,6 +549,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 548 | PPC64_STV_UNALIGNED(30) | 549 | PPC64_STV_UNALIGNED(30) |
| 549 | PPC64_STV_UNALIGNED(31) | 550 | PPC64_STV_UNALIGNED(31) |
| 550 | 551 | ||
| 552 | #endif | ||
| 551 | #endif | 553 | #endif |
| 552 | 554 | ||
| 553 | li %r3, 0 // return UNW_ESUCCESS | 555 | li %r3, 0 // return UNW_ESUCCESS |
| ... | @@ -608,6 +610,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) | ... | @@ -608,6 +610,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 608 | mfctr %r0 | 610 | mfctr %r0 |
| 609 | stw %r0, 148(%r3) | 611 | stw %r0, 148(%r3) |
| 610 | 612 | ||
| 613 | #if !defined(__NO_FPRS__) | ||
| 611 | // save float registers | 614 | // save float registers |
| 612 | stfd %f0, 160(%r3) | 615 | stfd %f0, 160(%r3) |
| 613 | stfd %f1, 168(%r3) | 616 | stfd %f1, 168(%r3) |
| ... | @@ -641,8 +644,9 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) | ... | @@ -641,8 +644,9 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 641 | stfd %f29,392(%r3) | 644 | stfd %f29,392(%r3) |
| 642 | stfd %f30,400(%r3) | 645 | stfd %f30,400(%r3) |
| 643 | stfd %f31,408(%r3) | 646 | stfd %f31,408(%r3) |
| 647 | #endif | ||
| 644 | 648 | ||
| 645 | 649 | #if defined(__ALTIVEC__) | |
| 646 | // save vector registers | 650 | // save vector registers |
| 647 | 651 | ||
| 648 | subi %r4, %r1, 16 | 652 | subi %r4, %r1, 16 |
| ... | @@ -692,6 +696,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) | ... | @@ -692,6 +696,7 @@ DEFINE_LIBUNWIND_FUNCTION(__unw_getcontext) |
| 692 | SAVE_VECTOR_UNALIGNED(%v29, 424+0x1D0) | 696 | SAVE_VECTOR_UNALIGNED(%v29, 424+0x1D0) |
| 693 | SAVE_VECTOR_UNALIGNED(%v30, 424+0x1E0) | 697 | SAVE_VECTOR_UNALIGNED(%v30, 424+0x1E0) |
| 694 | SAVE_VECTOR_UNALIGNED(%v31, 424+0x1F0) | 698 | SAVE_VECTOR_UNALIGNED(%v31, 424+0x1F0) |
| 699 | #endif | ||
| 695 | 700 | ||
| 696 | li %r3, 0 // return UNW_ESUCCESS | 701 | li %r3, 0 // return UNW_ESUCCESS |
| 697 | blr | 702 | blr |
lib/libunwind/src/Unwind_AppleExtras.cpp-70| ... | @@ -8,35 +8,6 @@ | ... | @@ -8,35 +8,6 @@ |
| 8 | //===----------------------------------------------------------------------===// | 8 | //===----------------------------------------------------------------------===// |
| 9 | 9 | ||
| 10 | #include "config.h" | 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 | // static linker symbols to prevent wrong two level namespace for _Unwind symbols | 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,44 +111,3 @@ NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Resume_or_Rethrow) |
| 140 | NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Unregister) | 111 | NOT_HERE_BEFORE_5_0(_Unwind_SjLj_Unregister) |
| 141 | 112 | ||
| 142 | #endif // defined(_LIBUNWIND_BUILD_SJLJ_APIS) | 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,9 +25,6 @@ |
| 25 | #define PPC64_OFFS_VRSAVE 304 | 25 | #define PPC64_OFFS_VRSAVE 304 |
| 26 | #define PPC64_OFFS_FP 312 | 26 | #define PPC64_OFFS_FP 312 |
| 27 | #define PPC64_OFFS_V 824 | 27 | #define PPC64_OFFS_V 824 |
| 28 | #ifdef _ARCH_PWR8 | ||
| 29 | #define PPC64_HAS_VMX | ||
| 30 | #endif | ||
| 31 | #elif defined(__APPLE__) && defined(__aarch64__) | 28 | #elif defined(__APPLE__) && defined(__aarch64__) |
| 32 | #define SEPARATOR %% | 29 | #define SEPARATOR %% |
| 33 | #else | 30 | #else |
| ... | @@ -48,6 +45,24 @@ | ... | @@ -48,6 +45,24 @@ |
| 48 | #define PPC64_OPD2 | 45 | #define PPC64_OPD2 |
| 49 | #endif | 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 | #define GLUE2(a, b) a ## b | 66 | #define GLUE2(a, b) a ## b |
| 52 | #define GLUE(a, b) GLUE2(a, b) | 67 | #define GLUE(a, b) GLUE2(a, b) |
| 53 | #define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name) | 68 | #define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name) |
| ... | @@ -144,7 +159,8 @@ | ... | @@ -144,7 +159,8 @@ |
| 144 | SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ | 159 | SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ |
| 145 | PPC64_OPD1 \ | 160 | PPC64_OPD1 \ |
| 146 | SYMBOL_NAME(name): \ | 161 | SYMBOL_NAME(name): \ |
| 147 | PPC64_OPD2 | 162 | PPC64_OPD2 \ |
| 163 | AARCH64_BTI | ||
| 148 | 164 | ||
| 149 | #if defined(__arm__) | 165 | #if defined(__arm__) |
| 150 | #if !defined(__ARM_ARCH) | 166 | #if !defined(__ARM_ARCH) |
lib/libunwind/src/config.h+39-15| ... | @@ -18,23 +18,15 @@ | ... | @@ -18,23 +18,15 @@ |
| 18 | #include <stdint.h> | 18 | #include <stdint.h> |
| 19 | #include <stdlib.h> | 19 | #include <stdlib.h> |
| 20 | 20 | ||
| 21 | // Define static_assert() unless already defined by compiler. | 21 | #include <__libunwind_config.h> |
| 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 | ||
| 30 | 22 | ||
| 31 | // Platform specific configuration defines. | 23 | // Platform specific configuration defines. |
| 32 | #ifdef __APPLE__ | 24 | #ifdef __APPLE__ |
| 33 | #if defined(FOR_DYLD) | 25 | #if defined(FOR_DYLD) |
| 34 | #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND | 26 | #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1 |
| 35 | #else | 27 | #else |
| 36 | #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND | 28 | #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 1 |
| 37 | #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 | 29 | #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 |
| 38 | #endif | 30 | #endif |
| 39 | #elif defined(_WIN32) | 31 | #elif defined(_WIN32) |
| 40 | #ifdef __SEH__ | 32 | #ifdef __SEH__ |
| ... | @@ -42,8 +34,19 @@ | ... | @@ -42,8 +34,19 @@ |
| 42 | #else | 34 | #else |
| 43 | #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 | 35 | #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 |
| 44 | #endif | 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 | #else | 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 | #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 | 50 | #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1 |
| 48 | #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1 | 51 | #define _LIBUNWIND_SUPPORT_DWARF_INDEX 1 |
| 49 | #endif | 52 | #endif |
| ... | @@ -91,6 +94,8 @@ | ... | @@ -91,6 +94,8 @@ |
| 91 | #error Unsupported target | 94 | #error Unsupported target |
| 92 | #endif | 95 | #endif |
| 93 | 96 | ||
| 97 | // Apple/armv7k defaults to DWARF/Compact unwinding, but its libunwind also | ||
| 98 | // needs to include the SJLJ APIs. | ||
| 94 | #if (defined(__APPLE__) && defined(__arm__)) || defined(__USING_SJLJ_EXCEPTIONS__) | 99 | #if (defined(__APPLE__) && defined(__arm__)) || defined(__USING_SJLJ_EXCEPTIONS__) |
| 95 | #define _LIBUNWIND_BUILD_SJLJ_APIS | 100 | #define _LIBUNWIND_BUILD_SJLJ_APIS |
| 96 | #endif | 101 | #endif |
| ... | @@ -111,8 +116,27 @@ | ... | @@ -111,8 +116,27 @@ |
| 111 | #endif | 116 | #endif |
| 112 | #endif | 117 | #endif |
| 113 | 118 | ||
| 114 | #if defined(__powerpc64__) && defined(_ARCH_PWR8) | 119 | #ifndef _LIBUNWIND_REMEMBER_HEAP_ALLOC |
| 115 | #define PPC64_HAS_VMX | 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 | #endif | 140 | #endif |
| 117 | 141 | ||
| 118 | #if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL) | 142 | #if defined(NDEBUG) && defined(_LIBUNWIND_IS_BAREMETAL) |