aboutsummaryrefslogtreecommitdiff
path: root/libunwind
diff options
context:
space:
mode:
authorEd Schouten <ed@nuxi.nl>2017-03-05 19:11:24 +0000
committerEd Schouten <ed@nuxi.nl>2017-03-05 19:11:24 +0000
commitfa1ef7d89cb4034536fecee06c64bb68cbfbc623 (patch)
treed50c4fb3da91910c18d2ead9fd62d162a679fe0f /libunwind
parent71db98c66534915623372a199d9bc11fe40daeff (diff)
downloadllvm-fa1ef7d89cb4034536fecee06c64bb68cbfbc623.zip
llvm-fa1ef7d89cb4034536fecee06c64bb68cbfbc623.tar.gz
llvm-fa1ef7d89cb4034536fecee06c64bb68cbfbc623.tar.bz2
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 llvm-svn: 296991
Diffstat (limited to 'libunwind')
-rw-r--r--libunwind/src/AddressSpace.hpp61
1 files changed, 30 insertions, 31 deletions
diff --git a/libunwind/src/AddressSpace.hpp b/libunwind/src/AddressSpace.hpp
index f0091fc..2229de5 100644
--- a/libunwind/src/AddressSpace.hpp
+++ b/libunwind/src/AddressSpace.hpp
@@ -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::findUnwindSections(pint_t targetAddr,
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::findUnwindSections(pint_t targetAddr,
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::findUnwindSections(pint_t targetAddr,
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::findUnwindSections(pint_t targetAddr,
} 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;