[libunwind] b16d665 - [libunwind] Combine dl_iterate_phdr codepaths for DWARF and EHABI

Ryan Prichard via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 23 15:42:28 PDT 2020


Author: Ryan Prichard
Date: 2020-09-23T15:40:39-07:00
New Revision: b16d6653c01cee37f51a98dd4092c4ef302c47a5

URL: https://github.com/llvm/llvm-project/commit/b16d6653c01cee37f51a98dd4092c4ef302c47a5
DIFF: https://github.com/llvm/llvm-project/commit/b16d6653c01cee37f51a98dd4092c4ef302c47a5.diff

LOG: [libunwind] Combine dl_iterate_phdr codepaths for DWARF and EHABI

dl_iterate_phdr is used to search for unwind info provided by either
PT_GNU_EH_FRAME or PT_ARM_EXIDX. Most of the code between the two is
the same, so combine them, and factor out what's different into
checkForUnwindInfoSegment.

Details:
 - The FrameHeaderCache can now be enabled for ARM EHABI.
 - findUnwindSectionsByPhdr now finds the last PT_ARM_EXIDX rather than
   the first. There should only be one segment.
 - The dso_base and text_segment_length fields of UnwindInfoSections
   are now needed for dl_iterate_phdr when using EHABI, to hold the
   low and high PC values for a cache entry.

Reviewed By: compnerd, danielkiss, #libunwind, saugustine

Differential Revision: https://reviews.llvm.org/D87880

Added: 
    

Modified: 
    libunwind/src/AddressSpace.hpp
    libunwind/test/frameheadercache_test.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libunwind/src/AddressSpace.hpp b/libunwind/src/AddressSpace.hpp
index 26397c28798e..7a926ec0be55 100644
--- a/libunwind/src/AddressSpace.hpp
+++ b/libunwind/src/AddressSpace.hpp
@@ -114,13 +114,13 @@ namespace libunwind {
 
 /// Used by findUnwindSections() to return info about needed sections.
 struct UnwindInfoSections {
-#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) || defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) ||       \
-    defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
-  // No dso_base for SEH or ARM EHABI.
+#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) ||                                \
+    defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) ||                              \
+    defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
+  // No dso_base for SEH.
   uintptr_t       dso_base;
 #endif
-#if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) &&                                 \
-    defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
+#if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
   uintptr_t       text_segment_length;
 #endif
 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
@@ -394,11 +394,6 @@ struct _LIBUNWIND_HIDDEN dl_iterate_cb_data {
   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
-
 #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE)
 #include "FrameHeaderCache.hpp"
 
@@ -421,6 +416,38 @@ static bool checkAddrInSegment(const Elf_Phdr *phdr, size_t image_base,
   return false;
 }
 
+static bool checkForUnwindInfoSegment(const Elf_Phdr *phdr, size_t image_base,
+                                      dl_iterate_cb_data *cbdata) {
+#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
+  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;
+    if (EHHeaderParser<LocalAddressSpace>::decodeEHHdr(
+            *cbdata->addressSpace, eh_frame_hdr_start, phdr->p_memsz,
+            hdrInfo)) {
+      // .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;
+      return true;
+    }
+  }
+  return false;
+#elif defined(_LIBUNWIND_ARM_EHABI)
+  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;
+    return true;
+  }
+  return false;
+#else
+#error Need one of _LIBUNWIND_SUPPORT_DWARF_INDEX or _LIBUNWIND_ARM_EHABI
+#endif
+}
+
 static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo,
                                     size_t pinfo_size, void *data) {
   auto cbdata = static_cast<dl_iterate_cb_data *>(data);
@@ -435,35 +462,22 @@ static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo,
 #endif
 
   Elf_Addr image_base = calculateImageBase(pinfo);
-  bool found_obj = false;
-  bool found_hdr = false;
+  bool found_text = false;
+  bool found_unwind = false;
 
   // Third phdr is usually the executable phdr.
   if (pinfo->dlpi_phnum > 2)
-    found_obj = checkAddrInSegment(&pinfo->dlpi_phdr[2], image_base, cbdata);
+    found_text = 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.
+  // PT_GNU_EH_FRAME and PT_ARM_EXIDX are 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) {
-        // .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;
-      }
-    } else if (!found_obj) {
-      found_obj = checkAddrInSegment(phdr, image_base, cbdata);
-    }
-    if (found_obj && found_hdr) {
+    if (!found_unwind && checkForUnwindInfoSegment(phdr, image_base, cbdata))
+      found_unwind = true;
+    else if (!found_text && checkAddrInSegment(phdr, image_base, cbdata))
+      found_text = true;
+    if (found_text && found_unwind) {
 #if defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE)
       TheFrameHeaderCache.add(cbdata->sects);
 #endif
@@ -473,40 +487,6 @@ static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo,
   return 0;
 }
 
-#elif defined(_LIBUNWIND_ARM_EHABI)
-
-static 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
 #endif  // defined(_LIBUNWIND_USE_DL_ITERATE_PHDR)
 
 

diff  --git a/libunwind/test/frameheadercache_test.pass.cpp b/libunwind/test/frameheadercache_test.pass.cpp
index 15c7c67c58ea..7f14830fa30d 100644
--- a/libunwind/test/frameheadercache_test.pass.cpp
+++ b/libunwind/test/frameheadercache_test.pass.cpp
@@ -5,7 +5,6 @@
 // Only run this test under supported configurations.
 
 #if defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) &&                                 \
-    defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) &&                                 \
     defined(_LIBUNWIND_USE_FRAME_HEADER_CACHE)
 
 #include <link.h>


        


More information about the cfe-commits mailing list