Mercurial > hg > CbC > CbC_llvm
diff libunwind/src/AddressSpace.hpp @ 173:0572611fdcc8 llvm10 llvm12
reorgnization done
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 11:55:54 +0900 |
parents | 1d019706d866 |
children | 2e18cbf3894f |
line wrap: on
line diff
--- a/libunwind/src/AddressSpace.hpp Mon May 25 11:50:15 2020 +0900 +++ b/libunwind/src/AddressSpace.hpp Mon May 25 11:55:54 2020 +0900 @@ -392,6 +392,164 @@ return result; } +#ifdef __APPLE__ +#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_LIBUNWIND_IS_BAREMETAL) +#elif defined(_LIBUNWIND_ARM_EHABI) && defined(_LIBUNWIND_IS_BAREMETAL) +#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32) +#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32) +#elif defined(_LIBUNWIND_ARM_EHABI) && defined(__BIONIC__) +// Code inside findUnwindSections handles all these cases. +// +// Although the above ifdef chain is ugly, there doesn't seem to be a cleaner +// way to handle it. The generalized boolean expression is: +// +// A OR (B AND C) OR (D AND C) OR (B AND E) OR (F AND E) OR (D AND G) +// +// Running it through various boolean expression simplifiers gives expressions +// that don't help at all. +#elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + +#if !defined(Elf_Half) + typedef ElfW(Half) Elf_Half; +#endif +#if !defined(Elf_Phdr) + typedef ElfW(Phdr) Elf_Phdr; +#endif +#if !defined(Elf_Addr) + 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; + uintptr_t targetAddr; +}; + +#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) + #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform." + #endif + +#include "FrameHeaderCache.hpp" + +// There should be just one of these per process. +static FrameHeaderCache ProcessFrameHeaderCache; + +static bool checkAddrInSegment(const Elf_Phdr *phdr, size_t image_base, + dl_iterate_cb_data *cbdata) { + if (phdr->p_type == PT_LOAD) { + uintptr_t begin = image_base + phdr->p_vaddr; + uintptr_t end = begin + phdr->p_memsz; + if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) { + cbdata->sects->dso_base = begin; + cbdata->sects->dwarf_section_length = phdr->p_memsz; + return true; + } + } + return false; +} + +int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, size_t pinfo_size, + void *data) { + auto cbdata = static_cast<dl_iterate_cb_data *>(data); + if (pinfo->dlpi_phnum == 0 || cbdata->targetAddr < pinfo->dlpi_addr) + return 0; + if (ProcessFrameHeaderCache.find(pinfo, pinfo_size, data)) + return 1; + + Elf_Addr image_base = calculateImageBase(pinfo); + bool found_obj = false; + bool found_hdr = false; + + // Third phdr is usually the executable phdr. + if (pinfo->dlpi_phnum > 2) + found_obj = checkAddrInSegment(&pinfo->dlpi_phdr[2], image_base, cbdata); + + // PT_GNU_EH_FRAME is usually near the end. Iterate backward. We already know + // that there is one or more phdrs. + for (Elf_Half i = pinfo->dlpi_phnum; i > 0; i--) { + const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i - 1]; + if (!found_hdr && phdr->p_type == PT_GNU_EH_FRAME) { + EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo; + uintptr_t eh_frame_hdr_start = image_base + phdr->p_vaddr; + cbdata->sects->dwarf_index_section = eh_frame_hdr_start; + cbdata->sects->dwarf_index_section_length = phdr->p_memsz; + found_hdr = EHHeaderParser<LocalAddressSpace>::decodeEHHdr( + *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, + hdrInfo); + if (found_hdr) + cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; + } else if (!found_obj) { + found_obj = checkAddrInSegment(phdr, image_base, cbdata); + } + if (found_obj && found_hdr) { + ProcessFrameHeaderCache.add(cbdata->sects); + return 1; + } + } + cbdata->sects->dwarf_section_length = 0; + return 0; +} + +#else // defined(LIBUNWIND_SUPPORT_DWARF_UNWIND) +// Given all the #ifdef's above, the code here is for +// defined(LIBUNWIND_ARM_EHABI) + +int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, size_t, void *data) { + auto *cbdata = static_cast<dl_iterate_cb_data *>(data); + bool found_obj = false; + bool found_hdr = false; + + assert(cbdata); + assert(cbdata->sects); + + if (cbdata->targetAddr < pinfo->dlpi_addr) + return 0; + + Elf_Addr image_base = calculateImageBase(pinfo); + + for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { + const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; + if (phdr->p_type == PT_LOAD) { + uintptr_t begin = image_base + phdr->p_vaddr; + uintptr_t end = begin + phdr->p_memsz; + if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) + found_obj = true; + } else if (phdr->p_type == PT_ARM_EXIDX) { + uintptr_t exidx_start = image_base + phdr->p_vaddr; + cbdata->sects->arm_section = exidx_start; + cbdata->sects->arm_section_length = phdr->p_memsz; + found_hdr = true; + } + } + return found_obj && found_hdr; +} +#endif // defined(LIBUNWIND_SUPPORT_DWARF_UNWIND) +#endif // defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) + + inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, UnwindInfoSections &info) { #ifdef __APPLE__ @@ -483,110 +641,8 @@ if (info.arm_section && info.arm_section_length) return true; #elif defined(_LIBUNWIND_ARM_EHABI) || defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - struct dl_iterate_cb_data { - LocalAddressSpace *addressSpace; - UnwindInfoSections *sects; - uintptr_t targetAddr; - }; - dl_iterate_cb_data cb_data = {this, &info, targetAddr}; - int found = dl_iterate_phdr( - [](struct dl_phdr_info *pinfo, size_t, void *data) -> int { - auto cbdata = static_cast<dl_iterate_cb_data *>(data); - bool found_obj = false; - bool found_hdr = false; - - assert(cbdata); - assert(cbdata->sects); - - if (cbdata->targetAddr < pinfo->dlpi_addr) { - return false; - } - -#if !defined(Elf_Half) - typedef ElfW(Half) Elf_Half; -#endif -#if !defined(Elf_Phdr) - typedef ElfW(Phdr) Elf_Phdr; -#endif -#if !defined(Elf_Addr) - typedef ElfW(Addr) Elf_Addr; -#endif - - 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 - - #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) - #if !defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) - #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform." - #endif - size_t object_length; - - for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { - const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; - if (phdr->p_type == PT_LOAD) { - uintptr_t begin = image_base + phdr->p_vaddr; - uintptr_t end = begin + phdr->p_memsz; - if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) { - cbdata->sects->dso_base = begin; - object_length = phdr->p_memsz; - found_obj = true; - } - } else if (phdr->p_type == PT_GNU_EH_FRAME) { - EHHeaderParser<LocalAddressSpace>::EHHeaderInfo hdrInfo; - uintptr_t eh_frame_hdr_start = image_base + phdr->p_vaddr; - cbdata->sects->dwarf_index_section = eh_frame_hdr_start; - cbdata->sects->dwarf_index_section_length = phdr->p_memsz; - found_hdr = EHHeaderParser<LocalAddressSpace>::decodeEHHdr( - *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz, - hdrInfo); - if (found_hdr) - cbdata->sects->dwarf_section = hdrInfo.eh_frame_ptr; - } - } - - if (found_obj && found_hdr) { - cbdata->sects->dwarf_section_length = object_length; - return true; - } else { - return false; - } - #else // defined(_LIBUNWIND_ARM_EHABI) - for (Elf_Half i = 0; i < pinfo->dlpi_phnum; i++) { - const Elf_Phdr *phdr = &pinfo->dlpi_phdr[i]; - if (phdr->p_type == PT_LOAD) { - uintptr_t begin = image_base + phdr->p_vaddr; - uintptr_t end = begin + phdr->p_memsz; - if (cbdata->targetAddr >= begin && cbdata->targetAddr < end) - found_obj = true; - } else if (phdr->p_type == PT_ARM_EXIDX) { - uintptr_t exidx_start = image_base + phdr->p_vaddr; - cbdata->sects->arm_section = exidx_start; - cbdata->sects->arm_section_length = phdr->p_memsz; - found_hdr = true; - } - } - return found_obj && found_hdr; - #endif - }, - &cb_data); + int found = dl_iterate_phdr(findUnwindSectionsByPhdr, &cb_data); return static_cast<bool>(found); #endif