OSDN Git Service

Patch from Stefan Allius and Edie C. Dost to add SuperH
[uclinux-h8/uClibc.git] / ldso / ldso / arm / elfinterp.c
index 39f29d6..dd68324 100644 (file)
-/* Run an ELF binary on a linux system.
-
-   Copyright (C) 1993, Eric Youngdale.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
-\f
-#ifndef VERBOSE_DLINKER
-#define VERBOSE_DLINKER
-#endif
-#ifdef VERBOSE_DLINKER
-static const char *_dl_reltypes[] =
-       { "R_ARM_NONE", "R_ARM_PC24", "R_ARM_ABS32", "R_ARM_REL32",
-       "R_ARM_PC13", "R_ARM_ABS16", "R_ARM_ABS12", "R_ARM_THM_ABS5",
-       "R_ARM_ABS8", "R_ARM_SBREL32", "R_ARM_THM_PC22", "R_ARM_THM_PC8",
-       "R_ARM_AMP_VCALL9", "R_ARM_SWI24", "R_ARM_THM_SWI8", "R_ARM_XPC25",
-       "R_ARM_THM_XPC22", "R_ARM_COPY", "R_ARM_GLOB_DAT", "R_ARM_JUMP_SLOT",
-       "R_ARM_RELATIVE", "R_ARM_GOTOFF", "R_ARM_GOTPC", "R_ARM_GOT32",
-       "R_ARM_PLT32", "R_ARM_ALU_PCREL_7_0", "R_ARM_ALU_PCREL_15_8",
-       "R_ARM_ALU_PCREL_23_15", "R_ARM_LDR_SBREL_11_0", "R_ARM_ALU_SBREL_19_12",
-       "R_ARM_ALU_SBREL_27_20", "R_ARM_GNU_VTENTRY", "R_ARM_GNU_VTINHERIT",
-       "R_ARM_THM_PC11", "R_ARM_THM_PC9", "R_ARM_RXPC25", "R_ARM_RSBREL32",
-       "R_ARM_THM_RPC22", "R_ARM_RREL32", "R_ARM_RABS22", "R_ARM_RPC24",
-       "R_ARM_RBASE", "R_ARM_NUM"
+/* vi: set sw=4 ts=4: */
+/* ARM ELF shared library loader suppport
+ *
+ * Copyright (C) 2001-2002, Erik Andersen
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined (SUPPORT_LD_DEBUG) || defined (LD_DEBUG_SYMBOLS)
+static const char *_dl_reltypes_tab[] =
+  [0]  "R_ARM_NONE",       "R_ARM_PC24",       "R_ARM_ABS32",          "R_ARM_REL32",
+  [4]  "R_ARM_PC13",       "R_ARM_ABS16",      "R_ARM_ABS12",          "R_ARM_THM_ABS5",
+  [8]  "R_ARM_ABS8",           "R_ARM_SBREL32","R_ARM_THM_PC22",       "R_ARM_THM_PC8",
+  [12] "R_ARM_AMP_VCALL9",     "R_ARM_SWI24",  "R_ARM_THM_SWI8",       "R_ARM_XPC25",
+  [16] "R_ARM_THM_XPC22",
+  [20] "R_ARM_COPY",           "R_ARM_GLOB_DAT","R_ARM_JUMP_SLOT",     "R_ARM_RELATIVE",
+  [24] "R_ARM_GOTOFF",         "R_ARM_GOTPC",   "R_ARM_GOT32",         "R_ARM_PLT32",
+  [32] "R_ARM_ALU_PCREL_7_0","R_ARM_ALU_PCREL_15_8","R_ARM_ALU_PCREL_23_15","R_ARM_LDR_SBREL_11_0",
+  [36] "R_ARM_ALU_SBREL_19_12","R_ARM_ALU_SBREL_27_20",
+  [100]        "R_ARM_GNU_VTENTRY","R_ARM_GNU_VTINHERIT","R_ARM_THM_PC11","R_ARM_THM_PC9",
+  [249] "R_ARM_RXPC25", "R_ARM_RSBREL32", "R_ARM_THM_RPC22", "R_ARM_RREL32",
+  [253] "R_ARM_RABS22", "R_ARM_RPC24", "R_ARM_RBASE",
 };
+
+static const char *
+_dl_reltypes(int type)
+{
+  static char buf[22];  
+  const char *str;
+  
+  if (type >= (sizeof (_dl_reltypes_tab)/sizeof(_dl_reltypes_tab[0])) ||
+      NULL == (str = _dl_reltypes_tab[type]))
+  {
+    str =_dl_simple_ltoa( buf, (unsigned long)(type));
+  }
+  return str;
+}
+
+static 
+void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index)
+{
+  if(_dl_debug_symbols)
+  {
+    if(symtab_index){
+      _dl_dprintf(_dl_debug_file, "\n%s\tvalue=%x\tsize=%x\tinfo=%x\tother=%x\tshndx=%x",
+                 strtab + symtab[symtab_index].st_name,
+                 symtab[symtab_index].st_value,
+                 symtab[symtab_index].st_size,
+                 symtab[symtab_index].st_info,
+                 symtab[symtab_index].st_other,
+                 symtab[symtab_index].st_shndx);
+    }
+  }
+}
+
+static void debug_reloc(Elf32_Sym *symtab,char *strtab, ELF_RELOC *rpnt)
+{
+  if(_dl_debug_reloc)
+  {
+    int symtab_index;
+    const char *sym;
+    symtab_index = ELF32_R_SYM(rpnt->r_info);
+    sym = symtab_index ? strtab + symtab[symtab_index].st_name : "sym=0x0";
+    
+#ifdef ELF_USES_RELOCA
+    _dl_dprintf(_dl_debug_file, "\n%s\toffset=%x\taddend=%x %s",
+               _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
+               rpnt->r_offset,
+               rpnt->r_addend,
+               sym);
+#else
+    _dl_dprintf(_dl_debug_file, "\n%s\toffset=%x %s",
+               _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
+               rpnt->r_offset,
+               sym);
+#endif
+  }
+}
 #endif
 
 /* Program to load an ELF binary on a linux system, and run it.
@@ -47,22 +110,21 @@ static const char *_dl_reltypes[] =
    a more than adequate job of explaining everything required to get this
    working. */
 
-
 extern int _dl_linux_resolve(void);
 
 unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
 {
        int reloc_type;
-       Elf32_Rel *this_reloc;
+       ELF_RELOC *this_reloc;
        char *strtab;
        Elf32_Sym *symtab;
-       Elf32_Rel *rel_addr;
+       ELF_RELOC *rel_addr;
        int symtab_index;
        char *new_addr;
        char **got_addr;
        unsigned long instr_addr;
 
-       rel_addr = (Elf32_Rel *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
+       rel_addr = (ELF_RELOC *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
 
        this_reloc = rel_addr + (reloc_entry >> 3);
        reloc_type = ELF32_R_TYPE(this_reloc->r_info);
@@ -71,92 +133,114 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
        symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
        strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
 
+
        if (reloc_type != R_ARM_JUMP_SLOT) {
-         _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", 
-                      _dl_progname);
-         _dl_exit(1);
+               _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", 
+                       _dl_progname);
+               _dl_exit(1);
        };
-       
+
        /* Address of jump instruction to fix up */
        instr_addr = ((unsigned long) this_reloc->r_offset + 
-                       (unsigned long) tpnt->loadaddr);
+               (unsigned long) tpnt->loadaddr);
        got_addr = (char **) instr_addr;
 
-#ifdef DL_DEBUG_SYMBOLS
-       _dl_dprintf(2, "Resolving symbol %s\n", 
-               strtab + symtab[symtab_index].st_name);
-#endif
-
        /* Get the address of the GOT entry */
        new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, 
-               tpnt->symbol_scope, tpnt, 0);
+               tpnt->symbol_scope, tpnt, resolver);
        if (!new_addr) {
                _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
                        _dl_progname, strtab + symtab[symtab_index].st_name);
                _dl_exit(1);
        };
-#ifdef DL_NEVER_FIXUP_SYMBOLS
-       if ((unsigned long) got_addr < 0x40000000) {
-               _dl_dprintf(2, "Calling library function: %s\n", 
+#if defined (SUPPORT_LD_DEBUG) || defined (LD_NEVER_FIXUP_SYMBOLS)
+       if ((unsigned long) got_addr < 0x40000000)
+       {
+#ifndef SUPPORT_LD_DEBUG
+          if (_dl_debug_bindings)
+         {
+           _dl_dprintf(_dl_debug_file, "\nresolve function: %s",
                        strtab + symtab[symtab_index].st_name);
+           if(_dl_debug_detail) _dl_dprintf(_dl_debug_file, "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr);
+         }
+#endif   
+#ifndef LD_NEVER_FIXUP_SYMBOLS
+         *got_addr = new_addr;
+#endif         
        } else {
-               *got_addr = new_addr;
+         *got_addr = new_addr;
        }
 #else
        *got_addr = new_addr;
 #endif
+
        return (unsigned long) new_addr;
 }
 
-void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt, 
-       unsigned long rel_addr, unsigned long rel_size, int type)
+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))
 {
        int i;
        char *strtab;
-       int reloc_type;
-       int symtab_index;
+       int goof = 0;
        Elf32_Sym *symtab;
-       Elf32_Rel *rpnt;
-       unsigned long *reloc_addr;
-
+       ELF_RELOC *rpnt;
+       int symtab_index;
        /* Now parse the relocation information */
-       rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
-       rel_size = rel_size / sizeof(Elf32_Rel);
 
-       symtab =
-               (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
+       rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
+       rel_size = rel_size / sizeof(ELF_RELOC);
+
+       symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
        strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
 
-       for (i = 0; i < rel_size; i++, rpnt++) {
-               reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
-               reloc_type = ELF32_R_TYPE(rpnt->r_info);
+         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))
+                   _dl_symbol(strtab + symtab[symtab_index].st_name))
                        continue;
 
-               switch (reloc_type) {
-               case R_ARM_NONE:
-                       break;
-               case R_ARM_JUMP_SLOT:
-                       *reloc_addr += (unsigned long) tpnt->loadaddr;
-                       break;
-               default:
-                       _dl_dprintf(2, "%s: (LAZY) can't handle reloc type ", 
-                               _dl_progname);
-#ifdef VERBOSE_DLINKER
-                       _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
+#if defined (SUPPORT_LD_DEBUG) || defined (LD_DEBUG_SYMBOLS)
+               debug_sym(symtab,strtab,symtab_index);
+               debug_reloc(symtab,strtab,rpnt);
 #endif
-                       if (symtab_index)
-                               _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
-                       _dl_exit(1);
-               };
-       };
+
+               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 '%s'\n");
+                       goof += res;
+               }
+         }
+         return goof;
 }
 
 static unsigned long
@@ -183,58 +267,40 @@ fix_bad_pc24 (unsigned long *const reloc_addr, unsigned long value)
   return (unsigned long)fix_address;
 }
 
-
-int _dl_parse_relocation_information(struct elf_resolve *tpnt, 
-       unsigned long rel_addr, unsigned long rel_size, int type)
+static int
+_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
+             ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
-       int i;
-       char *strtab;
        int reloc_type;
-       int goof = 0;
-       Elf32_Sym *symtab;
-       Elf32_Rel *rpnt;
+       int symtab_index;
        unsigned long *reloc_addr;
        unsigned long symbol_addr;
-       int symtab_index;
-
-       /* Now parse the relocation information */
+       int goof = 0;
 
-       rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
-       rel_size = rel_size / sizeof(Elf32_Rel);
+       reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+       reloc_type = ELF32_R_TYPE(rpnt->r_info);
+       symtab_index = ELF32_R_SYM(rpnt->r_info);
+       symbol_addr = 0;
 
-       symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
-       strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+       if (symtab_index) {
 
-       for (i = 0; i < rel_size; i++, rpnt++) {
-               reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
-               reloc_type = ELF32_R_TYPE(rpnt->r_info);
-               symtab_index = ELF32_R_SYM(rpnt->r_info);
-               symbol_addr = 0;
+               symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, 
+                               scope, (reloc_type == R_ARM_JUMP_SLOT ? tpnt : NULL), symbolrel);
 
-               if (!symtab_index && tpnt->libtype == program_interpreter)
-                       continue;
-
-               if (symtab_index) {
-
-                       if (tpnt->libtype == program_interpreter &&
-                                       _dl_symbol(strtab + symtab[symtab_index].st_name))
-                               continue;
-
-                       symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, 
-                                       tpnt->symbol_scope,
-                                       (reloc_type == R_ARM_JUMP_SLOT ? tpnt : NULL), 0);
-
-                       /*
-                        * 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 && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
-                               _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
-                                               _dl_progname, strtab + symtab[symtab_index].st_name);
-                               goof++;
-                       }
+               /*
+                * 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 && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
+                       goof++;
                }
+       }
+
+#if defined (SUPPORT_LD_DEBUG)
+       {
+               unsigned long old_val = *reloc_addr;
+#endif
                switch (reloc_type) {
                        case R_ARM_NONE:
                                break;
@@ -286,19 +352,50 @@ int _dl_parse_relocation_information(struct elf_resolve *tpnt,
 #endif
                                break;
                        default:
-                               _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
-#ifdef VERBOSE_DLINKER
-                               _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
+                               return -1; /*call _dl_exit(1) */
+               }
+#if defined (SUPPORT_LD_DEBUG)
+               if(_dl_debug_reloc && _dl_debug_detail)
+                       _dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
+       }
+
 #endif
-                               if (symtab_index)
-                                       _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
-                               _dl_exit(1);
-               };
 
-       };
        return goof;
 }
 
+static int
+_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
+                  ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
+{
+       int reloc_type;
+       unsigned long *reloc_addr;
+
+       reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+       reloc_type = ELF32_R_TYPE(rpnt->r_info);
+
+#if defined (SUPPORT_LD_DEBUG)
+       {
+               unsigned long old_val = *reloc_addr;
+#endif
+               switch (reloc_type) {
+                       case R_ARM_NONE:
+                               break;
+                       case R_ARM_JUMP_SLOT:
+                               *reloc_addr += (unsigned long) tpnt->loadaddr;
+                               break;
+                       default:
+                               return -1; /*call _dl_exit(1) */
+               }
+#if defined (SUPPORT_LD_DEBUG)
+               if(_dl_debug_reloc && _dl_debug_detail)
+                       _dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
+       }
+
+#endif
+       return 0;
+
+}
 
 /* This is done as a separate step, because there are cases where
    information is first copied and later initialized.  This results in
@@ -308,59 +405,60 @@ int _dl_parse_relocation_information(struct elf_resolve *tpnt,
 
 /* No, there are cases where the SVr4 linker fails to emit COPY relocs
    at all */
-
-int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr, 
-       unsigned long rel_size, int type)
+static int
+_dl_do_copy (struct elf_resolve *tpnt, struct dyn_elf *scope,
+            ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
 {
-       int i;
-       char *strtab;
-       int reloc_type;
-       int goof = 0;
-       Elf32_Sym *symtab;
-       Elf32_Rel *rpnt;
+        int reloc_type;
+       int symtab_index;
        unsigned long *reloc_addr;
        unsigned long symbol_addr;
-       struct elf_resolve *tpnt;
-       int symtab_index;
-
-       /* Now parse the relocation information */
+       int goof = 0;
+         
+       reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+       reloc_type = ELF32_R_TYPE(rpnt->r_info);
+       if (reloc_type != R_ARM_COPY) 
+               return 0;
+       symtab_index = ELF32_R_SYM(rpnt->r_info);
+       symbol_addr = 0;
+               
+       if (symtab_index) {
+
+               symbol_addr = (unsigned long) _dl_find_hash(strtab + 
+                       symtab[symtab_index].st_name, 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",
+                            strtab + symtab[symtab_index].st_name,
+                            symtab[symtab_index].st_size,
+                            symbol_addr, symtab[symtab_index].st_value);
+#endif
+               _dl_memcpy((char *) symtab[symtab_index].st_value, 
+                       (char *) symbol_addr, symtab[symtab_index].st_size);
+       }
 
-       tpnt = xpnt->dyn;
+       return goof;
+}
 
-       rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
-       rel_size = rel_size / sizeof(Elf32_Rel);
+void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt, 
+       unsigned long rel_addr, unsigned long rel_size, int type)
+{
+  (void)_dl_parse(tpnt, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
 
-       symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
-       strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+int _dl_parse_relocation_information(struct elf_resolve *tpnt, 
+       unsigned long rel_addr, unsigned long rel_size, int type)
+{
+  return _dl_parse(tpnt, tpnt->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+}
 
-       for (i = 0; i < rel_size; i++, rpnt++) {
-               reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
-               reloc_type = ELF32_R_TYPE(rpnt->r_info);
-               if (reloc_type != R_ARM_COPY)
-                       continue;
-               symtab_index = ELF32_R_SYM(rpnt->r_info);
-               symbol_addr = 0;
-               if (!symtab_index && tpnt->libtype == program_interpreter)
-                       continue;
-               if (symtab_index) {
-
-                       if (tpnt->libtype == program_interpreter &&
-                               _dl_symbol(strtab + symtab[symtab_index].st_name))
-                               continue;
-
-                       symbol_addr = (unsigned long) _dl_find_hash(strtab + 
-                               symtab[symtab_index].st_name, xpnt->next, 
-                               NULL, 1);
-                       if (!symbol_addr) {
-                               _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
-                                       _dl_progname, strtab + symtab[symtab_index].st_name);
-                               goof++;
-                       };
-               };
-               if (!goof) {
-                       _dl_memcpy((char *) symtab[symtab_index].st_value, 
-                               (char *) symbol_addr, symtab[symtab_index].st_size);
-               }
-       };
-       return goof;
+int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr, 
+       unsigned long rel_size, int type)
+{
+  return _dl_parse(xpnt->dyn, xpnt->next, rel_addr, rel_size, _dl_do_copy);
 }
+