OSDN Git Service

Joakim Tjernlund writes:
authorEric Andersen <andersen@codepoet.org>
Fri, 30 Jan 2004 20:34:03 +0000 (20:34 -0000)
committerEric Andersen <andersen@codepoet.org>
Fri, 30 Jan 2004 20:34:03 +0000 (20:34 -0000)
> Not there yet, but the interfaces are much closer now...
> Heading to bed though, since its 5:30am.  :-)

This works, but I discovered something "funny". For all
relocs but COPY you can use scope instead of scope->dyn->symbol_scope
and it is much faster to do that. Search for "Funny" in the patch
to see what I mean. Probably I probably broke something, please let me
know if it works for you too.

I think I am done with ldso now. Has been fun and I hope to
actually use uClibc/busybox soon in a project.

Ohh, there is one thing left, double sized PLT entries, but maybe these
aren't needed in uClibc?

 Sweet dreams
              Jocke

ldso/ldso/powerpc/elfinterp.c

index 6352961..c930f71 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2001-2002 David A. Schleef
  * Copyright (C) 2003-2004 Erik Andersen
+ * Copyright (C) 2004 Joakim Tjernlund
  *
  * All rights reserved.
  *
@@ -251,72 +252,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
        return finaladdr;
 }
 
-static int
-_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
-         unsigned long rel_addr, unsigned long rel_size,
-         int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
-                           ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
-{
-       unsigned int i;
-       char *strtab;
-       Elf32_Sym *symtab;
-       ELF_RELOC *rpnt;
-       int symtab_index;
-
-       /* Now parse the relocation information */
-       rpnt = (ELF_RELOC *)(intptr_t) (rel_addr + tpnt->loadaddr);
-       rel_size = rel_size / sizeof(ELF_RELOC);
-
-       symtab = (Elf32_Sym *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
-       strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
-
-         for (i = 0; i < rel_size; i++, rpnt++) {
-               int res;
-
-               symtab_index = ELF32_R_SYM(rpnt->r_info);
-
-               /* When the dynamic linker bootstrapped itself, it resolved some symbols.
-                  Make sure we do not do them again */
-               if (!symtab_index && tpnt->libtype == program_interpreter)
-                       continue;
-               if (symtab_index && tpnt->libtype == program_interpreter &&
-                   _dl_symbol(strtab + symtab[symtab_index].st_name))
-                       continue;
-
-#if defined (__SUPPORT_LD_DEBUG__)
-               debug_sym(symtab,strtab,symtab_index);
-               debug_reloc(symtab,strtab,rpnt);
-#endif
-
-               res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
-
-               if (res==0) continue;
-
-               _dl_dprintf(2, "\n%s: ",_dl_progname);
-
-               if (symtab_index)
-                 _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
-
-               if (res <0)
-               {
-                       int reloc_type = ELF32_R_TYPE(rpnt->r_info);
-#if defined (__SUPPORT_LD_DEBUG__)
-                       _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
-#else
-                       _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
-#endif
-                       _dl_exit(-res);
-               }
-               else if (res >0)
-               {
-                       _dl_dprintf(2, "can't resolve symbol\n");
-                       return res;
-               }
-         }
-         return 0;
-}
-
-static int
+static inline int
 _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
              ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
@@ -325,6 +261,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
        char *symname;
        Elf32_Addr *reloc_addr;
        Elf32_Addr finaladdr;
+       struct dyn_elf *sym_scope;
 
        unsigned long symbol_addr;
 #if defined (__SUPPORT_LD_DEBUG__)
@@ -336,13 +273,22 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
                *reloc_addr = tpnt->loadaddr + rpnt->r_addend;
                return 0;
        }
-       if (reloc_type == R_PPC_NONE || reloc_type == R_PPC_COPY) /*  R_PPC_COPY is handled later */
+       if (reloc_type == R_PPC_NONE)
                return 0;
        symtab_index = ELF32_R_SYM(rpnt->r_info);
        symname      = strtab + symtab[symtab_index].st_name;
-
-       symbol_addr = (unsigned long) _dl_find_hash(symname, scope,
-                                                   (reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL), symbolrel);
+#if 0
+       sym_scope = scope->dyn->symbol_scope;
+#else
+       sym_scope = scope;/* Funny, this works too and appears to be much faster. */
+#endif
+       if (reloc_type == R_PPC_COPY) {
+               sym_scope = scope->next;
+               tpnt = NULL; /* To be or not to be ...*/
+       }
+       symbol_addr = (unsigned long) _dl_find_hash(symname, sym_scope,
+                                                   (reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL),
+                                                   (reloc_type == R_PPC_COPY ? copyrel : symbolrel));
        /*
         * We want to allow undefined references to weak symbols - this might
         * have been intentional.  We should not be linking local symbols
@@ -398,7 +344,6 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
                break;
        }
        case R_PPC_COPY:
-               /* This does not work yet, R_PPC_COPY is handled later, see if statemet above */
                if (symbol_addr) {
 #if defined (__SUPPORT_LD_DEBUG__)
                        if(_dl_debug_move)
@@ -423,7 +368,8 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
        {
                Elf32_Sword delta = finaladdr - (Elf32_Word)reloc_addr;
                if(delta<<6>>6 != delta){
-                       _dl_dprintf(2, "%s: symbol '%s' R_PPC_REL24 is out of range.\n\tCompile shared libraries with -fPIC!\n",
+                       _dl_dprintf(2, "%s: symbol '%s' R_PPC_REL24 is out of range.\n\t"
+                                       "Compile shared libraries with -fPIC!\n",
                                    _dl_progname, symname);
                        _dl_exit(1);
                }
@@ -452,48 +398,6 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
        return 0;
 }
 
-/* This is done as a separate step, because there are cases where
-   information is first copied and later initialized.  This results in
-   the wrong information being copied.  Someone at Sun was complaining about
-   a bug in the handling of _COPY by SVr4, and this may in fact be what he
-   was talking about.  Sigh. */
-static int
-_dl_do_copy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
-            ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
-{
-       int reloc_type;
-       int symtab_index;
-       unsigned long *reloc_addr;
-       unsigned long symbol_addr;
-       int goof = 0;
-       char *symname;
-
-       reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
-       reloc_type = ELF32_R_TYPE(rpnt->r_info);
-       if (reloc_type != R_PPC_COPY)
-               return 0;
-       symtab_index = ELF32_R_SYM(rpnt->r_info);
-       symbol_addr = 0;
-       symname      = strtab + symtab[symtab_index].st_name;
-
-       if (symtab_index) {
-               symbol_addr = (unsigned long) _dl_find_hash(symname, scope, NULL, copyrel);
-               if (!symbol_addr) goof++;
-       }
-       if (!goof) {
-#if defined (__SUPPORT_LD_DEBUG__)
-               if(_dl_debug_move)
-                 _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x",
-                            symname, symtab[symtab_index].st_size,
-                            symbol_addr, symtab[symtab_index].st_value);
-#endif
-                       _dl_memcpy((char *) reloc_addr,
-                                       (char *) (symbol_addr + (unsigned long)rpnt->r_addend), symtab[symtab_index].st_size);
-       }
-
-       return goof;
-}
-
 void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
        unsigned long rel_addr, unsigned long rel_size, int type)
 {
@@ -538,16 +442,82 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
        PPC_ISYNC;
 }
 
+static inline int
+_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+         unsigned long rel_addr, unsigned long rel_size,
+         int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
+                           ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
+{
+       unsigned int i;
+       char *strtab;
+       Elf32_Sym *symtab;
+       ELF_RELOC *rpnt;
+       int symtab_index;
+
+       /* Now parse the relocation information */
+       rpnt = (ELF_RELOC *)(intptr_t) (rel_addr + tpnt->loadaddr);
+       rel_size = rel_size / sizeof(ELF_RELOC);
+
+       symtab = (Elf32_Sym *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
+       strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+
+         for (i = 0; i < rel_size; i++, rpnt++) {
+               int res;
+
+               symtab_index = ELF32_R_SYM(rpnt->r_info);
+
+               /* When the dynamic linker bootstrapped itself, it resolved some symbols.
+                  Make sure we do not do them again */
+               if (!symtab_index && tpnt->libtype == program_interpreter)
+                       continue;
+               if (symtab_index && tpnt->libtype == program_interpreter &&
+                   _dl_symbol(strtab + symtab[symtab_index].st_name))
+                       continue;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+               debug_sym(symtab,strtab,symtab_index);
+               debug_reloc(symtab,strtab,rpnt);
+#endif
+
+               res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
+
+               if (res==0) continue;
+
+               _dl_dprintf(2, "\n%s: ",_dl_progname);
+
+               if (symtab_index)
+                 _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
+
+               if (res <0)
+               {
+                       int reloc_type = ELF32_R_TYPE(rpnt->r_info);
+#if defined (__SUPPORT_LD_DEBUG__)
+                       _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
+#else
+                       _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
+#endif
+                       _dl_exit(-res);
+               }
+               else if (res >0)
+               {
+                       _dl_dprintf(2, "can't resolve symbol\n");
+                       return res;
+               }
+         }
+         return 0;
+}
+
 int _dl_parse_relocation_information(struct dyn_elf *rpnt,
        unsigned long rel_addr, unsigned long rel_size, int type)
 {
-       return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+       return _dl_parse(rpnt->dyn, rpnt, rel_addr, rel_size, _dl_do_reloc);
 }
 
+/* Should be a static inline instead, but that conflicts with ld_elf.h */
 int _dl_parse_copy_information(struct dyn_elf *rpnt,
        unsigned long rel_addr, unsigned long rel_size, int type)
 {
-       return _dl_parse(rpnt->dyn, rpnt->next, rel_addr, rel_size, _dl_do_copy_reloc);
+       /* Not used! */
+       return 0;
 }
 
-