Drop the dependency on dl_unwind_find_exidx().

While porting libunwind over to CloudABI for ARMv6, I observed that this
source file doesn't build, as it depends on dl_unwind_find_exidx(),
which CloudABI's C library was lacking. After I added that function,
I still needed to patch up libunwind to define _Unwind_Ptr.

Taking a step back, I wonder why we need to make use of this function
anyway. The unwinder already has some nice code to use dl_iterate_phdr()
to scan for a PT_GNU_EH_FRAME header. The dl_unwind_find_exidx() does
the same thing, except matching PT_ARM_EXIDX instead. We could also do
that ourselves.

This change gets rid of the dl_unwind_find_exidx() call and extends the
dl_iterate_phdr() loop. In addition to making the code a bit shorter, it
has the advantage of getting rid of some of those OS-specific #ifdefs.

This now means that if an operating system only provides
dl_iterate_phdr(), it gets support for unwinding on all architectures.
There is no need to add more stuff, just to get ARMv6 support.

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


git-svn-id: https://llvm.org/svn/llvm-project/libunwind/trunk@295944 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/src/AddressSpace.hpp b/src/AddressSpace.hpp
index f0091fc..219f3f4 100644
--- a/src/AddressSpace.hpp
+++ b/src/AddressSpace.hpp
@@ -35,29 +35,17 @@
 #include "Registers.hpp"
 
 #if _LIBUNWIND_ARM_EHABI
-#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
-
-typedef void *_Unwind_Ptr;
-
-#elif defined(__linux__)
-
-typedef long unsigned int *_Unwind_Ptr;
-extern "C" _Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr addr, int *len);
-
-// Emulate the BSD dl_unwind_find_exidx API when on a GNU libdl system.
-#define dl_unwind_find_exidx __gnu_Unwind_Find_exidx
-
-#elif !defined(_LIBUNWIND_IS_BAREMETAL)
-#include <link.h>
-#else // !defined(_LIBUNWIND_IS_BAREMETAL)
-// When statically linked on bare-metal, the symbols for the EH table are looked
-// up without going through the dynamic loader.
 struct EHTEntry {
   uint32_t functionOffset;
   uint32_t unwindOpcodes;
 };
+#if defined(_LIBUNWIND_IS_BAREMETAL)
+// When statically linked on bare-metal, the symbols for the EH table are looked
+// up without going through the dynamic loader.
 extern EHTEntry __exidx_start;
 extern EHTEntry __exidx_end;
+#else
+#include <link.h>
 #endif // !defined(_LIBUNWIND_IS_BAREMETAL)
 #endif // _LIBUNWIND_ARM_EHABI
 
@@ -368,23 +356,15 @@
     info.compact_unwind_section_length = dyldInfo.compact_unwind_section_length;
     return true;
   }
-#elif _LIBUNWIND_ARM_EHABI
- #ifdef _LIBUNWIND_IS_BAREMETAL
+#elif _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);
- #else
-  int length = 0;
-  info.arm_section = (uintptr_t) dl_unwind_find_exidx(
-      (_Unwind_Ptr) targetAddr, &length);
-  info.arm_section_length = (uintptr_t)length;
- #endif
   _LIBUNWIND_TRACE_UNWINDING("findUnwindSections: section %X length %x",
                              info.arm_section, info.arm_section_length);
   if (info.arm_section && info.arm_section_length)
     return true;
-#elif _LIBUNWIND_SUPPORT_DWARF_UNWIND
-#if _LIBUNWIND_SUPPORT_DWARF_INDEX
+#elif _LIBUNWIND_ARM_EHABI || _LIBUNWIND_SUPPORT_DWARF_UNWIND
   struct dl_iterate_cb_data {
     LocalAddressSpace *addressSpace;
     UnwindInfoSections *sects;
@@ -395,9 +375,6 @@
   int found = dl_iterate_phdr(
       [](struct dl_phdr_info *pinfo, size_t, void *data) -> int {
         auto cbdata = static_cast<dl_iterate_cb_data *>(data);
-        size_t object_length;
-        bool found_obj = false;
-        bool found_hdr = false;
 
         assert(cbdata);
         assert(cbdata->sects);
@@ -413,6 +390,14 @@
         typedef ElfW(Phdr) Elf_Phdr;
 #endif
 
+ #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
+  #if !_LIBUNWIND_SUPPORT_DWARF_INDEX
+   #error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
+  #endif
+        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) {
@@ -442,12 +427,22 @@
         } else {
           return false;
         }
+ #else // _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_ARM_EXIDX) {
+            uintptr_t exidx_start = pinfo->dlpi_addr + phdr->p_vaddr;
+            cbdata->sects->arm_section = exidx_start;
+            cbdata->sects->arm_section_length = phdr->p_memsz /
+                                                sizeof(EHTEntry);
+            return true;
+          }
+        }
+        return false;
+ #endif
       },
       &cb_data);
   return static_cast<bool>(found);
-#else
-#error "_LIBUNWIND_SUPPORT_DWARF_UNWIND requires _LIBUNWIND_SUPPORT_DWARF_INDEX on this platform."
-#endif
 #endif
 
   return false;