Mercurial > hg > CbC > CbC_llvm
diff 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 |
line wrap: on
line diff
--- a/libunwind/src/AddressSpace.hpp Wed Jul 21 10:27:27 2021 +0900 +++ b/libunwind/src/AddressSpace.hpp Wed Nov 09 17:45:10 2022 +0900 @@ -1,4 +1,4 @@ -//===------------------------- AddressSpace.hpp ---------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -24,7 +24,7 @@ #include "Registers.hpp" #ifndef _LIBUNWIND_USE_DLADDR - #if !defined(_LIBUNWIND_IS_BAREMETAL) && !defined(_WIN32) + #if !(defined(_LIBUNWIND_IS_BAREMETAL) || defined(_WIN32) || defined(_AIX)) #define _LIBUNWIND_USE_DLADDR 1 #else #define _LIBUNWIND_USE_DLADDR 0 @@ -45,6 +45,13 @@ }; #endif +#if defined(_AIX) +namespace libunwind { +char *getFuncNameFromTBTable(uintptr_t pc, uint16_t &NameLen, + unw_word_t *offset); +} +#endif + #ifdef __APPLE__ struct dyld_unwind_sections @@ -121,23 +128,23 @@ uintptr_t dso_base; #endif #if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) - uintptr_t text_segment_length; + size_t text_segment_length; #endif #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) uintptr_t dwarf_section; - uintptr_t dwarf_section_length; + size_t dwarf_section_length; #endif #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) uintptr_t dwarf_index_section; - uintptr_t dwarf_index_section_length; + size_t dwarf_index_section_length; #endif #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) uintptr_t compact_unwind_section; - uintptr_t compact_unwind_section_length; + size_t compact_unwind_section_length; #endif #if defined(_LIBUNWIND_ARM_EHABI) uintptr_t arm_section; - uintptr_t arm_section_length; + size_t arm_section_length; #endif }; @@ -366,28 +373,6 @@ typedef ElfW(Addr) Elf_Addr; #endif -static Elf_Addr calculateImageBase(struct dl_phdr_info *pinfo) { - Elf_Addr image_base = pinfo->dlpi_addr; -#if defined(__ANDROID__) && __ANDROID_API__ < 18 - if (image_base == 0) { - // Normally, an image base of 0 indicates a non-PIE executable. On - // versions of Android prior to API 18, the dynamic linker reported a - // dlpi_addr of 0 for PIE executables. Compute the true image base - // using the PT_PHDR segment. - // See https://github.com/android/ndk/issues/505. - for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { - const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; - if (phdr->p_type == PT_PHDR) { - image_base = reinterpret_cast<Elf_Addr>(pinfo->dlpi_phdr) - - phdr->p_vaddr; - break; - } - } - } -#endif - return image_base; -} - struct _LIBUNWIND_HIDDEN dl_iterate_cb_data { LocalAddressSpace *addressSpace; UnwindInfoSections *sects; @@ -430,7 +415,7 @@ // .eh_frame_hdr records the start of .eh_frame, but not its size. // Rely on a zero terminator to find the end of the section. cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; - cbdata->sects->dwarf_section_length = UINTPTR_MAX; + cbdata->sects->dwarf_section_length = SIZE_MAX; return true; } } @@ -461,7 +446,7 @@ (void)pinfo_size; #endif - Elf_Addr image_base = calculateImageBase(pinfo); + Elf_Addr image_base = pinfo->dlpi_addr; // Most shared objects seen in this callback function likely don't contain the // target address, so optimize for that. Scan for a matching PT_LOAD segment @@ -506,22 +491,22 @@ info.dso_base = (uintptr_t)dyldInfo.mh; #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) info.dwarf_section = (uintptr_t)dyldInfo.dwarf_section; - info.dwarf_section_length = dyldInfo.dwarf_section_length; + info.dwarf_section_length = (size_t)dyldInfo.dwarf_section_length; #endif info.compact_unwind_section = (uintptr_t)dyldInfo.compact_unwind_section; - info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length; + info.compact_unwind_section_length = (size_t)dyldInfo.compact_unwind_section_length; return true; } #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) info.dso_base = 0; // Bare metal is statically linked, so no need to ask the dynamic loader - info.dwarf_section_length = (uintptr_t)(&__eh_frame_end - &__eh_frame_start); + info.dwarf_section_length = (size_t)(&__eh_frame_end - &__eh_frame_start); info.dwarf_section = (uintptr_t)(&__eh_frame_start); _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", (void *)info.dwarf_section, (void *)info.dwarf_section_length); #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) info.dwarf_index_section = (uintptr_t)(&__eh_frame_hdr_start); - info.dwarf_index_section_length = (uintptr_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start); + info.dwarf_index_section_length = (size_t)(&__eh_frame_hdr_end - &__eh_frame_hdr_start); _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: index section %p length %p", (void *)info.dwarf_index_section, (void *)info.dwarf_index_section_length); #endif @@ -530,7 +515,7 @@ #elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) // Bare metal is statically linked, so no need to ask the dynamic loader info.arm_section = (uintptr_t)(&__exidx_start); - info.arm_section_length = (uintptr_t)(&__exidx_end - &__exidx_start); + info.arm_section_length = (size_t)(&__exidx_end - &__exidx_start); _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %p length %p", (void *)info.arm_section, (void *)info.arm_section_length); if (info.arm_section && info.arm_section_length) @@ -544,6 +529,7 @@ DWORD err = GetLastError(); _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: EnumProcessModules failed, " "returned error %d", (int)err); + (void)err; return false; } @@ -580,14 +566,69 @@ (void)targetAddr; (void)info; return true; +#elif defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND) + // The traceback table is used for unwinding. + (void)targetAddr; + (void)info; + return true; #elif defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX) int length = 0; info.arm_section = (uintptr_t)dl_unwind_find_exidx((_Unwind_Ptr)targetAddr, &length); - info.arm_section_length = (uintptr_t)length * sizeof(EHABIIndexEntry); + info.arm_section_length = (size_t)length * sizeof(EHABIIndexEntry); if (info.arm_section && info.arm_section_length) return true; #elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) + // Use DLFO_STRUCT_HAS_EH_DBASE to determine the existence of + // `_dl_find_object`. Use _LIBUNWIND_SUPPORT_DWARF_INDEX, because libunwind + // support for _dl_find_object on other unwind formats is not implemented, + // yet. +#if defined(DLFO_STRUCT_HAS_EH_DBASE) & defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) + // We expect `_dl_find_object` to return PT_GNU_EH_FRAME. +#if DLFO_EH_SEGMENT_TYPE != PT_GNU_EH_FRAME +#error _dl_find_object retrieves an unexpected section type +#endif + // We look-up `dl_find_object` dynamically at runtime to ensure backwards + // compatibility with earlier version of glibc not yet providing it. On older + // systems, we gracefully fallback to `dl_iterate_phdr`. Cache the pointer + // so we only look it up once. Do manual lock to avoid _cxa_guard_acquire. + static decltype(_dl_find_object) *dlFindObject; + static bool dlFindObjectChecked = false; + if (!dlFindObjectChecked) { + dlFindObject = reinterpret_cast<decltype(_dl_find_object) *>( + dlsym(RTLD_DEFAULT, "_dl_find_object")); + dlFindObjectChecked = true; + } + // Try to find the unwind info using `dl_find_object` + dl_find_object findResult; + if (dlFindObject && dlFindObject((void *)targetAddr, &findResult) == 0) { + if (findResult.dlfo_eh_frame == nullptr) { + // Found an entry for `targetAddr`, but there is no unwind info. + return false; + } + info.dso_base = reinterpret_cast<uintptr_t>(findResult.dlfo_map_start); + info.text_segment_length = static_cast<size_t>( + (char *)findResult.dlfo_map_end - (char *)findResult.dlfo_map_start); + + // Record the start of PT_GNU_EH_FRAME. + info.dwarf_index_section = + reinterpret_cast<uintptr_t>(findResult.dlfo_eh_frame); + // `_dl_find_object` does not give us the size of PT_GNU_EH_FRAME. + // Setting length to `SIZE_MAX` effectively disables all range checks. + info.dwarf_index_section_length = SIZE_MAX; + EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo; + if (!EHHeaderParser<LocalAddressSpace>::decodeEHHdr( + *this, info.dwarf_index_section, info.dwarf_index_section_length, + hdrInfo)) { + return false; + } + // Record the start of the FDE and use SIZE_MAX to indicate that we do + // not know the end address. + info.dwarf_section = hdrInfo.eh_frame_ptr; + info.dwarf_section_length = SIZE_MAX; + return true; + } +#endif dl_iterate_cb_data cb_data = {this, &info, targetAddr}; int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data); return static_cast<bool>(found); @@ -596,7 +637,6 @@ return false; } - inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { // TO DO: if OS has way to dynamically register FDEs, check that. (void)targetAddr; @@ -616,6 +656,13 @@ return true; } } +#elif defined(_AIX) + uint16_t nameLen; + char *funcName = getFuncNameFromTBTable(addr, nameLen, offset); + if (funcName != NULL) { + snprintf(buf, bufLen, "%.*s", nameLen, funcName); + return true; + } #else (void)addr; (void)buf;