Mercurial > hg > CbC > CbC_llvm
comparison libunwind/src/AddressSpace.hpp @ 236:c4bab56944e8 llvm-original
LLVM 16
author | kono |
---|---|
date | Wed, 09 Nov 2022 17:45:10 +0900 |
parents | 79ff65ed7e25 |
children | 1f2b6ac9f198 |
comparison
equal
deleted
inserted
replaced
232:70dce7da266c | 236:c4bab56944e8 |
---|---|
1 //===------------------------- AddressSpace.hpp ---------------------------===// | 1 //===----------------------------------------------------------------------===// |
2 // | 2 // |
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 // See https://llvm.org/LICENSE.txt for license information. | 4 // See https://llvm.org/LICENSE.txt for license information. |
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 // | 6 // |
22 #include "dwarf2.h" | 22 #include "dwarf2.h" |
23 #include "EHHeaderParser.hpp" | 23 #include "EHHeaderParser.hpp" |
24 #include "Registers.hpp" | 24 #include "Registers.hpp" |
25 | 25 |
26 #ifndef _LIBUNWIND_USE_DLADDR | 26 #ifndef _LIBUNWIND_USE_DLADDR |
27 #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32) | 27 #if !(defined(_LIBUNWIND_IS_BAREMETAL) || defined(_WIN32) || defined(_AIX)) |
28 #define _LIBUNWIND_USE_DLADDR 1 | 28 #define _LIBUNWIND_USE_DLADDR 1 |
29 #else | 29 #else |
30 #define _LIBUNWIND_USE_DLADDR 0 | 30 #define _LIBUNWIND_USE_DLADDR 0 |
31 #endif | 31 #endif |
32 #endif | 32 #endif |
41 #if defined(_LIBUNWIND_ARM_EHABI) | 41 #if defined(_LIBUNWIND_ARM_EHABI) |
42 struct EHABIIndexEntry { | 42 struct EHABIIndexEntry { |
43 uint32_t functionOffset; | 43 uint32_t functionOffset; |
44 uint32_t data; | 44 uint32_t data; |
45 }; | 45 }; |
46 #endif | |
47 | |
48 #if defined(_AIX) | |
49 namespace libunwind { | |
50 char *getFuncNameFromTBTable(uintptr_t pc, uint16_t &NameLen, | |
51 unw_word_t *offset); | |
52 } | |
46 #endif | 53 #endif |
47 | 54 |
48 #ifdef __APPLE__ | 55 #ifdef __APPLE__ |
49 | 56 |
50 struct dyld_unwind_sections | 57 struct dyld_unwind_sections |
119 defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) | 126 defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) |
120 // No dso_base for SEH. | 127 // No dso_base for SEH. |
121 uintptr_t dso_base; | 128 uintptr_t dso_base; |
122 #endif | 129 #endif |
123 #if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) | 130 #if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) |
124 uintptr_t text_segment_length; | 131 size_t text_segment_length; |
125 #endif | 132 #endif |
126 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | 133 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
127 uintptr_t dwarf_section; | 134 uintptr_t dwarf_section; |
128 uintptr_t dwarf_section_length; | 135 size_t dwarf_section_length; |
129 #endif | 136 #endif |
130 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) | 137 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) |
131 uintptr_t dwarf_index_section; | 138 uintptr_t dwarf_index_section; |
132 uintptr_t dwarf_index_section_length; | 139 size_t dwarf_index_section_length; |
133 #endif | 140 #endif |
134 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) | 141 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) |
135 uintptr_t compact_unwind_section; | 142 uintptr_t compact_unwind_section; |
136 uintptr_t compact_unwind_section_length; | 143 size_t compact_unwind_section_length; |
137 #endif | 144 #endif |
138 #if defined(_LIBUNWIND_ARM_EHABI) | 145 #if defined(_LIBUNWIND_ARM_EHABI) |
139 uintptr_t arm_section; | 146 uintptr_t arm_section; |
140 uintptr_t arm_section_length; | 147 size_t arm_section_length; |
141 #endif | 148 #endif |
142 }; | 149 }; |
143 | 150 |
144 | 151 |
145 /// LocalAddressSpace is used as a template parameter to UnwindCursor when | 152 /// LocalAddressSpace is used as a template parameter to UnwindCursor when |
364 #endif | 371 #endif |
365 #if !defined(Elf_Addr) | 372 #if !defined(Elf_Addr) |
366 typedef ElfW(Addr) Elf_Addr; | 373 typedef ElfW(Addr) Elf_Addr; |
367 #endif | 374 #endif |
368 | 375 |
369 static Elf_Addr calculateImageBase(struct dl_phdr_info *pinfo) { | |
370 Elf_Addr image_base = pinfo->dlpi_addr; | |
371 #if defined(__ANDROID__) && __ANDROID_API__ < 18 | |
372 if (image_base == 0) { | |
373 // Normally, an image base of 0 indicates a non-PIE executable. On | |
374 // versions of Android prior to API 18, the dynamic linker reported a | |
375 // dlpi_addr of 0 for PIE executables. Compute the true image base | |
376 // using the PT_PHDR segment. | |
377 // See https://github.com/android/ndk/issues/505. | |
378 for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { | |
379 const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; | |
380 if (phdr->p_type == PT_PHDR) { | |
381 image_base = reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) - | |
382 phdr->p_vaddr; | |
383 break; | |
384 } | |
385 } | |
386 } | |
387 #endif | |
388 return image_base; | |
389 } | |
390 | |
391 struct _LIBUNWIND_HIDDEN dl_iterate_cb_data { | 376 struct _LIBUNWIND_HIDDEN dl_iterate_cb_data { |
392 LocalAddressSpace *addressSpace; | 377 LocalAddressSpace *addressSpace; |
393 UnwindInfoSections *sects; | 378 UnwindInfoSections *sects; |
394 uintptr_t targetAddr; | 379 uintptr_t targetAddr; |
395 }; | 380 }; |
428 *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, | 413 *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, |
429 hdrInfo)) { | 414 hdrInfo)) { |
430 // .eh_frame_hdr records the start of .eh_frame, but not its size. | 415 // .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. | 416 // Rely on a zero terminator to find the end of the section. |
432 cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; | 417 cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; |
433 cbdata->sects->dwarf_section_length = UINTPTR_MAX; | 418 cbdata->sects->dwarf_section_length = SIZE_MAX; |
434 return true; | 419 return true; |
435 } | 420 } |
436 } | 421 } |
437 return false; | 422 return false; |
438 #elif defined(_LIBUNWIND_ARM_EHABI) | 423 #elif defined(_LIBUNWIND_ARM_EHABI) |
459 #else | 444 #else |
460 // Avoid warning about unused variable. | 445 // Avoid warning about unused variable. |
461 (void)pinfo_size; | 446 (void)pinfo_size; |
462 #endif | 447 #endif |
463 | 448 |
464 Elf_Addr image_base = calculateImageBase(pinfo); | 449 Elf_Addr image_base = pinfo->dlpi_addr; |
465 | 450 |
466 // Most shared objects seen in this callback function likely don't contain the | 451 // Most shared objects seen in this callback function likely don't contain the |
467 // target address, so optimize for that. Scan for a matching PT_LOAD segment | 452 // target address, so optimize for that. Scan for a matching PT_LOAD segment |
468 // first and bail when it isn't found. | 453 // first and bail when it isn't found. |
469 bool found_text = false; | 454 bool found_text = false; |
504 dyld_unwind_sections dyldInfo; | 489 dyld_unwind_sections dyldInfo; |
505 if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) { | 490 if (_dyld_find_unwind_sections((void *)targetAddr, &dyldInfo)) { |
506 info.dso_base = (uintptr_t)dyldInfo.mh; | 491 info.dso_base = (uintptr_t)dyldInfo.mh; |
507 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) | 492 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) |
508 info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section; | 493 info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section; |
509 info.dwarf_section_length = dyldInfo.dwarf_section_length; | 494 info.dwarf_section_length = (size_t)dyldInfo.dwarf_section_length; |
510 #endif | 495 #endif |
511 info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section; | 496 info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section; |
512 info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length; | 497 info.compact_unwind_section_length = (size_t)dyldInfo.compact_unwind_section_length; |
513 return true; | 498 return true; |
514 } | 499 } |
515 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) | 500 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) |
516 info.dso_base = 0; | 501 info.dso_base = 0; |
517 // Bare metal is statically linked, so no need to ask the dynamic loader | 502 // Bare metal is statically linked, so no need to ask the dynamic loader |
518 info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start); | 503 info.dwarf_section_length = (size_t)(&__eh_frame_end - &__eh_frame_start); |
519 info.dwarf_section = (uintptr_t)(&__eh_frame_start); | 504 info.dwarf_section = (uintptr_t)(&__eh_frame_start); |
520 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", | 505 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", |
521 (void *)info.dwarf_section, (void *)info.dwarf_section_length); | 506 (void *)info.dwarf_section, (void *)info.dwarf_section_length); |
522 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) | 507 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) |
523 info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start); | 508 info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start); |
524 info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start); | 509 info.dwarf_index_section_length = (size_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start); |
525 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p", | 510 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p", |
526 (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length); | 511 (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length); |
527 #endif | 512 #endif |
528 if (info.dwarf_section_length) | 513 if (info.dwarf_section_length) |
529 return true; | 514 return true; |
530 #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) | 515 #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) |
531 // Bare metal is statically linked, so no need to ask the dynamic loader | 516 // Bare metal is statically linked, so no need to ask the dynamic loader |
532 info.arm_section = (uintptr_t)(&__exidx_start); | 517 info.arm_section = (uintptr_t)(&__exidx_start); |
533 info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start); | 518 info.arm_section_length = (size_t)(&__exidx_end - &__exidx_start); |
534 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", | 519 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", |
535 (void *)info.arm_section, (void *)info.arm_section_length); | 520 (void *)info.arm_section, (void *)info.arm_section_length); |
536 if (info.arm_section && info.arm_section_length) | 521 if (info.arm_section && info.arm_section_length) |
537 return true; | 522 return true; |
538 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32) | 523 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32) |
542 | 527 |
543 if (!EnumProcessModules(process, mods, sizeof(mods), &needed)) { | 528 if (!EnumProcessModules(process, mods, sizeof(mods), &needed)) { |
544 DWORD err = GetLastError(); | 529 DWORD err = GetLastError(); |
545 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: EnumProcessModules failed, " | 530 _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: EnumProcessModules failed, " |
546 "returned error %d", (int)err); | 531 "returned error %d", (int)err); |
532 (void)err; | |
547 return false; | 533 return false; |
548 } | 534 } |
549 | 535 |
550 for (unsigned i = 0; i < (needed / sizeof(HMODULE)); i++) { | 536 for (unsigned i = 0; i < (needed / sizeof(HMODULE)); i++) { |
551 PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)mods[i]; | 537 PIMAGE_DOS_HEADER pidh = (PIMAGE_DOS_HEADER)mods[i]; |
578 // Don't even bother, since Windows has functions that do all this stuff | 564 // Don't even bother, since Windows has functions that do all this stuff |
579 // for us. | 565 // for us. |
580 (void)targetAddr; | 566 (void)targetAddr; |
581 (void)info; | 567 (void)info; |
582 return true; | 568 return true; |
569 #elif defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND) | |
570 // The traceback table is used for unwinding. | |
571 (void)targetAddr; | |
572 (void)info; | |
573 return true; | |
583 #elif defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX) | 574 #elif defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX) |
584 int length = 0; | 575 int length = 0; |
585 info.arm_section = | 576 info.arm_section = |
586 (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length); | 577 (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length); |
587 info.arm_section_length = (uintptr_t)length * sizeof(EHABIIndexEntry); | 578 info.arm_section_length = (size_t)length * sizeof(EHABIIndexEntry); |
588 if (info.arm_section && info.arm_section_length) | 579 if (info.arm_section && info.arm_section_length) |
589 return true; | 580 return true; |
590 #elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) | 581 #elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) |
582 // Use DLFO_STRUCT_HAS_EH_DBASE to determine the existence of | |
583 // `_dl_find_object`. Use _LIBUNWIND_SUPPORT_DWARF_INDEX, because libunwind | |
584 // support for _dl_find_object on other unwind formats is not implemented, | |
585 // yet. | |
586 #if defined(DLFO_STRUCT_HAS_EH_DBASE) & defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) | |
587 // We expect `_dl_find_object` to return PT_GNU_EH_FRAME. | |
588 #if DLFO_EH_SEGMENT_TYPE != PT_GNU_EH_FRAME | |
589 #error _dl_find_object retrieves an unexpected section type | |
590 #endif | |
591 // We look-up `dl_find_object` dynamically at runtime to ensure backwards | |
592 // compatibility with earlier version of glibc not yet providing it. On older | |
593 // systems, we gracefully fallback to `dl_iterate_phdr`. Cache the pointer | |
594 // so we only look it up once. Do manual lock to avoid _cxa_guard_acquire. | |
595 static decltype(_dl_find_object) *dlFindObject; | |
596 static bool dlFindObjectChecked = false; | |
597 if (!dlFindObjectChecked) { | |
598 dlFindObject = reinterpret_cast<decltype(_dl_find_object) *>( | |
599 dlsym(RTLD_DEFAULT, "_dl_find_object")); | |
600 dlFindObjectChecked = true; | |
601 } | |
602 // Try to find the unwind info using `dl_find_object` | |
603 dl_find_object findResult; | |
604 if (dlFindObject && dlFindObject((void *)targetAddr, &findResult) == 0) { | |
605 if (findResult.dlfo_eh_frame == nullptr) { | |
606 // Found an entry for `targetAddr`, but there is no unwind info. | |
607 return false; | |
608 } | |
609 info.dso_base = reinterpret_cast<uintptr_t>(findResult.dlfo_map_start); | |
610 info.text_segment_length = static_cast<size_t>( | |
611 (char *)findResult.dlfo_map_end - (char *)findResult.dlfo_map_start); | |
612 | |
613 // Record the start of PT_GNU_EH_FRAME. | |
614 info.dwarf_index_section = | |
615 reinterpret_cast<uintptr_t>(findResult.dlfo_eh_frame); | |
616 // `_dl_find_object` does not give us the size of PT_GNU_EH_FRAME. | |
617 // Setting length to `SIZE_MAX` effectively disables all range checks. | |
618 info.dwarf_index_section_length = SIZE_MAX; | |
619 EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo; | |
620 if (!EHHeaderParser<LocalAddressSpace>::decodeEHHdr( | |
621 *this, info.dwarf_index_section, info.dwarf_index_section_length, | |
622 hdrInfo)) { | |
623 return false; | |
624 } | |
625 // Record the start of the FDE and use SIZE_MAX to indicate that we do | |
626 // not know the end address. | |
627 info.dwarf_section = hdrInfo.eh_frame_ptr; | |
628 info.dwarf_section_length = SIZE_MAX; | |
629 return true; | |
630 } | |
631 #endif | |
591 dl_iterate_cb_data cb_data = {this, &info, targetAddr}; | 632 dl_iterate_cb_data cb_data = {this, &info, targetAddr}; |
592 int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data); | 633 int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data); |
593 return static_cast<bool>(found); | 634 return static_cast<bool>(found); |
594 #endif | 635 #endif |
595 | 636 |
596 return false; | 637 return false; |
597 } | 638 } |
598 | |
599 | 639 |
600 inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { | 640 inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { |
601 // TO DO: if OS has way to dynamically register FDEs, check that. | 641 // TO DO: if OS has way to dynamically register FDEs, check that. |
602 (void)targetAddr; | 642 (void)targetAddr; |
603 (void)fde; | 643 (void)fde; |
614 snprintf(buf, bufLen, "%s", dyldInfo.dli_sname); | 654 snprintf(buf, bufLen, "%s", dyldInfo.dli_sname); |
615 *offset = (addr - (pint_t) dyldInfo.dli_saddr); | 655 *offset = (addr - (pint_t) dyldInfo.dli_saddr); |
616 return true; | 656 return true; |
617 } | 657 } |
618 } | 658 } |
659 #elif defined(_AIX) | |
660 uint16_t nameLen; | |
661 char *funcName = getFuncNameFromTBTable(addr, nameLen, offset); | |
662 if (funcName != NULL) { | |
663 snprintf(buf, bufLen, "%.*s", nameLen, funcName); | |
664 return true; | |
665 } | |
619 #else | 666 #else |
620 (void)addr; | 667 (void)addr; |
621 (void)buf; | 668 (void)buf; |
622 (void)bufLen; | 669 (void)bufLen; |
623 (void)offset; | 670 (void)offset; |