summaryrefslogtreecommitdiff
path: root/ldso/ldso/arm/elfinterp.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 /ldso/ldso/arm/elfinterp.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 'ldso/ldso/arm/elfinterp.c')
-rw-r--r--ldso/ldso/arm/elfinterp.c85
1 files changed, 64 insertions, 21 deletions
diff --git a/ldso/ldso/arm/elfinterp.c b/ldso/ldso/arm/elfinterp.c
index 96809a9ae..402ba9618 100644
--- a/ldso/ldso/arm/elfinterp.c
+++ b/ldso/ldso/arm/elfinterp.c
@@ -36,6 +36,11 @@ extern int _dl_linux_resolve(void);
unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
{
+#if __FDPIC__
+ /* FIXME: implement. */
+ while(1) ;
+ return 0;
+#else
ELF_RELOC *this_reloc;
char *strtab;
char *symname;
@@ -88,6 +93,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
#endif
return new_addr;
+#endif
}
static int
@@ -181,7 +187,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct r_scope_elem *scope,
struct elf_resolve *def_mod = 0;
int goof = 0;
- reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+ reloc_addr = (unsigned long *) DL_RELOC_ADDR(tpnt->loadaddr, rpnt->r_offset);
reloc_type = ELF_R_TYPE(rpnt->r_info);
symtab_index = ELF_R_SYM(rpnt->r_info);
@@ -191,25 +197,30 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct r_scope_elem *scope,
symname = strtab + symtab[symtab_index].st_name;
if (symtab_index) {
- symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt,
- elf_machine_type_class(reloc_type), &sym_ref);
-
- /*
- * We want to allow undefined references to weak symbols - this might
- * have been intentional. We should not be linking local symbols
- * here, so all bases should be covered.
- */
- if (!symbol_addr && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS)
- && (ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) {
- /* This may be non-fatal if called from dlopen. */
- return 1;
-
- }
- if (_dl_trace_prelink) {
- _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
- &sym_ref, elf_machine_type_class(reloc_type));
+ if (ELF_ST_BIND (symtab[symtab_index].st_info) == STB_LOCAL) {
+ symbol_addr = (unsigned long) DL_RELOC_ADDR(tpnt->loadaddr, symtab[symtab_index].st_value);
+ def_mod = tpnt;
+ } else {
+ symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt,
+ elf_machine_type_class(reloc_type), &sym_ref);
+
+ /*
+ * We want to allow undefined references to weak symbols - this might
+ * have been intentional. We should not be linking local symbols
+ * here, so all bases should be covered.
+ */
+ if (!symbol_addr && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS)
+ && (ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) {
+ /* This may be non-fatal if called from dlopen. */
+ return 1;
+
+ }
+ if (_dl_trace_prelink) {
+ _dl_debug_lookup (symname, tpnt, &symtab[symtab_index],
+ &sym_ref, elf_machine_type_class(reloc_type));
+ }
+ def_mod = sym_ref.tpnt;
}
- def_mod = sym_ref.tpnt;
} else {
/*
* Relocs against STN_UNDEF are usually treated as using a
@@ -267,12 +278,42 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct r_scope_elem *scope,
*reloc_addr = symbol_addr;
break;
case R_ARM_RELATIVE:
- *reloc_addr += (unsigned long) tpnt->loadaddr;
+ *reloc_addr = DL_RELOC_ADDR(tpnt->loadaddr, *reloc_addr);
break;
case R_ARM_COPY:
_dl_memcpy((void *) reloc_addr,
(void *) symbol_addr, symtab[symtab_index].st_size);
break;
+#ifdef __FDPIC__
+ case R_ARM_FUNCDESC_VALUE:
+ {
+ struct funcdesc_value funcval;
+ struct funcdesc_value *dst = (struct funcdesc_value *) reloc_addr;
+
+ funcval.entry_point = (void*)symbol_addr;
+ /* Add offset to section address for local symbols. */
+ if (ELF_ST_BIND(symtab[symtab_index].st_info) == STB_LOCAL)
+ funcval.entry_point += *reloc_addr;
+ funcval.got_value = def_mod->loadaddr.got_value;
+ *dst = funcval;
+ }
+ break;
+ case R_ARM_FUNCDESC:
+ {
+ unsigned long reloc_value = *reloc_addr;
+
+ if (symbol_addr)
+ reloc_value = (unsigned long) _dl_funcdesc_for(symbol_addr + reloc_value, sym_ref.tpnt->loadaddr.got_value);
+ else
+ /* Relocation against an
+ undefined weak symbol:
+ set funcdesc to zero. */
+ reloc_value = 0;
+
+ *reloc_addr = reloc_value;
+ }
+ break;
+#endif
#if defined USE_TLS && USE_TLS
case R_ARM_TLS_DTPMOD32:
*reloc_addr = def_mod->l_tls_modid;
@@ -330,7 +371,6 @@ _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
#endif
return 0;
-
}
void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
@@ -345,3 +385,6 @@ int _dl_parse_relocation_information(struct dyn_elf *rpnt,
return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc);
}
+#ifndef IS_IN_libdl
+# include "../../libc/sysdeps/linux/arm/crtreloc.c"
+#endif