]> Git Repo - uclibc-ng.git/commitdiff
rtld: Add lazy binding support
authorChristophe Lyon <[email protected]>
Thu, 28 Mar 2013 09:46:55 +0000 (10:46 +0100)
committerWaldemar Brodkorb <[email protected]>
Fri, 10 Aug 2018 14:02:45 +0000 (16:02 +0200)
Add support for R_ARM_FUNCDESC_VALUE and implement _dl_linux_resolver
for FDPIC on ARM.

* ldso/ldso/arm/elfinterp.c (_dl_linux_resolver): Support __FDPIC__.
(_dl_do_lazy_reloc): Likewise.
* ldso/ldso/arm/resolve.S (_dl_linux_resolve): Likewise.

Signed-off-by: Mickaël Guêné <[email protected]>
Signed-off-by: Christophe Lyon <[email protected]>
ldso/ldso/arm/elfinterp.c
ldso/ldso/arm/resolve.S

index 402ba961864e2bd352889d503f3879aeaee99cd8..1d79d925b6f58fd1c9d2f58822cd5afa51415a48 100644 (file)
 
 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;
+unsigned long _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_offet)
+{
+       ELF_RELOC *this_reloc;
+       char *strtab;
+       ElfW(Sym) *symtab;
+       int symtab_index;
+       char *rel_addr;
+       char *new_addr;
+       struct funcdesc_value funcval;
+       struct funcdesc_value volatile *got_entry;
+       char *symname;
+       struct symbol_ref sym_ref;
+
+       rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
+
+       this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_offet);
+       symtab_index = ELF_R_SYM(this_reloc->r_info);
+
+       symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
+       strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+       sym_ref.sym = &symtab[symtab_index];
+       sym_ref.tpnt = NULL;
+       symname= strtab + symtab[symtab_index].st_name;
+
+       /* Address of GOT entry fix up */
+       got_entry = (struct funcdesc_value *) DL_RELOC_ADDR(tpnt->loadaddr, this_reloc->r_offset);
+
+       /* Get the address to be used to fill in the GOT entry.  */
+       new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, NULL, 0, &sym_ref);
+       if (!new_addr) {
+               new_addr = _dl_find_hash(symname, NULL, NULL, 0, &sym_ref);
+               if (!new_addr) {
+                       _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
+                       _dl_exit(1);
+               }
+       }
+
+       funcval.entry_point = new_addr;
+       funcval.got_value = sym_ref.tpnt->loadaddr.got_value;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+       if (_dl_debug_bindings) {
+               _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+               if (_dl_debug_detail)
+                       _dl_dprintf(_dl_debug_file,
+                                   "\n\tpatched (%x,%x) ==> (%x,%x) @ %x\n",
+                                   got_entry->entry_point, got_entry->got_value,
+                                   funcval.entry_point, funcval.got_value,
+                                   got_entry);
+       }
+       if (1 || !_dl_debug_nofixups) {
+               *got_entry = funcval;
+       }
+#else
+       *got_entry = funcval;
+#endif
+
+       return got_entry;
+}
 #else
+unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+{
        ELF_RELOC *this_reloc;
        char *strtab;
        char *symname;
@@ -93,8 +149,8 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 #endif
 
        return new_addr;
-#endif
 }
+#endif
 
 static int
 _dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
@@ -348,7 +404,7 @@ _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
        int reloc_type;
        unsigned long *reloc_addr;
 
-       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);
 
 #if defined (__SUPPORT_LD_DEBUG__)
@@ -358,9 +414,20 @@ _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope,
                switch (reloc_type) {
                        case R_ARM_NONE:
                                break;
+
                        case R_ARM_JUMP_SLOT:
-                               *reloc_addr += (unsigned long) tpnt->loadaddr;
+                               *reloc_addr = DL_RELOC_ADDR(tpnt->loadaddr, *reloc_addr);
+                               break;
+#ifdef __FDPIC__
+                       case R_ARM_FUNCDESC_VALUE:
+                               {
+                                       struct funcdesc_value *dst = (struct funcdesc_value *) reloc_addr;
+
+                                       dst->entry_point = DL_RELOC_ADDR(tpnt->loadaddr, dst->entry_point);
+                                       dst->got_value = tpnt->loadaddr.got_value;
+                               }
                                break;
+#endif
                        default:
                                return -1; /*call _dl_exit(1) */
                }
index 2a516436eb7c7897f413fe8fad8fb4ff7d1926cd..039a6b78872c5a8e6bf88cdf8d9a9d74235799c0 100644 (file)
  .type _dl_linux_resolve,%function
  .align 4;
 
+#if __FDPIC__
+/*
+ *    _dl_linux_resolve() FDPIC version receives the following parameters from
+ *    lazy PLT entry:
+ *    R12: GOT address for the resolver GOT
+ *    SP[0]: funcdesc_value_reloc_offset(foo)
+ *    R9: GOT address for the caller GOT
+ *    _dl_linux_resolver() will return a function descriptor address in R0.
+ */
+_dl_linux_resolve:
+       push  {r0, r1, r2, r3, r14}
+       ldr   r0, [r9, #8]
+       ldr   r1, [sp, #20]
+       mov   r9, r12
+       blx   _dl_linux_resolver
+       ldr   r9, [r0, #4]
+       ldr   r12, [r0]
+       pop   {r0, r1, r2, r3, r14}
+       add   sp, sp, #4
+       bx    r12
+#else
 _dl_linux_resolve:
          @ _dl_linux_resolver is a standard subroutine call, therefore it
          @ preserves everything except r0-r3 (a1-a4), ip and lr.  This
@@ -129,6 +150,7 @@ _dl_linux_resolve:
         ldmia sp!, {r0, r1, r2, r3, r4, lr}
 
         BX(ip)
+#endif /* __FDPIC__ */
 #else
        @ In the thumb case _dl_linux_resolver is thumb.  If a bl is used
        @ from arm code the linker will insert a stub call which, with
This page took 0.032251 seconds and 4 git commands to generate.