[libunwind] r296991 - Drop the dependency on dl_unwind_find_exidx().
Ed Schouten via cfe-commits
cfe-commits at lists.llvm.org
Sun Mar 5 11:11:24 PST 2017
Author: ed
Date: Sun Mar 5 13:11:24 2017
New Revision: 296991
URL: http://llvm.org/viewvc/llvm-project?rev=296991&view=rev
Log:
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. This approach 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.
This change is identical to r295944, except that it now adds the
necessary code to do bounds checking on PT_LOAD. The previous version of
this change lacked this, which didn't cause any problems on CloudABI,
but did break the Linux build bots. This is why I reverted it in
r295948.
Differential Revision: https://reviews.llvm.org/D30306
Modified:
libunwind/trunk/src/AddressSpace.hpp
Modified: libunwind/trunk/src/AddressSpace.hpp
URL: http://llvm.org/viewvc/llvm-project/libunwind/trunk/src/AddressSpace.hpp?rev=296991&r1=296990&r2=296991&view=diff
==============================================================================
--- libunwind/trunk/src/AddressSpace.hpp (original)
+++ libunwind/trunk/src/AddressSpace.hpp Sun Mar 5 13:11:24 2017
@@ -35,29 +35,17 @@ namespace libunwind {
#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 @@ inline bool LocalAddressSpace::findUnwin
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,7 +375,6 @@ inline bool LocalAddressSpace::findUnwin
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;
@@ -413,6 +392,11 @@ inline bool LocalAddressSpace::findUnwin
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;
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 +426,27 @@ inline bool LocalAddressSpace::findUnwin
} 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_LOAD) {
+ uintptr_t begin = pinfo->dlpi_addr + 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 = pinfo->dlpi_addr + phdr->p_vaddr;
+ cbdata->sects->arm_section = exidx_start;
+ cbdata->sects->arm_section_length = phdr->p_memsz /
+ sizeof(EHTEntry);
+ found_hdr = true;
+ }
+ }
+ return found_obj && found_hdr;
+ #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;
More information about the cfe-commits
mailing list