summaryrefslogtreecommitdiff
path: root/ldso
diff options
context:
space:
mode:
Diffstat (limited to 'ldso')
-rw-r--r--ldso/ldso/Makefile34
-rw-r--r--ldso/ldso/arm/boot1_arch.h2
-rw-r--r--ldso/ldso/arm/dl-startup.h2
-rw-r--r--ldso/ldso/arm/elfinterp.c468
-rw-r--r--ldso/ldso/dl-elf.c96
-rw-r--r--ldso/ldso/dl-hash.c82
-rw-r--r--ldso/ldso/hash.c82
-rw-r--r--ldso/ldso/i386/boot1_arch.h2
-rw-r--r--ldso/ldso/i386/dl-startup.h2
-rw-r--r--ldso/ldso/i386/elfinterp.c494
-rw-r--r--ldso/ldso/ld_hash.h26
-rw-r--r--ldso/ldso/ld_string.h26
-rw-r--r--ldso/ldso/ld_syscall.h10
-rw-r--r--ldso/ldso/ldso.c288
-rw-r--r--ldso/ldso/m68k/boot1_arch.h2
-rw-r--r--ldso/ldso/m68k/dl-startup.h2
-rw-r--r--ldso/ldso/m68k/elfinterp.c60
-rw-r--r--ldso/ldso/mips/boot1_arch.h2
-rw-r--r--ldso/ldso/mips/dl-startup.h2
-rw-r--r--ldso/ldso/mips/elfinterp.c69
-rw-r--r--ldso/ldso/powerpc/boot1_arch.h2
-rw-r--r--ldso/ldso/powerpc/dl-startup.h2
-rw-r--r--ldso/ldso/powerpc/elfinterp.c56
-rw-r--r--ldso/ldso/readelflib1.c96
-rw-r--r--ldso/ldso/sh/boot1_arch.h23
-rw-r--r--ldso/ldso/sh/dl-startup.h23
-rw-r--r--ldso/ldso/sh/dl-syscalls.h7
-rw-r--r--ldso/ldso/sh/dl-sysdep.h145
-rw-r--r--ldso/ldso/sh/elfinterp.c416
-rw-r--r--ldso/ldso/sh/ld_syscalls.h7
-rw-r--r--ldso/ldso/sh/ld_sysdep.h145
-rw-r--r--ldso/ldso/sh/resolve.S69
-rw-r--r--ldso/ldso/sparc/boot1_arch.h2
-rw-r--r--ldso/ldso/sparc/dl-startup.h2
-rw-r--r--ldso/ldso/sparc/elfinterp.c56
35 files changed, 2065 insertions, 737 deletions
diff --git a/ldso/ldso/Makefile b/ldso/ldso/Makefile
index 4100f82ff..ff1d9ea48 100644
--- a/ldso/ldso/Makefile
+++ b/ldso/ldso/Makefile
@@ -31,13 +31,35 @@ LDSO_FULLNAME=ld-uClibc-$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBLEVEL).so
# (i.e. where the shared library loader does all the heavy lifting)
# Since this currently only saves about 300 bytes, I'm going to leave
# it enabled...
-XXFLAGS+= -DDL_TRACE
+XXFLAGS+= -DLD_TRACE
-# Enable this to enable debugging output from ld.so
-#XXFLAGS+= -DDL_DEBUG
-#XXFLAGS+= -DDL_DEBUG_SYMBOLS
-#Enable this to never actually fixup symbols so you can watch each call...
-#XXFLAGS+= -DDL_NEVER_FIXUP_SYMBOLS
+# Enable this to enable all the code needed for debugging the runtime
+# linking of an application using the LD_DEBUG environment variable:
+# LD_DEBUG=token1,token2,.. prog
+# enables diagnostics to the stderr.
+# For now there are these tokens possible:
+# bindings displays the resolve processing (function calls); detail shows the relocation patch
+# detail provide more information for some options
+# move display copy processings
+# reloc display relocation processing; detail shows the relocation patch
+# symbols display symbol table processing
+#
+# The additional environment variable:
+# LD_DEBUG_OUTPUT=file
+# redirects the diagnostics to an output file created using
+# the specified name and the process id as a suffix.
+#
+# try this
+# $ LD_DEBUG=binding,move,symbols,reloc,detail LD_DEBUG_OUTPUT=appname ./appname
+#
+#XXFLAGS+= -DSUPPORT_LD_DEBUG
+
+# Enable this for the very very early debugging. Really only useful
+# for people porting to new architectures.
+#XXFLAGS+= -DLD_DEBUG
+
+# Enable this to never actually fixup symbols...
+#XXFLAGS+= -DLD_NEVER_FIXUP_SYMBOLS
XXFLAGS+=-DUCLIBC_TARGET_PREFIX=\"$(TARGET_PREFIX)\" \
-DUCLIBC_DEVEL_PREFIX=\"$(DEVEL_PREFIX)\" \
diff --git a/ldso/ldso/arm/boot1_arch.h b/ldso/ldso/arm/boot1_arch.h
index e4c9bafb7..af9acc22c 100644
--- a/ldso/ldso/arm/boot1_arch.h
+++ b/ldso/ldso/arm/boot1_arch.h
@@ -20,7 +20,7 @@ _dl_boot:
");
#define _dl_boot _dl_boot2
-#define DL_BOOT(X) static void * __attribute__ ((unused)) _dl_boot (X)
+#define LD_BOOT(X) static void * __attribute__ ((unused)) _dl_boot (X)
/* It seems ARM needs an offset here */
diff --git a/ldso/ldso/arm/dl-startup.h b/ldso/ldso/arm/dl-startup.h
index e4c9bafb7..af9acc22c 100644
--- a/ldso/ldso/arm/dl-startup.h
+++ b/ldso/ldso/arm/dl-startup.h
@@ -20,7 +20,7 @@ _dl_boot:
");
#define _dl_boot _dl_boot2
-#define DL_BOOT(X) static void * __attribute__ ((unused)) _dl_boot (X)
+#define LD_BOOT(X) static void * __attribute__ ((unused)) _dl_boot (X)
/* It seems ARM needs an offset here */
diff --git a/ldso/ldso/arm/elfinterp.c b/ldso/ldso/arm/elfinterp.c
index 39f29d634..dd68324a5 100644
--- a/ldso/ldso/arm/elfinterp.c
+++ b/ldso/ldso/arm/elfinterp.c
@@ -1,39 +1,102 @@
-/* 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. */
-
-#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);
}
+
diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
index c5e7607e0..8c2314184 100644
--- a/ldso/ldso/dl-elf.c
+++ b/ldso/ldso/dl-elf.c
@@ -1,21 +1,34 @@
-/* Load an ELF sharable library into memory.
-
- Copyright (C) 1993-1996, 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. */
-
+/* vi: set sw=4 ts=4: */
+/* Program to load an ELF binary on a linux system, and run it
+ * after resolving ELF shared library symbols
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * 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.
+ */
/* This file contains the helper routines to load an ELF sharable
@@ -180,8 +193,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
pnt++;
}
-#ifdef DL_DEBUG
- _dl_dprintf(2, "searching for library: '%s'\n", libname);
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "searching for library: '%s'\n", libname);
#endif
/* If the filename has any '/', try it straight and leave it at that.
For IBCS2 compatibility under linux, we substitute the string
@@ -204,8 +217,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
if (pnt) {
pnt += (unsigned long) tpnt->loadaddr +
tpnt->dynamic_info[DT_STRTAB];
-#ifdef DL_DEBUG
- _dl_dprintf(2, "searching RPATH: '%s'\n", pnt);
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "searching RPATH: '%s'\n", pnt);
#endif
if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL)
{
@@ -217,8 +230,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
/* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */
if (_dl_library_path) {
-#ifdef DL_DEBUG
- _dl_dprintf(2, "searching _dl_library_path: '%s'\n", _dl_library_path);
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "searching _dl_library_path: '%s'\n", _dl_library_path);
#endif
if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL)
{
@@ -251,8 +264,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
/* Look for libraries wherever the shared library loader
* was installed */
-#ifdef DL_DEBUG
- _dl_dprintf(2, "searching in ldso dir: %s\n", _dl_ldsopath);
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "searching in ldso dir: %s\n", _dl_ldsopath);
#endif
if ((tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt)) != NULL)
{
@@ -262,8 +275,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
/* Lastly, search the standard list of paths for the library.
This list must exactly match the list in uClibc/ldso/util/ldd.c */
-#ifdef DL_DEBUG
- _dl_dprintf(2, "searching full lib path list\n");
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "searching full lib path list\n");
#endif
if ((tpnt1 = search_for_named_library(libname, secure,
UCLIBC_TARGET_PREFIX "/usr/lib:"
@@ -282,8 +295,8 @@ goof:
if (_dl_internal_error_number)
_dl_error_number = _dl_internal_error_number;
else
- _dl_error_number = DL_ERROR_NOFILE;
-#ifdef DL_DEBUG
+ _dl_error_number = LD_ERROR_NOFILE;
+#ifdef LD_DEBUG
_dl_dprintf(2, "Bummer: could not find '%s'!\n", libname);
#endif
return NULL;
@@ -323,6 +336,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
(*rpnt)->next = (struct dyn_elf *)
_dl_malloc(sizeof(struct dyn_elf));
_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
+ (*rpnt)->next->prev = (*rpnt);
*rpnt = (*rpnt)->next;
(*rpnt)->dyn = tpnt;
tpnt->symbol_scope = _dl_symbol_tables;
@@ -352,7 +366,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
*/
_dl_dprintf(2, "%s: can't open '%s'\n", _dl_progname, libname);
#endif
- _dl_internal_error_number = DL_ERROR_NOFILE;
+ _dl_internal_error_number = LD_ERROR_NOFILE;
return NULL;
}
@@ -365,7 +379,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
{
_dl_dprintf(2, "%s: '%s' is not an ELF file\n", _dl_progname,
libname);
- _dl_internal_error_number = DL_ERROR_NOTELF;
+ _dl_internal_error_number = LD_ERROR_NOTELF;
_dl_close(infile);
return NULL;
};
@@ -377,7 +391,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
))
{
_dl_internal_error_number =
- (epnt->e_type != ET_DYN ? DL_ERROR_NOTDYN : DL_ERROR_NOTMAGIC);
+ (epnt->e_type != ET_DYN ? LD_ERROR_NOTDYN : LD_ERROR_NOTMAGIC);
_dl_dprintf(2, "%s: '%s' is not an ELF executable for " ELF_TARGET
"\n", _dl_progname, libname);
_dl_close(infile);
@@ -424,7 +438,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0);
if (_dl_mmap_check_error(status)) {
_dl_dprintf(2, "%s: can't map %s\n", _dl_progname, libname);
- _dl_internal_error_number = DL_ERROR_MMAP_FAILED;
+ _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
_dl_close(infile);
return NULL;
};
@@ -457,7 +471,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
if (_dl_mmap_check_error(status)) {
_dl_dprintf(2, "%s: can't map '%s'\n",
_dl_progname, libname);
- _dl_internal_error_number = DL_ERROR_MMAP_FAILED;
+ _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
_dl_munmap((char *) libaddr, maxvma - minvma);
_dl_close(infile);
return NULL;
@@ -488,7 +502,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
infile, ppnt->p_offset & OFFS_ALIGN);
if (_dl_mmap_check_error(status)) {
_dl_dprintf(2, "%s: can't map '%s'\n", _dl_progname, libname);
- _dl_internal_error_number = DL_ERROR_MMAP_FAILED;
+ _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
_dl_munmap((char *) libaddr, maxvma - minvma);
_dl_close(infile);
return NULL;
@@ -516,7 +530,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
/* Start by scanning the dynamic section to get all of the pointers */
if (!dynamic_addr) {
- _dl_internal_error_number = DL_ERROR_NODYNAMIC;
+ _dl_internal_error_number = LD_ERROR_NODYNAMIC;
_dl_dprintf(2, "%s: '%s' is missing a dynamic section\n",
_dl_progname, libname);
return NULL;
@@ -580,6 +594,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
(*rpnt)->next = (struct dyn_elf *)
_dl_malloc(sizeof(struct dyn_elf));
_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
+ (*rpnt)->next->prev = (*rpnt);
*rpnt = (*rpnt)->next;
(*rpnt)->dyn = tpnt;
tpnt->symbol_scope = _dl_symbol_tables;
@@ -626,6 +641,10 @@ int _dl_copy_fixups(struct dyn_elf *rpnt)
return goof;
tpnt->init_flag |= COPY_RELOCS_DONE;
+#if defined (SUPPORT_LD_DEBUG)
+ if(_dl_debug) _dl_dprintf(_dl_debug_file,"\nrelocation copy fixups: %s", tpnt->libname);
+#endif
+
#ifdef ELF_USES_RELOCA
goof += _dl_parse_copy_information(rpnt,
tpnt->dynamic_info[DT_RELA], tpnt->dynamic_info[DT_RELASZ], 0);
@@ -635,5 +654,8 @@ int _dl_copy_fixups(struct dyn_elf *rpnt)
tpnt->dynamic_info[DT_RELSZ], 0);
#endif
+#if defined (SUPPORT_LD_DEBUG)
+ if(_dl_debug) _dl_dprintf(_dl_debug_file,"\nrelocation copy fixups: %s; finished\n\n", tpnt->libname);
+#endif
return goof;
}
diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c
index b063d0b79..5711bebaa 100644
--- a/ldso/ldso/dl-hash.c
+++ b/ldso/ldso/dl-hash.c
@@ -1,21 +1,34 @@
-/* Run an ELF binary on a linux system.
-
- Copyright (C) 1993-1996, 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. */
-
+/* vi: set sw=4 ts=4: */
+/* Program to load an ELF binary on a linux system, and run it
+ * after resolving ELF shared library symbols
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * 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.
+ */
/* Various symbol table handling functions, including symbol lookup */
@@ -150,7 +163,7 @@ struct elf_resolve *_dl_add_elf_hash_table(char *libname,
*/
char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
- struct elf_resolve *f_tpnt, int copyrel)
+ struct elf_resolve *f_tpnt, enum caller_type caller_type)
{
struct elf_resolve *tpnt;
int si;
@@ -172,7 +185,7 @@ char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
that any shared library data symbols referenced in the executable
will be seen at the same address by the executable, shared libraries
and dynamically loaded code. -Rob Ryan (robr@cmu.edu) */
- if (!copyrel && rpnt1) {
+ if (copyrel!=caller_type && rpnt1) {
first = (*_dl_symbol_tables);
first.next = rpnt1;
rpnt1 = (&first);
@@ -247,11 +260,12 @@ char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
pnt = strtab + symtab[si].st_name;
if (_dl_strcmp(pnt, name) == 0 &&
- (ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC ||
- ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE ||
- ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) &&
- symtab[si].st_value != 0 &&
- symtab[si].st_shndx != 0) {
+ symtab[si].st_value != 0)
+ {
+ if ((ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC ||
+ ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE ||
+ ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) &&
+ symtab[si].st_shndx != SHN_UNDEF) {
/* Here we make sure that we find a module where the symbol is
* actually defined.
@@ -284,6 +298,24 @@ char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
default: /* Do local symbols need to be examined? */
break;
}
+ }
+ /*
+ * References to the address of a function from an executable file and
+ * the shared objects associated with it might not resolve to the same
+ * value. To allow comparisons of function addresses we must resolve
+ * to the address of the plt entry of the executable instead of the
+ * real function address.
+ * see "TIS ELF Specification Version 1.2, Book 3, A-11 (Function
+ * Adresses)
+ */
+ if (resolver != caller_type &&
+ NULL==f_tpnt && /*trick: don't handle R_??_JMP_SLOT reloc type*/
+ tpnt->libtype == elf_executable &&
+ ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC &&
+ symtab[si].st_shndx == SHN_UNDEF)
+ {
+ return (char*)symtab[si].st_value;
+ }
}
}
}
diff --git a/ldso/ldso/hash.c b/ldso/ldso/hash.c
index b063d0b79..5711bebaa 100644
--- a/ldso/ldso/hash.c
+++ b/ldso/ldso/hash.c
@@ -1,21 +1,34 @@
-/* Run an ELF binary on a linux system.
-
- Copyright (C) 1993-1996, 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. */
-
+/* vi: set sw=4 ts=4: */
+/* Program to load an ELF binary on a linux system, and run it
+ * after resolving ELF shared library symbols
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * 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.
+ */
/* Various symbol table handling functions, including symbol lookup */
@@ -150,7 +163,7 @@ struct elf_resolve *_dl_add_elf_hash_table(char *libname,
*/
char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
- struct elf_resolve *f_tpnt, int copyrel)
+ struct elf_resolve *f_tpnt, enum caller_type caller_type)
{
struct elf_resolve *tpnt;
int si;
@@ -172,7 +185,7 @@ char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
that any shared library data symbols referenced in the executable
will be seen at the same address by the executable, shared libraries
and dynamically loaded code. -Rob Ryan (robr@cmu.edu) */
- if (!copyrel && rpnt1) {
+ if (copyrel!=caller_type && rpnt1) {
first = (*_dl_symbol_tables);
first.next = rpnt1;
rpnt1 = (&first);
@@ -247,11 +260,12 @@ char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
pnt = strtab + symtab[si].st_name;
if (_dl_strcmp(pnt, name) == 0 &&
- (ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC ||
- ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE ||
- ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) &&
- symtab[si].st_value != 0 &&
- symtab[si].st_shndx != 0) {
+ symtab[si].st_value != 0)
+ {
+ if ((ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC ||
+ ELF32_ST_TYPE(symtab[si].st_info) == STT_NOTYPE ||
+ ELF32_ST_TYPE(symtab[si].st_info) == STT_OBJECT) &&
+ symtab[si].st_shndx != SHN_UNDEF) {
/* Here we make sure that we find a module where the symbol is
* actually defined.
@@ -284,6 +298,24 @@ char *_dl_find_hash(char *name, struct dyn_elf *rpnt1,
default: /* Do local symbols need to be examined? */
break;
}
+ }
+ /*
+ * References to the address of a function from an executable file and
+ * the shared objects associated with it might not resolve to the same
+ * value. To allow comparisons of function addresses we must resolve
+ * to the address of the plt entry of the executable instead of the
+ * real function address.
+ * see "TIS ELF Specification Version 1.2, Book 3, A-11 (Function
+ * Adresses)
+ */
+ if (resolver != caller_type &&
+ NULL==f_tpnt && /*trick: don't handle R_??_JMP_SLOT reloc type*/
+ tpnt->libtype == elf_executable &&
+ ELF32_ST_TYPE(symtab[si].st_info) == STT_FUNC &&
+ symtab[si].st_shndx == SHN_UNDEF)
+ {
+ return (char*)symtab[si].st_value;
+ }
}
}
}
diff --git a/ldso/ldso/i386/boot1_arch.h b/ldso/ldso/i386/boot1_arch.h
index 2f8fe1357..cd1f016a6 100644
--- a/ldso/ldso/i386/boot1_arch.h
+++ b/ldso/ldso/i386/boot1_arch.h
@@ -4,4 +4,4 @@
* can be done.
*/
-#define DL_BOOT(X) void _dl_boot (X)
+#define LD_BOOT(X) void _dl_boot (X)
diff --git a/ldso/ldso/i386/dl-startup.h b/ldso/ldso/i386/dl-startup.h
index 2f8fe1357..cd1f016a6 100644
--- a/ldso/ldso/i386/dl-startup.h
+++ b/ldso/ldso/i386/dl-startup.h
@@ -4,4 +4,4 @@
* can be done.
*/
-#define DL_BOOT(X) void _dl_boot (X)
+#define LD_BOOT(X) void _dl_boot (X)
diff --git a/ldso/ldso/i386/elfinterp.c b/ldso/ldso/i386/elfinterp.c
index 3c9979e49..4bfa349e8 100644
--- a/ldso/ldso/i386/elfinterp.c
+++ b/ldso/ldso/i386/elfinterp.c
@@ -1,31 +1,96 @@
-/* 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. */
-
-#ifndef VERBOSE_DLINKER
-#define VERBOSE_DLINKER
-#endif
-#ifdef VERBOSE_DLINKER
-static const char *_dl_reltypes[] =
- { "R_386_NONE", "R_386_32", "R_386_PC32", "R_386_GOT32",
- "R_386_PLT32", "R_386_COPY", "R_386_GLOB_DAT",
- "R_386_JMP_SLOT", "R_386_RELATIVE", "R_386_GOTOFF",
- "R_386_GOTPC", "R_386_NUM"
+/* vi: set sw=4 ts=4: */
+/* i386 ELF shared library loader suppport
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * 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_386_NONE", "R_386_32", "R_386_PC32", "R_386_GOT32",
+ [4] "R_386_PLT32", "R_386_COPY", "R_386_GLOB_DAT", "R_386_JMP_SLOT",
+ [8] "R_386_RELATIVE", "R_386_GOTOFF", "R_386_GOTPC",
};
+
+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.
@@ -44,16 +109,16 @@ 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);
@@ -74,175 +139,211 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
(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_386_NONE:
- break;
- case R_386_JMP_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;
}
-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 */
-
- rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
- rel_size = rel_size / sizeof(Elf32_Rel);
+ int goof = 0;
- symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
- strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+ 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;
- 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;
+ if (symtab_index) {
- if (!symtab_index && tpnt->libtype == program_interpreter)
- continue;
+ symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name,
+ scope, (reloc_type == R_386_JMP_SLOT ? tpnt : NULL), symbolrel);
- 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_386_JMP_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_386_NONE:
- break;
- case R_386_32:
- *reloc_addr += symbol_addr;
- break;
- case R_386_PC32:
- *reloc_addr += symbol_addr - (unsigned long) reloc_addr;
- break;
- case R_386_GLOB_DAT:
- case R_386_JMP_SLOT:
- *reloc_addr = symbol_addr;
- break;
- case R_386_RELATIVE:
- *reloc_addr += (unsigned long) tpnt->loadaddr;
- break;
- case R_386_COPY:
-#if 0
- /* Do this later */
- _dl_dprintf(2, "Doing copy for symbol ");
- if (symtab_index) _dl_dprintf(2, strtab + symtab[symtab_index].st_name);
- _dl_dprintf(2, "\n");
- _dl_memcpy((void *) symtab[symtab_index].st_value,
- (void *) symbol_addr, symtab[symtab_index].st_size);
+ case R_386_NONE:
+ break;
+ case R_386_32:
+ *reloc_addr += symbol_addr;
+ break;
+ case R_386_PC32:
+ *reloc_addr += symbol_addr - (unsigned long) reloc_addr;
+ break;
+ case R_386_GLOB_DAT:
+ case R_386_JMP_SLOT:
+ *reloc_addr = symbol_addr;
+ break;
+ case R_386_RELATIVE:
+ *reloc_addr += (unsigned long) tpnt->loadaddr;
+ break;
+ case R_386_COPY:
+#if 0
+ /* Do this later */
+ _dl_dprintf(2, "Doing copy for symbol ");
+ if (symtab_index) _dl_dprintf(2, strtab + symtab[symtab_index].st_name);
+ _dl_dprintf(2, "\n");
+ _dl_memcpy((void *) symtab[symtab_index].st_value,
+ (void *) symbol_addr, symtab[symtab_index].st_size);
#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]);
+ 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
- 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_386_NONE:
+ break;
+ case R_386_JMP_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
@@ -252,59 +353,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_386_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_386_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);
}
+
diff --git a/ldso/ldso/ld_hash.h b/ldso/ldso/ld_hash.h
index 639ae4510..b19d680a2 100644
--- a/ldso/ldso/ld_hash.h
+++ b/ldso/ldso/ld_hash.h
@@ -43,6 +43,7 @@ struct dyn_elf{
struct elf_resolve * dyn;
struct dyn_elf * next_handle; /* Used by dlopen et al. */
struct dyn_elf * next;
+ struct dyn_elf * prev;
};
struct elf_resolve{
@@ -113,8 +114,11 @@ extern struct elf_resolve * _dl_check_hashed_files(char * libname);
extern struct elf_resolve * _dl_add_elf_hash_table(char * libname,
char * loadaddr, unsigned long * dynamic_info,
unsigned long dynamic_addr, unsigned long dynamic_size);
+
+enum caller_type{symbolrel=0,copyrel=1,resolver=2};
extern char * _dl_find_hash(char * name, struct dyn_elf * rpnt1,
- struct elf_resolve * f_tpnt, int copyrel);
+ struct elf_resolve * f_tpnt, enum caller_type);
+
extern int _dl_linux_dynamic_link(void);
extern char * _dl_library_path;
@@ -129,16 +133,16 @@ static inline int _dl_symbol(char * name)
}
-#define DL_ERROR_NOFILE 1
-#define DL_ERROR_NOZERO 2
-#define DL_ERROR_NOTELF 3
-#define DL_ERROR_NOTMAGIC 4
-#define DL_ERROR_NOTDYN 5
-#define DL_ERROR_MMAP_FAILED 6
-#define DL_ERROR_NODYNAMIC 7
-#define DL_WRONG_RELOCS 8
-#define DL_BAD_HANDLE 9
-#define DL_NO_SYMBOL 10
+#define LD_ERROR_NOFILE 1
+#define LD_ERROR_NOZERO 2
+#define LD_ERROR_NOTELF 3
+#define LD_ERROR_NOTMAGIC 4
+#define LD_ERROR_NOTDYN 5
+#define LD_ERROR_MMAP_FAILED 6
+#define LD_ERROR_NODYNAMIC 7
+#define LD_WRONG_RELOCS 8
+#define LD_BAD_HANDLE 9
+#define LD_NO_SYMBOL 10
diff --git a/ldso/ldso/ld_string.h b/ldso/ldso/ld_string.h
index e2b1f28c3..1de9f8d76 100644
--- a/ldso/ldso/ld_string.h
+++ b/ldso/ldso/ld_string.h
@@ -17,6 +17,7 @@ static int _dl_strcmp(const char * s1,const char * s2);
static int _dl_strncmp(const char * s1,const char * s2,size_t len);
static char * _dl_strchr(const char * str,int c);
static char *_dl_strrchr(const char *str, int c);
+static char *_dl_strstr(const char *s1, const char *s2);
static void * _dl_memcpy(void * dst, const void * src, size_t len);
static int _dl_memcmp(const void * s1,const void * s2,size_t len);
static void *_dl_memset(void * str,int c,size_t len);
@@ -122,6 +123,29 @@ static inline char *_dl_strrchr(const char *str, int c)
return(prev);
}
+
+static inline char *_dl_strstr(const char *s1, const char *s2)
+{
+ register const char *s = s1;
+ register const char *p = s2;
+
+ do {
+ if (!*p) {
+ return (char *) s1;;
+ }
+ if (*p == *s) {
+ ++p;
+ ++s;
+ } else {
+ p = s2;
+ if (!*s) {
+ return NULL;
+ }
+ s = ++s1;
+ }
+ } while (1);
+}
+
static inline void * _dl_memcpy(void * dst, const void * src, size_t len)
{
register char *a = dst;
@@ -221,7 +245,7 @@ static inline char *_dl_simple_ltoahex(char * local, unsigned long i)
}
-#if defined mc68000 || defined __arm__ || defined __mips__
+#if defined mc68000 || defined __arm__ || defined __mips__ || defined __sh__
/* On some arches constant strings are referenced through the GOT. */
/* XXX Requires load_addr to be defined. */
#define SEND_STDERR(X) \
diff --git a/ldso/ldso/ld_syscall.h b/ldso/ldso/ld_syscall.h
index 386756d05..94048cdbd 100644
--- a/ldso/ldso/ld_syscall.h
+++ b/ldso/ldso/ld_syscall.h
@@ -51,8 +51,8 @@ static inline _syscall1(void, _dl_exit, int, status);
static inline _syscall1(int, _dl_close, int, fd);
-#if defined(__powerpc) || defined(__mips__)
-/* PowerPC and MIPS have a different calling convention for mmap(). */
+#if defined(__powerpc) || defined(__mips__) || defined(__sh__)
+/* PowerPC, MIPS and SuperH have a different calling convention for mmap(). */
#define __NR__dl_mmap __NR_mmap
static inline _syscall6(void *, _dl_mmap, void *, start, size_t, length,
int, prot, int, flags, int, fd, off_t, offset);
@@ -91,6 +91,9 @@ static inline void * _dl_mmap(void * addr, unsigned long size, int prot,
#define __NR__dl_open __NR_open
#define O_RDONLY 0x0000
+#define O_WRONLY 01
+#define O_RDWR 02
+#define O_CREAT 0100 /* not fcntl */
static inline _syscall2(int, _dl_open, const char *, fn, int, flags);
#define __NR__dl_write __NR_write
@@ -126,6 +129,9 @@ static inline _syscall0(gid_t, _dl_getgid);
#define __NR__dl_getegid __NR_getegid
static inline _syscall0(gid_t, _dl_getegid);
+#define __NR__dl_getpid __NR_getpid
+static inline _syscall0(gid_t, _dl_getpid);
+
/*
* Not an actual syscall, but we need something in assembly to say whether
* this is OK or not.
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
index ce0b86406..9c94e7e97 100644
--- a/ldso/ldso/ldso.c
+++ b/ldso/ldso/ldso.c
@@ -1,23 +1,33 @@
/* vi: set sw=4 ts=4: */
/* Program to load an ELF binary on a linux system, and run it
* after resolving ELF shared library symbols
- *
- * Copyright (C) 1993-1996, Eric Youngdale.
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
* Copyright (C) 2001-2002, Erik Andersen
*
- * 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.
+ * 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.
*/
/* Enable mprotect protection munging. ARM and MIPS Linux needs this
@@ -27,21 +37,6 @@
// Support a list of library preloads in /etc/ld.so.preload
//#define SUPPORT_LDSO_PRELOAD_FILE
-/* Enable ldd library tracing. Just set LD_TRACE_LOADED_OBJECTS=1 in
- * the environment and run the app to do the ldd thing. With this
- * enabled you can make a simple /usr/bin/ldd shell script as:
- * #!/bin/sh
- * LD_TRACE_LOADED_OBJECTS=1 $1
- * so you can do stuff like:
- * $ ldd ./appname
- * libc.so.0 => /lib/libc.so.0 (0x0x40006000)
- * ld-uClibc.so.0 => /home/andersen/CVS/uClibc/lib/ld-uClibc.so.0 (0x0x40000000)
- * This is off by default since it doesn't work when cross compiling,
- * so uClibc provides an ELF header reading ldd instead...
- */
-//#define DL_TRACE
-
-
/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
I ever taken any courses on internals. This program was developed using
@@ -113,6 +108,12 @@
* housekeeping chores and we can transfer control to the user's
* application.
*/
+#ifdef LD_DEBUG_SYMBOLS
+#ifdef SUPPORT_LD_DEBUG
+#undef SUPPORT_LD_DEBUG
+#endif
+#define SUPPORT_LD_DEBUG
+#endif
#include "ld_syscall.h"
#include "linuxelf.h"
@@ -127,11 +128,11 @@
#define ELFMAGIC ELFMAG
/* This is a poor man's malloc, used prior to resolving our internal poor man's malloc */
-#define DL_MALLOC(SIZE) ((void *) (malloc_buffer += SIZE, malloc_buffer - SIZE)) ; REALIGN();
+#define LD_MALLOC(SIZE) ((void *) (malloc_buffer += SIZE, malloc_buffer - SIZE)) ; REALIGN();
/*
* Make sure that the malloc buffer is aligned on 4 byte boundary. For 64 bit
* platforms we may need to increase this to 8, but this is good enough for
- * now. This is typically called after DL_MALLOC.
+ * now. This is typically called after LD_MALLOC.
*/
#define REALIGN() malloc_buffer = (char *) (((unsigned long) malloc_buffer + 3) & ~(3))
@@ -139,6 +140,17 @@ char *_dl_library_path = 0; /* Where we look for libraries */
char *_dl_preload = 0; /* Things to be loaded before the libs. */
char *_dl_ldsopath = 0;
static char *_dl_not_lazy = 0;
+#ifdef SUPPORT_LD_DEBUG
+static char *_dl_debug = 0;
+static char *_dl_debug_symbols = 0;
+static char *_dl_debug_move = 0;
+static char *_dl_debug_reloc = 0;
+static char *_dl_debug_detail = 0;
+static char *_dl_debug_bindings = 0;
+static int _dl_debug_file = 2;
+#else
+#define _dl_debug_file 2
+#endif
static char *_dl_malloc_addr, *_dl_mmap_zero;
static char *_dl_trace_loaded_objects = 0;
@@ -171,7 +183,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
auxvt[0...N] Auxiliary Vector Table elements (mixed types)
*/
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
/* Debugging is especially tricky on PowerPC, since string literals
* require relocations. Thus, you can't use _dl_dprintf() for
* anything until the bootstrap relocations are finished. */
@@ -192,7 +204,7 @@ static inline void hexprint(unsigned long x)
}
#endif
-DL_BOOT(unsigned long args)
+LD_BOOT(unsigned long args)
{
unsigned int argc;
char **argv, **envp;
@@ -257,14 +269,19 @@ DL_BOOT(unsigned long args)
/* Check the ELF header to make sure everything looks ok. */
if (!header || header->e_ident[EI_CLASS] != ELFCLASS32 ||
header->e_ident[EI_VERSION] != EV_CURRENT
-#if !defined(__powerpc__) && !defined(__mips__)
+#if !defined(__powerpc__) && !defined(__mips__) && !defined(__sh__)
|| _dl_strncmp((void *) header, ELFMAGIC, SELFMAG) != 0
+#else
+ || header->e_ident[EI_MAG0] != ELFMAG0
+ || header->e_ident[EI_MAG1] != ELFMAG1
+ || header->e_ident[EI_MAG2] != ELFMAG2
+ || header->e_ident[EI_MAG3] != ELFMAG3
#endif
) {
SEND_STDERR("Invalid ELF header\n");
_dl_exit(0);
}
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
SEND_STDERR("ELF header=");
SEND_ADDRESS_STDERR(load_addr, 1);
#endif
@@ -286,6 +303,16 @@ DL_BOOT(unsigned long args)
__asm__("\tbl _GLOBAL_OFFSET_TABLE_-4@local\n\t":"=l"(got));
#elif defined(__mips__)
__asm__("\tmove %0, $28\n\tsubu %0,%0,0x7ff0\n\t":"=r"(got));
+#elif defined(__sh__)
+ __asm__("
+ mov.l 1f, %0
+ mova 1f, r0
+ bra 2f
+ add r0, %0
+ .balign 4
+1: .long _GLOBAL_OFFSET_TABLE_
+2:
+" : "=r" (got) : : "r0");
#else
/* Do things the slow way in C */
{
@@ -294,7 +321,7 @@ DL_BOOT(unsigned long args)
Elf32_Shdr *shdr;
Elf32_Phdr *pt_load;
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
SEND_STDERR("Finding the GOT using C code to read the ELF file\n");
#endif
/* Find where the dynamic linking information section is hiding */
@@ -339,7 +366,7 @@ DL_BOOT(unsigned long args)
/* Now, finally, fix up the location of the dynamic stuff */
dpnt = (Elf32_Dyn *) (*got + load_addr);
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
SEND_STDERR("First Dynamic section entry=");
SEND_ADDRESS_STDERR(dpnt, 1);
#endif
@@ -354,15 +381,15 @@ DL_BOOT(unsigned long args)
_dl_exit(13);
}
- tpnt = DL_MALLOC(sizeof(struct elf_resolve));
+ tpnt = LD_MALLOC(sizeof(struct elf_resolve));
_dl_memset(tpnt, 0, sizeof(*tpnt));
- app_tpnt = DL_MALLOC(sizeof(struct elf_resolve));
+ app_tpnt = LD_MALLOC(sizeof(struct elf_resolve));
_dl_memset(app_tpnt, 0, sizeof(*app_tpnt));
/*
* This is used by gdb to locate the chain of shared libraries that are currently loaded.
*/
- debug_addr = DL_MALLOC(sizeof(struct r_debug));
+ debug_addr = LD_MALLOC(sizeof(struct r_debug));
_dl_memset(debug_addr, 0, sizeof(*debug_addr));
/* OK, that was easy. Next scan the DYNAMIC section of the image.
@@ -483,7 +510,7 @@ DL_BOOT(unsigned long args)
/* OK, now do the relocations. We do not do a lazy binding here, so
that once we are done, we have considerably more flexibility. */
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
SEND_STDERR("About to do library loader relocations.\n");
#endif
@@ -541,7 +568,7 @@ DL_BOOT(unsigned long args)
SEND_STDERR(" undefined.\n");
goof++;
}
-#ifdef DL_DEBUG_SYMBOLS
+#ifdef LD_DEBUG_SYMBOLS
SEND_STDERR("About to fixup symbol: ");
SEND_STDERR(strtab + symtab[symtab_index].st_name);
SEND_STDERR("\n");
@@ -557,9 +584,9 @@ DL_BOOT(unsigned long args)
if (goof) {
_dl_exit(14);
}
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
/* Wahoo!!! */
- _dl_dprintf(2, "Done relocating library loader, so we can now\n\tuse globals and make function calls!\n");
+ _dl_dprintf(_dl_debug_file, "Done relocating library loader, so we can now\n\tuse globals and make function calls!\n");
#endif
if (argv[0]) {
@@ -594,9 +621,12 @@ DL_BOOT(unsigned long args)
* Transfer control to the application.
*/
status = 0; /* Used on x86, but not on other arches */
-#ifdef DL_DEBUG
- _dl_dprintf(2, "Calling application main()\n");
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "Calling application main()\n");
#endif
+#if defined (SUPPORT_LD_DEBUG)
+ if(_dl_debug) _dl_dprintf(_dl_debug_file,"\ntransfering control: %s\n\n", _dl_progname);
+#endif
START();
}
@@ -628,8 +658,8 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
tpnt->loadaddr = (char *) load_addr;
INIT_GOT(lpnt, tpnt);
-#ifdef DL_DEBUG
- _dl_dprintf(2, "GOT found at %x\n", tpnt);
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "GOT found at %x\n", lpnt);
#endif
/* OK, this was a big step, now we need to scan all of the user images
and load them properly. */
@@ -728,8 +758,8 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
if (readsize > 0 && readsize < sizeof(buf)-1) {
pnt1 = _dl_strrchr(buf, '/');
if (pnt1 && buf != pnt1) {
-#ifdef DL_DEBUG
- _dl_dprintf(2, "changing tpnt->libname from '%s' to '%s'\n", tpnt->libname, buf);
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "changing tpnt->libname from '%s' to '%s'\n", tpnt->libname, buf);
#endif
tpnt->libname = _dl_strdup(buf);
}
@@ -745,8 +775,8 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
} else {
_dl_ldsopath = tpnt->libname;
}
-#ifdef DL_DEBUG
- _dl_dprintf(2, "Lib Loader:\t(%x) %s\n", tpnt->loadaddr, tpnt->libname);
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "Lib Loader:\t(%x) %s\n", tpnt->loadaddr, tpnt->libname);
#endif
}
}
@@ -774,10 +804,56 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
}
}
+#ifdef SUPPORT_LD_DEBUG
+ _dl_debug = _dl_getenv("LD_DEBUG", envp);
+ if (_dl_debug)
+ {
+ _dl_debug_detail = _dl_strstr(_dl_debug, "detail");
+ _dl_debug_move = _dl_strstr(_dl_debug, "move");
+ _dl_debug_symbols = _dl_strstr(_dl_debug, "sym");
+ _dl_debug_reloc = _dl_strstr(_dl_debug, "reloc");
+ _dl_debug_bindings = _dl_strstr(_dl_debug, "bind");
+ }
+ {
+ const char *dl_debug_output;
+
+ dl_debug_output = _dl_getenv("LD_DEBUG_OUTPUT", envp);
+
+ if (dl_debug_output)
+ {
+ char tmp[22], *tmp1, *filename;
+ int len1, len2;
+
+ _dl_memset(tmp, 0, sizeof(tmp));
+ tmp1=_dl_simple_ltoa( tmp, (unsigned long)_dl_getpid());
+
+ len1 = _dl_strlen(dl_debug_output);
+ len2 = _dl_strlen(tmp1);
+
+ filename = _dl_malloc(len1+len2+2);
+
+ if (filename)
+ {
+ _dl_strcpy (filename, dl_debug_output);
+ filename[len1] = '.';
+ _dl_strcpy (&filename[len1+1], tmp1);
+
+ _dl_debug_file= _dl_open (filename, O_WRONLY|O_CREAT);
+ if (_dl_debug_file<0)
+ {
+ _dl_debug_file = 2;
+ _dl_dprintf (2, "can't open file: '%s'\n",filename);
+ }
+ }
+ }
+ }
+
+
+#endif
_dl_trace_loaded_objects = _dl_getenv("LD_TRACE_LOADED_OBJECTS", envp);
-#ifndef DL_TRACE
+#ifndef LD_TRACE
if (_dl_trace_loaded_objects) {
- _dl_dprintf(2, "Use the ldd provided by uClibc\n");
+ _dl_dprintf(_dl_debug_file, "Use the ldd provided by uClibc\n");
_dl_exit(1);
}
#endif
@@ -809,7 +885,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
{
tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str);
if (!tpnt1) {
-#ifdef DL_TRACE
+#ifdef LD_TRACE
if (_dl_trace_loaded_objects)
_dl_dprintf(1, "\t%s => not found\n", str);
else {
@@ -817,14 +893,14 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
_dl_dprintf(2, "%s: can't load "
"library '%s'\n", _dl_progname, str);
_dl_exit(15);
-#ifdef DL_TRACE
+#ifdef LD_TRACE
}
#endif
} else {
-#ifdef DL_DEBUG
- _dl_dprintf(2, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
#endif
-#ifdef DL_TRACE
+#ifdef LD_TRACE
if (_dl_trace_loaded_objects
&& tpnt1->usage_count==1) {
/* this is a real hack to make ldd not print
@@ -888,7 +964,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2);
if (!tpnt1) {
-#ifdef DL_TRACE
+#ifdef LD_TRACE
if (_dl_trace_loaded_objects)
_dl_dprintf(1, "\t%s => not found\n", cp2);
else {
@@ -896,14 +972,14 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
_dl_dprintf(2, "%s: can't load library '%s'\n",
_dl_progname, cp2);
_dl_exit(15);
-#ifdef DL_TRACE
+#ifdef LD_TRACE
}
#endif
} else {
-#ifdef DL_DEBUG
- _dl_dprintf(2, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
#endif
-#ifdef DL_TRACE
+#ifdef LD_TRACE
if (_dl_trace_loaded_objects
&& tpnt1->usage_count==1) {
_dl_dprintf(1, "\t%s => %s (0x%x)\n", cp2,
@@ -939,7 +1015,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
if (tpnt && _dl_strcmp(lpntstr, _dl_get_last_path_component(tpnt->libname)) == 0) {
struct elf_resolve *ttmp;
-#ifdef DL_TRACE
+#ifdef LD_TRACE
if (_dl_trace_loaded_objects && tpnt->usage_count==1) {
_dl_dprintf(1, "\t%s => %s (0x%x)\n",
lpntstr, tpnt->libname, (unsigned) tpnt->loadaddr);
@@ -954,6 +1030,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
rpnt->next = (struct dyn_elf *)
_dl_malloc(sizeof(struct dyn_elf));
_dl_memset(rpnt->next, 0, sizeof(*(rpnt->next)));
+ rpnt->next->prev = rpnt;
rpnt = rpnt->next;
rpnt->dyn = tpnt;
tpnt->usage_count++;
@@ -963,7 +1040,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
}
if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr)))
{
-#ifdef DL_TRACE
+#ifdef LD_TRACE
if (_dl_trace_loaded_objects)
_dl_dprintf(1, "\t%s => not found\n", lpntstr);
else {
@@ -971,14 +1048,14 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
_dl_dprintf(2, "%s: can't load library '%s'\n",
_dl_progname, lpntstr);
_dl_exit(16);
-#ifdef DL_TRACE
+#ifdef LD_TRACE
}
#endif
} else {
-#ifdef DL_DEBUG
- _dl_dprintf(2, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
#endif
-#ifdef DL_TRACE
+#ifdef LD_TRACE
if (_dl_trace_loaded_objects && tpnt1->usage_count==1)
_dl_dprintf(1, "\t%s => %s (0x%x)\n", lpntstr, tpnt1->libname,
(unsigned) tpnt1->loadaddr);
@@ -993,7 +1070,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
_dl_unmap_cache();
#endif
/* ldd uses uses this. I am not sure how you pick up the other flags */
-#ifdef DL_TRACE
+#ifdef LD_TRACE
if (_dl_trace_loaded_objects) {
char *_dl_warn = 0;
_dl_warn = _dl_getenv("LD_WARN", envp);
@@ -1026,6 +1103,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
rpnt->next =
(struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
_dl_memset(rpnt->next, 0, sizeof(*(rpnt->next)));
+ rpnt->next->prev = rpnt;
rpnt = rpnt->next;
} else {
rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf));
@@ -1034,7 +1112,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
rpnt->dyn = tpnt;
tpnt = NULL;
}
-#ifdef DL_TRACE
+#ifdef LD_TRACE
if (_dl_trace_loaded_objects) {
_dl_dprintf(1, "\t%s => %s (0x%x)\n", rpnt->dyn->libname + (_dl_strlen(_dl_ldsopath)) + 1,
rpnt->dyn->libname, rpnt->dyn->loadaddr);
@@ -1050,8 +1128,8 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
_dl_perform_mips_global_got_relocations(_dl_loaded_modules);
#endif
-#ifdef DL_DEBUG
- _dl_dprintf(2, "Beginning relocation fixups\n");
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "Beginning relocation fixups\n");
#endif
/*
* OK, now all of the kids are tucked into bed in their proper addresses.
@@ -1065,12 +1143,12 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
and we have to manually search for entries that require fixups.
Solaris gets this one right, from what I understand. */
-#ifdef DL_DEBUG
- _dl_dprintf(2, "Beginning copy fixups\n");
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "Beginning copy fixups\n");
#endif
if (_dl_symbol_tables)
goof += _dl_copy_fixups(_dl_symbol_tables);
-#ifdef DL_TRACE
+#ifdef LD_TRACE
if (goof || _dl_trace_loaded_objects)
_dl_exit(0);
#endif
@@ -1083,13 +1161,13 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
up each symbol individually. */
- _dl_brkp = (unsigned long *) _dl_find_hash("___brk_addr", NULL, NULL, 0);
+ _dl_brkp = (unsigned long *) _dl_find_hash("___brk_addr", NULL, NULL, symbolrel);
if (_dl_brkp) {
*_dl_brkp = brk_addr;
}
_dl_envp =
- (unsigned long *) _dl_find_hash("__environ", NULL, NULL, 0);
+ (unsigned long *) _dl_find_hash("__environ", NULL, NULL, symbolrel);
if (_dl_envp) {
*_dl_envp = (unsigned long) envp;
@@ -1113,7 +1191,7 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
}
#endif
- _dl_atexit = (int (*)(void *)) _dl_find_hash("atexit", NULL, NULL, 0);
+ _dl_atexit = (int (*)(void *)) _dl_find_hash("atexit", NULL, NULL, symbolrel);
/*
* OK, fix one more thing - set up the debug_addr structure to point
@@ -1130,33 +1208,48 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
function call. */
((void (*)(void)) debug_addr->r_brk) ();
-#ifdef DL_DEBUG
- _dl_dprintf(2, "Calling init/fini for shared libraries\n");
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "Calling init/fini for shared libraries\n");
#endif
- for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
- /* Apparently crt1 for the application is responsible for handling this.
+
+ for (rpnt = _dl_symbol_tables; rpnt!=NULL&& rpnt->next!=NULL; rpnt=rpnt->next)
+ ;
+
+ for (;rpnt!=NULL; rpnt=rpnt->prev)
+ {
+ tpnt = rpnt->dyn;
+
+ if (tpnt->libtype == program_interpreter)
+ continue;
+
+ /* Apparently crt0/1 for the application is responsible for handling this.
* We only need to run the init/fini for shared libraries
*/
- if (tpnt->libtype == program_interpreter || tpnt->libtype == elf_executable)
- continue;
+ if (tpnt->libtype == elf_executable)
+ break; /* at this point all shared libs are initialized !! */
+
if (tpnt->init_flag & INIT_FUNCS_CALLED)
continue;
tpnt->init_flag |= INIT_FUNCS_CALLED;
if (tpnt->dynamic_info[DT_INIT]) {
_dl_elf_init = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]);
+
+#if defined (SUPPORT_LD_DEBUG)
+ if(_dl_debug) _dl_dprintf(_dl_debug_file,"\ncalling init: %s\n\n", tpnt->libname);
+#endif
(*_dl_elf_init) ();
}
if (_dl_atexit && tpnt->dynamic_info[DT_FINI]) {
(*_dl_atexit) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
}
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
else {
if (!_dl_atexit)
- _dl_dprintf(2, "%s: The address of atexit () is 0x0.\n", tpnt->libname);
+ _dl_dprintf(_dl_debug_file, "%s: The address of atexit () is 0x0.\n", tpnt->libname);
#if 0
if (!tpnt->dynamic_info[DT_FINI])
- _dl_dprintf(2, "%s: Invalid .fini section.\n", tpnt->libname);
+ _dl_dprintf(_dl_debug_file, "%s: Invalid .fini section.\n", tpnt->libname);
#endif
}
#endif
@@ -1179,6 +1272,10 @@ int _dl_fixup(struct elf_resolve *tpnt)
if (tpnt->next)
goof += _dl_fixup(tpnt->next);
+#if defined (SUPPORT_LD_DEBUG)
+ if(_dl_debug) _dl_dprintf(_dl_debug_file,"\nrelocation processing: %s", tpnt->libname);
+#endif
+
if (tpnt->dynamic_info[DT_REL]) {
#ifdef ELF_USES_RELOCA
_dl_dprintf(2, "%s: can't handle REL relocation records\n",
@@ -1216,6 +1313,9 @@ int _dl_fixup(struct elf_resolve *tpnt)
goof += _dl_parse_relocation_information(tpnt, tpnt->dynamic_info[DT_JMPREL],
tpnt->dynamic_info[DT_PLTRELSZ], 0);
}
+#if defined (SUPPORT_LD_DEBUG)
+ if(_dl_debug) _dl_dprintf(_dl_debug_file,"\nrelocation processing: %s; finished\n\n", tpnt->libname);
+#endif
return goof;
}
@@ -1224,8 +1324,8 @@ void *_dl_malloc(int size)
void *retval;
#if 0
-#ifdef DL_DEBUG
- _dl_dprintf(2, "malloc: request for %d bytes\n", size);
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "malloc: request for %d bytes\n", size);
#endif
#endif
@@ -1233,8 +1333,8 @@ void *_dl_malloc(int size)
return (*_dl_malloc_function) (size);
if (_dl_malloc_addr - _dl_mmap_zero + size > 4096) {
-#ifdef DL_DEBUG
- _dl_dprintf(2, "malloc: mmapping more memory\n");
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "malloc: mmapping more memory\n");
#endif
_dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, size,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
diff --git a/ldso/ldso/m68k/boot1_arch.h b/ldso/ldso/m68k/boot1_arch.h
index 2f8fe1357..cd1f016a6 100644
--- a/ldso/ldso/m68k/boot1_arch.h
+++ b/ldso/ldso/m68k/boot1_arch.h
@@ -4,4 +4,4 @@
* can be done.
*/
-#define DL_BOOT(X) void _dl_boot (X)
+#define LD_BOOT(X) void _dl_boot (X)
diff --git a/ldso/ldso/m68k/dl-startup.h b/ldso/ldso/m68k/dl-startup.h
index 2f8fe1357..cd1f016a6 100644
--- a/ldso/ldso/m68k/dl-startup.h
+++ b/ldso/ldso/m68k/dl-startup.h
@@ -4,4 +4,4 @@
* can be done.
*/
-#define DL_BOOT(X) void _dl_boot (X)
+#define LD_BOOT(X) void _dl_boot (X)
diff --git a/ldso/ldso/m68k/elfinterp.c b/ldso/ldso/m68k/elfinterp.c
index 7e9853765..5854899ec 100644
--- a/ldso/ldso/m68k/elfinterp.c
+++ b/ldso/ldso/m68k/elfinterp.c
@@ -1,23 +1,33 @@
-/* Run an ELF binary on a linux system.
-
- Copyright (C) 1993, Eric Youngdale.
- Copyright (C) 1995, Andreas Schwab.
-
- 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. */
-
-/* Adapted to ELF/68k by Andreas Schwab. */
+/* vi: set sw=4 ts=4: */
+/* m68k ELF shared library loader suppport
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * Adapted to ELF/68k by Andreas Schwab.
+ *
+ * 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.
+ */
#ifndef VERBOSE_DLINKER
#define VERBOSE_DLINKER
@@ -83,21 +93,21 @@ unsigned int _dl_linux_resolver (int dummy1, int dummy2,
instr_addr = (int) this_reloc->r_offset + (int) tpnt->loadaddr;
got_addr = (char **) instr_addr;
-#ifdef DL_DEBUG_SYMBOLS
+#ifdef LD_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
+#ifdef LD_NEVER_FIXUP_SYMBOLS
if ((unsigned int) got_addr < 0x40000000) {
_dl_dprintf (2, "Calling library function: %s\n",
strtab + symtab[symtab_index].st_name);
@@ -202,7 +212,7 @@ _dl_parse_relocation_information (struct elf_resolve *tpnt,
symbol_addr = (unsigned int)
_dl_find_hash (strtab + symtab[symtab_index].st_name,
tpnt->symbol_scope,
- reloc_type == R_68K_JMP_SLOT ? tpnt : NULL, 0);
+ reloc_type == R_68K_JMP_SLOT ? tpnt : NULL, symbolrel);
/* We want to allow undefined references to weak symbols -
this might have been intentional. We should not be
@@ -327,7 +337,7 @@ _dl_parse_copy_information (struct dyn_elf *xpnt, unsigned long rel_addr,
{
symbol_addr = (unsigned int)
_dl_find_hash (strtab + symtab[symtab_index].st_name,
- xpnt->next, NULL, 1);
+ xpnt->next, NULL, copyrel);
if (!symbol_addr)
{
_dl_dprintf (2, "%s: can't resolve symbol '%s'\n",
diff --git a/ldso/ldso/mips/boot1_arch.h b/ldso/ldso/mips/boot1_arch.h
index 6dda467e8..b4663bcae 100644
--- a/ldso/ldso/mips/boot1_arch.h
+++ b/ldso/ldso/mips/boot1_arch.h
@@ -35,4 +35,4 @@ coff: subu $8, $31, $8
");
#define _dl_boot _dl_boot2
-#define DL_BOOT(X) static void __attribute__ ((unused)) _dl_boot (X)
+#define LD_BOOT(X) static void __attribute__ ((unused)) _dl_boot (X)
diff --git a/ldso/ldso/mips/dl-startup.h b/ldso/ldso/mips/dl-startup.h
index 6dda467e8..b4663bcae 100644
--- a/ldso/ldso/mips/dl-startup.h
+++ b/ldso/ldso/mips/dl-startup.h
@@ -35,4 +35,4 @@ coff: subu $8, $31, $8
");
#define _dl_boot _dl_boot2
-#define DL_BOOT(X) static void __attribute__ ((unused)) _dl_boot (X)
+#define LD_BOOT(X) static void __attribute__ ((unused)) _dl_boot (X)
diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c
index 377c8fa61..bac0cf584 100644
--- a/ldso/ldso/mips/elfinterp.c
+++ b/ldso/ldso/mips/elfinterp.c
@@ -1,34 +1,31 @@
/* vi: set sw=4 ts=4: */
-
-/* Run an ELF binary on a linux system.
-
+/* mips/mipsel ELF shared library loader suppport
+ *
Copyright (C) 2002, Steven J. Hill (sjhill@realitydiluted.com)
-
- 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. */
-
-
-/* Program to load an ELF binary on a linux system, and run it.
- References to symbols in sharable libraries can be resolved by either
- an ELF sharable library or a linux style of shared library. */
-
-/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
- I ever taken any courses on internals. This program was developed using
- information available through the book "UNIX SYSTEM V RELEASE 4,
- Programmers guide: Ansi C and Programming Support Tools", which did
- a more than adequate job of explaining everything required to get this
- working. */
+ *
+ * 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.
+ */
extern int _dl_linux_resolve(void);
@@ -55,11 +52,11 @@ unsigned long _dl_linux_resolver(unsigned long sym_index,
strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
value = (unsigned long) _dl_find_hash(strtab + sym->st_name,
- tpnt->symbol_scope, tpnt, 1);
+ tpnt->symbol_scope, tpnt, resolver);
*(got + local_gotno + sym_index - gotsym) = value;
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
_dl_dprintf(2, "---RESOLVER---\n");
_dl_dprintf(2, "SYMTAB INDEX: %i\n", sym_index);
_dl_dprintf(2, " GOTSYM: %i\n", gotsym);
@@ -167,7 +164,7 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
/* Relocate the global GOT entries for the object */
while(i--) {
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
_dl_dprintf(2,"BEFORE: %s=%x\n", strtab + sym->st_name,
*got_entry);
#endif
@@ -176,12 +173,12 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
*got_entry = sym->st_value + (unsigned long) tpnt->loadaddr;
else {
*got_entry = (unsigned long) _dl_find_hash(strtab +
- sym->st_name, tpnt->symbol_scope, NULL, 1);
+ sym->st_name, tpnt->symbol_scope, NULL, copyrel);
}
}
else if (sym->st_shndx == SHN_COMMON) {
*got_entry = (unsigned long) _dl_find_hash(strtab +
- sym->st_name, tpnt->symbol_scope, NULL, 1);
+ sym->st_name, tpnt->symbol_scope, NULL, copyrel);
}
else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC &&
*got_entry != sym->st_value)
@@ -192,10 +189,10 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
}
else {
*got_entry = (unsigned long) _dl_find_hash(strtab +
- sym->st_name, tpnt->symbol_scope, NULL, 1);
+ sym->st_name, tpnt->symbol_scope, NULL, copyrel);
}
-#ifdef DL_DEBUG
+#ifdef LD_DEBUG
if (*got_entry == 0)
_dl_dprintf(2,"ZERO: %s\n", strtab + sym->st_name);
else
diff --git a/ldso/ldso/powerpc/boot1_arch.h b/ldso/ldso/powerpc/boot1_arch.h
index 0e2e1f055..ae7939eb2 100644
--- a/ldso/ldso/powerpc/boot1_arch.h
+++ b/ldso/ldso/powerpc/boot1_arch.h
@@ -17,5 +17,5 @@ _dl_boot:
");
#define _dl_boot _dl_boot2
-#define DL_BOOT(X) static void * __attribute__ ((unused)) _dl_boot (X)
+#define LD_BOOT(X) static void * __attribute__ ((unused)) _dl_boot (X)
diff --git a/ldso/ldso/powerpc/dl-startup.h b/ldso/ldso/powerpc/dl-startup.h
index 0e2e1f055..ae7939eb2 100644
--- a/ldso/ldso/powerpc/dl-startup.h
+++ b/ldso/ldso/powerpc/dl-startup.h
@@ -17,5 +17,5 @@ _dl_boot:
");
#define _dl_boot _dl_boot2
-#define DL_BOOT(X) static void * __attribute__ ((unused)) _dl_boot (X)
+#define LD_BOOT(X) static void * __attribute__ ((unused)) _dl_boot (X)
diff --git a/ldso/ldso/powerpc/elfinterp.c b/ldso/ldso/powerpc/elfinterp.c
index 5ecef1a02..4d263df2f 100644
--- a/ldso/ldso/powerpc/elfinterp.c
+++ b/ldso/ldso/powerpc/elfinterp.c
@@ -1,22 +1,32 @@
-//#define DL_DEBUG
-/* Run an ELF binary on a linux system.
+/* vi: set sw=4 ts=4: */
+/* i386 ELF shared library loader suppport
+ *
+ * Copyright (C) 2001-2002, David A. Schleef
+ *
+ * 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.
+ */
- 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. */
-
#ifndef VERBOSE_DLINKER
#define VERBOSE_DLINKER
#endif
@@ -49,7 +59,7 @@ static const char *_dl_reltypes[] =
working. */
-#ifdef DL_DEBUG_SYMBOLS
+#ifdef LD_DEBUG_SYMBOLS
static void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index);
static void debug_reloc(ELF_RELOC *rpnt);
#define DPRINTF(fmt,args...) _dl_dprintf(2,fmt,args)
@@ -161,7 +171,7 @@ unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
/* Get the address of the GOT entry */
targ_addr = (unsigned long) _dl_find_hash(
strtab + symtab[symtab_index].st_name,
- tpnt->symbol_scope, tpnt, 0);
+ tpnt->symbol_scope, tpnt, resolver);
if (!targ_addr) {
_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
_dl_progname, strtab + symtab[symtab_index].st_name);
@@ -338,7 +348,7 @@ int _dl_parse_relocation_information(struct elf_resolve *tpnt,
symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name,
tpnt->symbol_scope,
- (reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL), 0);
+ (reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL), symbolrel);
/*
* We want to allow undefined references to weak symbols - this might
@@ -499,7 +509,7 @@ int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
symbol_addr = (unsigned long) _dl_find_hash(strtab +
symtab[symtab_index].st_name, xpnt->next,
- NULL, 1);
+ NULL, copyrel);
if (!symbol_addr) {
_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
_dl_progname, strtab + symtab[symtab_index].st_name);
@@ -551,7 +561,7 @@ static void fixup_jmpslot(unsigned long reloc_addr, unsigned long targ_addr)
#endif
-#ifdef DL_DEBUG_SYMBOLS
+#ifdef LD_DEBUG_SYMBOLS
static void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index)
{
if(symtab_index){
diff --git a/ldso/ldso/readelflib1.c b/ldso/ldso/readelflib1.c
index c5e7607e0..8c2314184 100644
--- a/ldso/ldso/readelflib1.c
+++ b/ldso/ldso/readelflib1.c
@@ -1,21 +1,34 @@
-/* Load an ELF sharable library into memory.
-
- Copyright (C) 1993-1996, 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. */
-
+/* vi: set sw=4 ts=4: */
+/* Program to load an ELF binary on a linux system, and run it
+ * after resolving ELF shared library symbols
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ * 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.
+ */
/* This file contains the helper routines to load an ELF sharable
@@ -180,8 +193,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
pnt++;
}
-#ifdef DL_DEBUG
- _dl_dprintf(2, "searching for library: '%s'\n", libname);
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "searching for library: '%s'\n", libname);
#endif
/* If the filename has any '/', try it straight and leave it at that.
For IBCS2 compatibility under linux, we substitute the string
@@ -204,8 +217,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
if (pnt) {
pnt += (unsigned long) tpnt->loadaddr +
tpnt->dynamic_info[DT_STRTAB];
-#ifdef DL_DEBUG
- _dl_dprintf(2, "searching RPATH: '%s'\n", pnt);
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "searching RPATH: '%s'\n", pnt);
#endif
if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL)
{
@@ -217,8 +230,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
/* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */
if (_dl_library_path) {
-#ifdef DL_DEBUG
- _dl_dprintf(2, "searching _dl_library_path: '%s'\n", _dl_library_path);
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "searching _dl_library_path: '%s'\n", _dl_library_path);
#endif
if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL)
{
@@ -251,8 +264,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
/* Look for libraries wherever the shared library loader
* was installed */
-#ifdef DL_DEBUG
- _dl_dprintf(2, "searching in ldso dir: %s\n", _dl_ldsopath);
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "searching in ldso dir: %s\n", _dl_ldsopath);
#endif
if ((tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt)) != NULL)
{
@@ -262,8 +275,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
/* Lastly, search the standard list of paths for the library.
This list must exactly match the list in uClibc/ldso/util/ldd.c */
-#ifdef DL_DEBUG
- _dl_dprintf(2, "searching full lib path list\n");
+#ifdef LD_DEBUG
+ _dl_dprintf(_dl_debug_file, "searching full lib path list\n");
#endif
if ((tpnt1 = search_for_named_library(libname, secure,
UCLIBC_TARGET_PREFIX "/usr/lib:"
@@ -282,8 +295,8 @@ goof:
if (_dl_internal_error_number)
_dl_error_number = _dl_internal_error_number;
else
- _dl_error_number = DL_ERROR_NOFILE;
-#ifdef DL_DEBUG
+ _dl_error_number = LD_ERROR_NOFILE;
+#ifdef LD_DEBUG
_dl_dprintf(2, "Bummer: could not find '%s'!\n", libname);
#endif
return NULL;
@@ -323,6 +336,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
(*rpnt)->next = (struct dyn_elf *)
_dl_malloc(sizeof(struct dyn_elf));
_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
+ (*rpnt)->next->prev = (*rpnt);
*rpnt = (*rpnt)->next;
(*rpnt)->dyn = tpnt;
tpnt->symbol_scope = _dl_symbol_tables;
@@ -352,7 +366,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
*/
_dl_dprintf(2, "%s: can't open '%s'\n", _dl_progname, libname);
#endif
- _dl_internal_error_number = DL_ERROR_NOFILE;
+ _dl_internal_error_number = LD_ERROR_NOFILE;
return NULL;
}
@@ -365,7 +379,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
{
_dl_dprintf(2, "%s: '%s' is not an ELF file\n", _dl_progname,
libname);
- _dl_internal_error_number = DL_ERROR_NOTELF;
+ _dl_internal_error_number = LD_ERROR_NOTELF;
_dl_close(infile);
return NULL;
};
@@ -377,7 +391,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
))
{
_dl_internal_error_number =
- (epnt->e_type != ET_DYN ? DL_ERROR_NOTDYN : DL_ERROR_NOTMAGIC);
+ (epnt->e_type != ET_DYN ? LD_ERROR_NOTDYN : LD_ERROR_NOTMAGIC);
_dl_dprintf(2, "%s: '%s' is not an ELF executable for " ELF_TARGET
"\n", _dl_progname, libname);
_dl_close(infile);
@@ -424,7 +438,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0);
if (_dl_mmap_check_error(status)) {
_dl_dprintf(2, "%s: can't map %s\n", _dl_progname, libname);
- _dl_internal_error_number = DL_ERROR_MMAP_FAILED;
+ _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
_dl_close(infile);
return NULL;
};
@@ -457,7 +471,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
if (_dl_mmap_check_error(status)) {
_dl_dprintf(2, "%s: can't map '%s'\n",
_dl_progname, libname);
- _dl_internal_error_number = DL_ERROR_MMAP_FAILED;
+ _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
_dl_munmap((char *) libaddr, maxvma - minvma);
_dl_close(infile);
return NULL;
@@ -488,7 +502,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
infile, ppnt->p_offset & OFFS_ALIGN);
if (_dl_mmap_check_error(status)) {
_dl_dprintf(2, "%s: can't map '%s'\n", _dl_progname, libname);
- _dl_internal_error_number = DL_ERROR_MMAP_FAILED;
+ _dl_internal_error_number = LD_ERROR_MMAP_FAILED;
_dl_munmap((char *) libaddr, maxvma - minvma);
_dl_close(infile);
return NULL;
@@ -516,7 +530,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
/* Start by scanning the dynamic section to get all of the pointers */
if (!dynamic_addr) {
- _dl_internal_error_number = DL_ERROR_NODYNAMIC;
+ _dl_internal_error_number = LD_ERROR_NODYNAMIC;
_dl_dprintf(2, "%s: '%s' is missing a dynamic section\n",
_dl_progname, libname);
return NULL;
@@ -580,6 +594,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
(*rpnt)->next = (struct dyn_elf *)
_dl_malloc(sizeof(struct dyn_elf));
_dl_memset((*rpnt)->next, 0, sizeof(*((*rpnt)->next)));
+ (*rpnt)->next->prev = (*rpnt);
*rpnt = (*rpnt)->next;
(*rpnt)->dyn = tpnt;
tpnt->symbol_scope = _dl_symbol_tables;
@@ -626,6 +641,10 @@ int _dl_copy_fixups(struct dyn_elf *rpnt)
return goof;
tpnt->init_flag |= COPY_RELOCS_DONE;
+#if defined (SUPPORT_LD_DEBUG)
+ if(_dl_debug) _dl_dprintf(_dl_debug_file,"\nrelocation copy fixups: %s", tpnt->libname);
+#endif
+
#ifdef ELF_USES_RELOCA
goof += _dl_parse_copy_information(rpnt,
tpnt->dynamic_info[DT_RELA], tpnt->dynamic_info[DT_RELASZ], 0);
@@ -635,5 +654,8 @@ int _dl_copy_fixups(struct dyn_elf *rpnt)
tpnt->dynamic_info[DT_RELSZ], 0);
#endif
+#if defined (SUPPORT_LD_DEBUG)
+ if(_dl_debug) _dl_dprintf(_dl_debug_file,"\nrelocation copy fixups: %s; finished\n\n", tpnt->libname);
+#endif
return goof;
}
diff --git a/ldso/ldso/sh/boot1_arch.h b/ldso/ldso/sh/boot1_arch.h
new file mode 100644
index 000000000..798121dc0
--- /dev/null
+++ b/ldso/ldso/sh/boot1_arch.h
@@ -0,0 +1,23 @@
+/* Any assmbly language/system dependent hacks needed to setup boot1.c so it
+ * will work as expected and cope with whatever platform specific wierdness is
+ * needed for this architecture. */
+
+asm("\
+ .text
+ .globl _dl_boot
+_dl_boot:
+ mov r15, r4
+ mov.l .L_dl_boot2, r1
+ mova .L_dl_boot2, r0
+ add r1, r0
+ jsr @r0
+ add #4, r4
+ jmp @r0
+ mov #0, r4 /* call _start with arg == 0 */
+.L_dl_boot2:\n\
+ .long _dl_boot2-.\n\
+ .previous\n\
+");
+
+#define _dl_boot _dl_boot2
+#define LD_BOOT(X) static void * __attribute__ ((unused)) _dl_boot (X)
diff --git a/ldso/ldso/sh/dl-startup.h b/ldso/ldso/sh/dl-startup.h
new file mode 100644
index 000000000..798121dc0
--- /dev/null
+++ b/ldso/ldso/sh/dl-startup.h
@@ -0,0 +1,23 @@
+/* Any assmbly language/system dependent hacks needed to setup boot1.c so it
+ * will work as expected and cope with whatever platform specific wierdness is
+ * needed for this architecture. */
+
+asm("\
+ .text
+ .globl _dl_boot
+_dl_boot:
+ mov r15, r4
+ mov.l .L_dl_boot2, r1
+ mova .L_dl_boot2, r0
+ add r1, r0
+ jsr @r0
+ add #4, r4
+ jmp @r0
+ mov #0, r4 /* call _start with arg == 0 */
+.L_dl_boot2:\n\
+ .long _dl_boot2-.\n\
+ .previous\n\
+");
+
+#define _dl_boot _dl_boot2
+#define LD_BOOT(X) static void * __attribute__ ((unused)) _dl_boot (X)
diff --git a/ldso/ldso/sh/dl-syscalls.h b/ldso/ldso/sh/dl-syscalls.h
new file mode 100644
index 000000000..793dc9110
--- /dev/null
+++ b/ldso/ldso/sh/dl-syscalls.h
@@ -0,0 +1,7 @@
+/* Define the __set_errno macro as nothing so that we don't bother
+ * setting errno, which is important since we make system calls
+ * before the errno symbol is dynamicly linked. */
+
+#define __set_errno(X)
+#include "sys/syscall.h"
+
diff --git a/ldso/ldso/sh/dl-sysdep.h b/ldso/ldso/sh/dl-sysdep.h
new file mode 100644
index 000000000..dc1b895b9
--- /dev/null
+++ b/ldso/ldso/sh/dl-sysdep.h
@@ -0,0 +1,145 @@
+/*
+ * Various assmbly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ */
+
+/*
+ * Define this if the system uses RELOCA.
+ */
+#define ELF_USES_RELOCA
+
+/*
+ * Get a pointer to the argv array. On many platforms this can be just
+ * the address if the first argument, on other platforms we need to
+ * do something a little more subtle here.
+ */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*) ARGS)
+
+/*
+ * Initialization sequence for a GOT.
+ */
+#define INIT_GOT(GOT_BASE,MODULE) \
+{ \
+ GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \
+ GOT_BASE[1] = (unsigned long) (MODULE); \
+}
+
+/*
+ * Here is a macro to perform a relocation. This is only used when
+ * bootstrapping the dynamic loader. RELP is the relocation that we
+ * are performing, REL is the pointer to the address we are relocating.
+ * SYMBOL is the symbol involved in the relocation, and LOAD is the
+ * load address.
+ */
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD) \
+ switch(ELF32_R_TYPE((RELP)->r_info)){ \
+ case R_SH_REL32: \
+ *(REL) += (RELP)->r_addend - (LOAD); \
+ break; \
+ case R_SH_DIR32: \
+ *(REL) += (SYMBOL) + (RELP)->r_addend; \
+ break; \
+ case R_SH_RELATIVE: \
+ *(REL) += (LOAD); \
+ break; \
+ case R_SH_NONE: \
+ break; \
+ default: \
+ SEND_STDERR("BOOTSTRAP_RELOC: unhandled reloc type "); \
+ SEND_NUMBER_STDERR(ELF32_R_TYPE((RELP)->r_info), 1); \
+ SEND_STDERR("REL, SYMBOL, LOAD: "); \
+ SEND_ADDRESS_STDERR(REL, 0); \
+ SEND_STDERR(", "); \
+ SEND_ADDRESS_STDERR(SYMBOL, 0); \
+ SEND_STDERR(", "); \
+ SEND_ADDRESS_STDERR(LOAD, 1); \
+ _dl_exit(1); \
+ }
+
+
+/*
+ * Transfer control to the user's application, once the dynamic loader
+ * is done. This routine has to exit the current function, then
+ * call the _dl_elf_main function.
+ */
+
+#define START() return _dl_elf_main;
+
+
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+
+#define MAGIC1 EM_SH
+#undef MAGIC2
+/* Used for error messages */
+#define ELF_TARGET "sh"
+
+struct elf_resolve;
+extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+static __inline__ unsigned int
+_dl_urem(unsigned int n, unsigned int base)
+{
+register unsigned int __r0 __asm__ ("r0");
+register unsigned int __r4 __asm__ ("r4") = n;
+register unsigned int __r5 __asm__ ("r5") = base;
+
+ __asm__ ("
+ mov #0, r0
+ div0u
+
+ ! get one bit from the msb of the numerator into the T
+ ! bit and divide it by whats in %2. Put the answer bit
+ ! into the T bit so it can come out again at the bottom
+
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4
+ mov r4, r0
+"
+ : "=r" (__r0)
+ : "r" (__r4), "r" (__r5)
+ : "r4", "cc");
+
+ return n - (base * __r0);
+}
+
+#define do_rem(result, n, base) ((result) = _dl_urem((n), (base)))
+
+/* 4096 bytes alignment */
+#define PAGE_ALIGN 0xfffff000
+#define ADDR_ALIGN 0xfff
+#define OFFS_ALIGN 0x7ffff000
diff --git a/ldso/ldso/sh/elfinterp.c b/ldso/ldso/sh/elfinterp.c
new file mode 100644
index 000000000..2a0ab9f7a
--- /dev/null
+++ b/ldso/ldso/sh/elfinterp.c
@@ -0,0 +1,416 @@
+/* vi: set sw=4 ts=4: */
+/* SuperH ELF shared library loader suppport
+ *
+ * Copyright (C) 2002, Stefan Allius <allius@atecom.com> and
+ * Eddie C. Dost <ecd@atecom.com>
+ *
+ * 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_SH_NONE", "R_SH_DIR32", "R_SH_REL32", "R_SH_DIR8WPN",
+ [4] "R_SH_IND12W", "R_SH_DIR8WPL", "R_SH_DIR8WPZ", "R_SH_DIR8BP",
+ [8] "R_SH_DIR8W", "R_SH_DIR8L",
+ [25] "R_SH_SWITCH16","R_SH_SWITCH32","R_SH_USES",
+ [28] "R_SH_COUNT", "R_SH_ALIGN", "R_SH_CODE", "R_SH_DATA",
+ [32] "R_SH_LABEL", "R_SH_SWITCH8", "R_SH_GNU_VTINHERIT","R_SH_GNU_VTENTRY",
+[160] "R_SH_GOT32", "R_SH_PLT32", "R_SH_COPY", "R_SH_GLOB_DAT",
+[164] "R_SH_JMP_SLOT","R_SH_RELATIVE","R_SH_GOTOFF", "R_SH_GOTPC",
+};
+
+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.
+ References to symbols in sharable libraries can be resolved by either
+ an ELF sharable library or a linux style of shared library. */
+
+/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have
+ I ever taken any courses on internals. This program was developed using
+ information available through the book "UNIX SYSTEM V RELEASE 4,
+ Programmers guide: Ansi C and Programming Support Tools", which did
+ 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;
+ ELF_RELOC *this_reloc;
+ char *strtab;
+ Elf32_Sym *symtab;
+ int symtab_index;
+ char *rel_addr;
+ char *new_addr;
+ char **got_addr;
+ unsigned long instr_addr;
+
+ rel_addr = (char *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
+
+ this_reloc = (ELF_RELOC *) (rel_addr + reloc_entry);
+ reloc_type = ELF32_R_TYPE(this_reloc->r_info);
+ symtab_index = ELF32_R_SYM(this_reloc->r_info);
+
+ symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
+ strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+
+ if (reloc_type != R_SH_JMP_SLOT) {
+ _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);
+ got_addr = (char **) instr_addr;
+
+
+ /* Get the address of the GOT entry */
+ new_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name,
+ 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);
+ }
+
+#if defined (SUPPORT_LD_DEBUG) || defined (LD_NEVER_FIXUP_SYMBOLS)
+ if ((unsigned long) got_addr < 0x20000000)
+ {
+#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;
+ }
+#else
+ *got_addr = new_addr;
+#endif
+
+ return (unsigned long) new_addr;
+}
+
+
+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 goof = 0;
+ Elf32_Sym *symtab;
+ ELF_RELOC *rpnt;
+ int symtab_index;
+ /* Now parse the relocation information */
+
+ 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++) {
+ 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 '%s'\n");
+ goof += res;
+ }
+ }
+ return goof;
+}
+
+
+static int
+_dl_do_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;
+
+ 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;
+
+ if (symtab_index) {
+
+
+ symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name,
+ scope,
+ (reloc_type == R_SH_JMP_SLOT ? tpnt : NULL), symbolrel);
+
+ /*
+ * 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_SH_NONE:
+ break;
+ case R_SH_COPY:
+ /* handled later on */
+ break;
+ case R_SH_DIR32:
+ *reloc_addr += symbol_addr + rpnt->r_addend;
+ break;
+ case R_SH_JMP_SLOT:
+ *reloc_addr = symbol_addr + rpnt->r_addend;
+ break;
+ case R_SH_REL32:
+ *reloc_addr += rpnt->r_addend -
+ (unsigned long) tpnt->loadaddr;
+ break;
+ case R_SH_RELATIVE:
+ *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 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_SH_NONE:
+ break;
+ case R_SH_JMP_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
+ 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. */
+
+/* No, there are cases where the SVr4 linker fails to emit COPY relocs
+ at all */
+static int
+_dl_do_copy (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;
+
+ reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
+ reloc_type = ELF32_R_TYPE(rpnt->r_info);
+ if (reloc_type != R_SH_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);
+ }
+
+ return goof;
+}
+
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+
diff --git a/ldso/ldso/sh/ld_syscalls.h b/ldso/ldso/sh/ld_syscalls.h
new file mode 100644
index 000000000..793dc9110
--- /dev/null
+++ b/ldso/ldso/sh/ld_syscalls.h
@@ -0,0 +1,7 @@
+/* Define the __set_errno macro as nothing so that we don't bother
+ * setting errno, which is important since we make system calls
+ * before the errno symbol is dynamicly linked. */
+
+#define __set_errno(X)
+#include "sys/syscall.h"
+
diff --git a/ldso/ldso/sh/ld_sysdep.h b/ldso/ldso/sh/ld_sysdep.h
new file mode 100644
index 000000000..dc1b895b9
--- /dev/null
+++ b/ldso/ldso/sh/ld_sysdep.h
@@ -0,0 +1,145 @@
+/*
+ * Various assmbly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ */
+
+/*
+ * Define this if the system uses RELOCA.
+ */
+#define ELF_USES_RELOCA
+
+/*
+ * Get a pointer to the argv array. On many platforms this can be just
+ * the address if the first argument, on other platforms we need to
+ * do something a little more subtle here.
+ */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*) ARGS)
+
+/*
+ * Initialization sequence for a GOT.
+ */
+#define INIT_GOT(GOT_BASE,MODULE) \
+{ \
+ GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \
+ GOT_BASE[1] = (unsigned long) (MODULE); \
+}
+
+/*
+ * Here is a macro to perform a relocation. This is only used when
+ * bootstrapping the dynamic loader. RELP is the relocation that we
+ * are performing, REL is the pointer to the address we are relocating.
+ * SYMBOL is the symbol involved in the relocation, and LOAD is the
+ * load address.
+ */
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD) \
+ switch(ELF32_R_TYPE((RELP)->r_info)){ \
+ case R_SH_REL32: \
+ *(REL) += (RELP)->r_addend - (LOAD); \
+ break; \
+ case R_SH_DIR32: \
+ *(REL) += (SYMBOL) + (RELP)->r_addend; \
+ break; \
+ case R_SH_RELATIVE: \
+ *(REL) += (LOAD); \
+ break; \
+ case R_SH_NONE: \
+ break; \
+ default: \
+ SEND_STDERR("BOOTSTRAP_RELOC: unhandled reloc type "); \
+ SEND_NUMBER_STDERR(ELF32_R_TYPE((RELP)->r_info), 1); \
+ SEND_STDERR("REL, SYMBOL, LOAD: "); \
+ SEND_ADDRESS_STDERR(REL, 0); \
+ SEND_STDERR(", "); \
+ SEND_ADDRESS_STDERR(SYMBOL, 0); \
+ SEND_STDERR(", "); \
+ SEND_ADDRESS_STDERR(LOAD, 1); \
+ _dl_exit(1); \
+ }
+
+
+/*
+ * Transfer control to the user's application, once the dynamic loader
+ * is done. This routine has to exit the current function, then
+ * call the _dl_elf_main function.
+ */
+
+#define START() return _dl_elf_main;
+
+
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+
+#define MAGIC1 EM_SH
+#undef MAGIC2
+/* Used for error messages */
+#define ELF_TARGET "sh"
+
+struct elf_resolve;
+extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+
+static __inline__ unsigned int
+_dl_urem(unsigned int n, unsigned int base)
+{
+register unsigned int __r0 __asm__ ("r0");
+register unsigned int __r4 __asm__ ("r4") = n;
+register unsigned int __r5 __asm__ ("r5") = base;
+
+ __asm__ ("
+ mov #0, r0
+ div0u
+
+ ! get one bit from the msb of the numerator into the T
+ ! bit and divide it by whats in %2. Put the answer bit
+ ! into the T bit so it can come out again at the bottom
+
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4 ; div1 r5, r0
+ rotcl r4
+ mov r4, r0
+"
+ : "=r" (__r0)
+ : "r" (__r4), "r" (__r5)
+ : "r4", "cc");
+
+ return n - (base * __r0);
+}
+
+#define do_rem(result, n, base) ((result) = _dl_urem((n), (base)))
+
+/* 4096 bytes alignment */
+#define PAGE_ALIGN 0xfffff000
+#define ADDR_ALIGN 0xfff
+#define OFFS_ALIGN 0x7ffff000
diff --git a/ldso/ldso/sh/resolve.S b/ldso/ldso/sh/resolve.S
new file mode 100644
index 000000000..4d8eee6c2
--- /dev/null
+++ b/ldso/ldso/sh/resolve.S
@@ -0,0 +1,69 @@
+/*
+ * Stolen from glibc-2.2.2 by Eddie C. Dost <ecd@atecom.com>
+ */
+
+ .text
+ .globl _dl_linux_resolve
+ .type _dl_linux_resolve, @function
+ .balign 16
+_dl_linux_resolve:
+ mov.l r3, @-r15
+ mov.l r4, @-r15
+ mov.l r5, @-r15
+ mov.l r6, @-r15
+ mov.l r7, @-r15
+ mov.l r12, @-r15
+ movt r3 ! Save T flag
+ mov.l r3, @-r15
+
+#ifdef HAVE_FPU
+ sts.l fpscr, @-r15
+ mov #8,r3
+ swap.w r3, r3
+ lds r3, fpscr
+ fmov.s fr11, @-r15
+ fmov.s fr10, @-r15
+ fmov.s fr9, @-r15
+ fmov.s fr8, @-r15
+ fmov.s fr7, @-r15
+ fmov.s fr6, @-r15
+ fmov.s fr5, @-r15
+ fmov.s fr4, @-r15
+#endif
+ sts.l pr, @-r15
+
+ mov r2, r4 ! link map address
+
+ mov.l 3f, r0
+ jsr @r0 ! Call resolver
+ mov r1, r5 ! Reloc offset
+
+ lds.l @r15+, pr ! Get register content back
+
+#ifdef HAVE_FPU
+ fmov.s @r15+, fr4
+ fmov.s @r15+, fr5
+ fmov.s @r15+, fr6
+ fmov.s @r15+, fr7
+ fmov.s @r15+, fr8
+ fmov.s @r15+, fr9
+ fmov.s @r15+, fr10
+ fmov.s @r15+, fr11
+ lds.l @r15+, fpscr
+#endif
+
+ mov.l @r15+, r3
+ shal r3 ! Load T flag
+ mov.l @r15+, r12
+ mov.l @r15+, r7
+ mov.l @r15+, r6
+ mov.l @r15+, r5
+ mov.l @r15+, r4
+ jmp @r0 ! Jump to function address
+ mov.l @r15+, r3
+
+ .balign 4
+3:
+ .long _dl_linux_resolver
+ .size _dl_linux_resolve, . - _dl_linux_resolve
+
diff --git a/ldso/ldso/sparc/boot1_arch.h b/ldso/ldso/sparc/boot1_arch.h
index 2f8fe1357..cd1f016a6 100644
--- a/ldso/ldso/sparc/boot1_arch.h
+++ b/ldso/ldso/sparc/boot1_arch.h
@@ -4,4 +4,4 @@
* can be done.
*/
-#define DL_BOOT(X) void _dl_boot (X)
+#define LD_BOOT(X) void _dl_boot (X)
diff --git a/ldso/ldso/sparc/dl-startup.h b/ldso/ldso/sparc/dl-startup.h
index 2f8fe1357..cd1f016a6 100644
--- a/ldso/ldso/sparc/dl-startup.h
+++ b/ldso/ldso/sparc/dl-startup.h
@@ -4,4 +4,4 @@
* can be done.
*/
-#define DL_BOOT(X) void _dl_boot (X)
+#define LD_BOOT(X) void _dl_boot (X)
diff --git a/ldso/ldso/sparc/elfinterp.c b/ldso/ldso/sparc/elfinterp.c
index 3270a0821..60ec4b0e8 100644
--- a/ldso/ldso/sparc/elfinterp.c
+++ b/ldso/ldso/sparc/elfinterp.c
@@ -1,21 +1,33 @@
-/* Run an ELF binary on a linux system.
+/* vi: set sw=4 ts=4: */
+/* sparc ELF shared library loader suppport
+ *
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ *
+ * 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.
+ */
- Copyright (C) 1995, 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. */
-
#ifndef VERBOSE_DLINKER
#define VERBOSE_DLINKER
#endif
@@ -91,20 +103,20 @@ unsigned int _dl_linux_resolver(unsigned int reloc_entry, unsigned int * plt)
_dl_dprintf(2, "symtab_index %d\n", symtab_index);
-#ifdef DL_DEBUG_SYMBOLS
+#ifdef LD_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(31);
};
-#ifdef DL_NEVER_FIXUP_SYMBOLS
+#ifdef LD_NEVER_FIXUP_SYMBOLS
if((unsigned int) got_addr < 0x40000000) {
_dl_dprintf(2, "Calling library function: %s\n",
strtab + symtab[symtab_index].st_name);
@@ -202,7 +214,7 @@ int _dl_parse_relocation_information(struct elf_resolve * tpnt, int rel_addr,
symbol_addr = (unsigned int)
_dl_find_hash(strtab + symtab[symtab_index].st_name,
tpnt->symbol_scope,
- (reloc_type == R_SPARC_JMP_SLOT ? tpnt : NULL), 0);
+ (reloc_type == R_SPARC_JMP_SLOT ? tpnt : NULL), symbolrel);
if(!symbol_addr &&
ELF32_ST_BIND(symtab [symtab_index].st_info) == STB_GLOBAL) {
@@ -319,7 +331,7 @@ int _dl_parse_copy_information(struct dyn_elf * xpnt, int rel_addr,
symbol_addr = (unsigned int)
_dl_find_hash(strtab + symtab[symtab_index].st_name,
- xpnt->next, NULL, 1);
+ xpnt->next, NULL, copyrel);
if(!symbol_addr) {
_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
_dl_progname, strtab + symtab[symtab_index].st_name);