[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