summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/arm/find_exidx.c
diff options
context:
space:
mode:
authorChristophe Lyon <christophe.lyon@st.com>2013-01-18 15:08:04 +0100
committerWaldemar Brodkorb <wbrodkorb@conet.de>2018-08-10 16:01:58 +0200
commit5ec586eb37f61e57f19ac60b58af61f167ca054a (patch)
tree6c72d03d43e76a33eb5d6360d9bdb2573a048c42 /libc/sysdeps/linux/arm/find_exidx.c
parentf88bb681ba22d77a19abfb4c1617c826298ed473 (diff)
rtld: Add FDPIC code for arm
Add FDPIC dynamic relocations support, similar to what other FDPIC targets do. Lazy binding is implemented in a folllow-up patch. Disable the SEND* macros because they involve relocations to access constant strings that are unsupported by the existing arm version. Define DL_START, START, ARCH_NEEDS_BOOTSTRAP_RELOCS, DL_CHECK_LIB_TYPE similarly to what other FDPIC targets do. Define raise() because _dl_find_hash references __aeabi_uidivmod, which uses __aeabi_idiv0 which in turn references raise. * include/elf.h (R_ARM_FUNCDESC): Define. (R_ARM_FUNCDESC_VALUE): Define. * ldso/include/dl-string.h (SEND_STDERR, SEND_ADDRESS_STDERR) (SEND_NUMBER_STDERR): Define empty for __FDPIC__. * ldso/ldso/arm/dl-inlines.h: New file. * ldso/ldso/arm/dl-startup.h (PERFORM_BOOTSTRAP_RELOC): Fix type of load_addr. Fix handling of R_ARM_RELATIVE, add support for R_ARM_FUNCDESC_VALUE. (DL_START, START): Define for __FDPIC__. (raise): Define. * ldso/ldso/arm/dl-sysdep.h (ARCH_NEEDS_BOOTSTRAP_RELOCS): Define. (DL_CHECK_LIB_TYPE): Define. (elf_machine_type_class): Take into account FDPIC related relocations. (elf_machine_load_address): Support __FDPIC__. (elf_machine_relative): Likewise. * ldso/ldso/arm/elfinterp.c (_dl_linux_resolver): Dummy support for __FDPIC__, implemented in a later patch. (_dl_do_reloc): Fix reloc_adr computation for __FDPIC__, fix handling of local symbols. Fix handling of R_ARM_RELATIVE, add support for R_ARM_FUNCDESC_VALUE, R_ARM_FUNCDESC. * ldso/ldso/arm/resolve.S: Make _dl_linux_resolve hidden. * ldso/ldso/fdpic/dl-inlines.h (htab_delete): Declare. * libc/sysdeps/linux/arm/bits/elf-fdpic.h: New file, similar to bfin's. * libc/sysdeps/linux/arm/crtreloc.c: Likewise. * libc/sysdeps/linux/arm/find_exidx.c (__dl_addr_in_loadaddr) Define. (find_exidx_callback): Support __FDPIC__. Signed-off-by: Mickaël Guêné <mickael.guene@st.com> Signed-off-by: Christophe Lyon <christophe.lyon@st.com>
Diffstat (limited to 'libc/sysdeps/linux/arm/find_exidx.c')
-rw-r--r--libc/sysdeps/linux/arm/find_exidx.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/libc/sysdeps/linux/arm/find_exidx.c b/libc/sysdeps/linux/arm/find_exidx.c
index 679d90c05..cd4d442cf 100644
--- a/libc/sysdeps/linux/arm/find_exidx.c
+++ b/libc/sysdeps/linux/arm/find_exidx.c
@@ -18,6 +18,23 @@
#include <link.h>
#include <unwind.h>
+#if __FDPIC__
+#include <bits/elf-fdpic.h>
+static __always_inline int
+__dl_addr_in_loadaddr(void *p, struct elf32_fdpic_loadaddr loadaddr)
+{
+ struct elf32_fdpic_loadmap *map = loadaddr.map;
+ int c;
+
+ for (c = 0; c < map->nsegs; c++)
+ if ((void *)map->segs[c].addr <= p &&
+ (char *)p < (char *)map->segs[c].addr + map->segs[c].p_memsz)
+ return 1;
+
+ return 0;
+}
+#endif
+
struct unw_eh_callback_data
{
_Unwind_Ptr pc;
@@ -32,6 +49,26 @@ struct unw_eh_callback_data
static int
find_exidx_callback (struct dl_phdr_info * info, size_t size, void * ptr)
{
+#if __FDPIC__
+ struct unw_eh_callback_data * data;
+ const ElfW(Phdr) *phdr;
+ int i;
+ int match = 0;
+
+ data = (struct unw_eh_callback_data *) ptr;
+ if (__dl_addr_in_loadaddr((void *) data->pc, info->dlpi_addr)) {
+ match = 1;
+ phdr = info->dlpi_phdr;
+ for (i = info->dlpi_phnum; i > 0; i--, phdr++) {
+ if (phdr->p_type == PT_ARM_EXIDX) {
+ data->exidx_start = (_Unwind_Ptr) __RELOC_POINTER(phdr->p_vaddr, info->dlpi_addr);
+ data->exidx_len = phdr->p_memsz;
+ }
+ }
+ }
+
+ return match;
+#else
struct unw_eh_callback_data * data;
const ElfW(Phdr) *phdr;
int i;
@@ -59,6 +96,7 @@ find_exidx_callback (struct dl_phdr_info * info, size_t size, void * ptr)
}
return match;
+#endif
}