[libunwind] d67cf7a - Rework findUnwindSectionsByPhdr to be more optimal.
Sterling Augustine via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 10 10:35:45 PDT 2020
Author: Sterling Augustine
Date: 2020-03-10T10:35:15-07:00
New Revision: d67cf7a0a970df6e69db437514bf61a2ab283e67
URL: https://github.com/llvm/llvm-project/commit/d67cf7a0a970df6e69db437514bf61a2ab283e67
DIFF: https://github.com/llvm/llvm-project/commit/d67cf7a0a970df6e69db437514bf61a2ab283e67.diff
LOG: Rework findUnwindSectionsByPhdr to be more optimal.
Summary:
- Executable segment is usually segment 3. Look there for the address first.
- GNU_EH_FRAME_HEADER segment is usually near the end. Iterate from the end.
- Exit early if both phdrs have been found.
This is the last cl before a patch to cache the information this function
finds.
Subscribers: libcxx-commits
Tags: #libc
Differential Revision: https://reviews.llvm.org/D75781
Added:
Modified:
libunwind/src/AddressSpace.hpp
Removed:
################################################################################
diff --git a/libunwind/src/AddressSpace.hpp b/libunwind/src/AddressSpace.hpp
index d4d66ad74ff6..83af9aeaef77 100644
--- a/libunwind/src/AddressSpace.hpp
+++ b/libunwind/src/AddressSpace.hpp
@@ -452,31 +452,38 @@ struct _LIBUNWIND_HIDDEN dl_iterate_cb_data {
#error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
#endif
-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);
+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;
+}
- if (cbdata->targetAddr < pinfo->dlpi_addr)
+int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, size_t, void *data) {
+ auto cbdata = static_cast<dl_iterate_cb_data *>(data);
+ if (pinfo->dlpi_phnum == 0 || cbdata->targetAddr < pinfo->dlpi_addr)
return 0;
Elf_Addr image_base = calculateImageBase(pinfo);
- size_t object_length;
+ bool found_obj = false;
+ bool found_hdr = false;
- 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) {
+ // 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;
@@ -486,15 +493,14 @@ int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, size_t, void *data) {
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)
+ return 1;
}
-
- if (found_obj && found_hdr) {
- cbdata->sects->dwarf_section_length = object_length;
- return true;
- } else {
- return false;
- }
+ cbdata->sects->dwarf_section_length = 0;
+ return 0;
}
#else // defined(LIBUNWIND_SUPPORT_DWARF_UNWIND)
More information about the cfe-commits
mailing list