diff options
author | Christophe Lyon <christophe.lyon@st.com> | 2013-01-18 15:08:04 +0100 |
---|---|---|
committer | Waldemar Brodkorb <wbrodkorb@conet.de> | 2018-08-10 16:01:58 +0200 |
commit | 5ec586eb37f61e57f19ac60b58af61f167ca054a (patch) | |
tree | 6c72d03d43e76a33eb5d6360d9bdb2573a048c42 /ldso/ldso/arm/elfinterp.c | |
parent | f88bb681ba22d77a19abfb4c1617c826298ed473 (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.c | 85 |
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 |