summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2002-04-02 21:12:37 +0000
committerEric Andersen <andersen@codepoet.org>2002-04-02 21:12:37 +0000
commit96749a768287761528a05670560402a16f6839ac (patch)
treec53550a3ec7458f02da07d465c74bae3f752f499
parentabdb41c778c5892d51fe92879d383eb8ba000028 (diff)
Steven J. Hill's latest mips dynamic loader updates
-rw-r--r--Makefile9
-rw-r--r--ldso/ldso/dl-elf.c7
-rw-r--r--ldso/ldso/ld_string.h2
-rw-r--r--ldso/ldso/ld_syscall.h4
-rw-r--r--ldso/ldso/ldso.c46
-rw-r--r--ldso/ldso/mips/README43
-rw-r--r--ldso/ldso/mips/boot1_arch.h5
-rw-r--r--ldso/ldso/mips/dl-startup.h5
-rw-r--r--ldso/ldso/mips/dl-syscalls.h30
-rw-r--r--ldso/ldso/mips/dl-sysdep.h92
-rw-r--r--ldso/ldso/mips/elfinterp.c49
-rw-r--r--ldso/ldso/mips/ld_syscalls.h30
-rw-r--r--ldso/ldso/mips/ld_sysdep.h92
-rw-r--r--ldso/ldso/readelflib1.c7
14 files changed, 346 insertions, 75 deletions
diff --git a/Makefile b/Makefile
index ac6b27bc0..0455a2ac9 100644
--- a/Makefile
+++ b/Makefile
@@ -332,16 +332,17 @@ finished2:
distclean clean:
@rm -rf tmp lib include/bits libc/tmp _install
- - find include -type l -exec rm -f {} \;
- - find . \( -name \*.o -o -name \*.a -o -name \*.so -o -name core -o -name .\#\* \) -exec rm -f {} \;
$(MAKE) -C test clean
$(MAKE) -C ldso clean
$(MAKE) -C libc/misc clean
$(MAKE) -C libc/unistd clean
$(MAKE) -C libc/sysdeps/linux/common clean
- $(MAKE) -C libc/sysdeps/linux/$(TARGET_ARCH) clean
$(MAKE) -C extra/gcc-uClibc clean
- find . -name mipsel -exec rm -rf {} \;
+ @if [ -d libc/sysdeps/linux/$(TARGET_ARCH) ]; then \
+ $(MAKE) -C libc/sysdeps/linux/$(TARGET_ARCH) clean; \
+ fi;
+ - find . \( -name \*.o -o -name \*.a -o -name \*.so -o -name core -o -name .\#\* \) -exec rm -f {} \;
+ - find -type l -exec rm -f {} \;
dist release: distclean
cd ..; \
diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
index d565b9290..913ac8778 100644
--- a/ldso/ldso/dl-elf.c
+++ b/ldso/ldso/dl-elf.c
@@ -308,7 +308,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
int flags;
char header[4096];
unsigned long dynamic_info[24];
- int *lpnt;
+ unsigned long *lpnt;
unsigned long libaddr;
unsigned long minvma = 0xffffffff, maxvma = 0;
@@ -553,10 +553,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
* resolved.
*/
- lpnt = (int *) dynamic_info[DT_PLTGOT];
+ lpnt = (unsigned long *) dynamic_info[DT_PLTGOT];
if (lpnt) {
- lpnt = (int *) (dynamic_info[DT_PLTGOT] + ((int) libaddr));
+ lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT] +
+ ((int) libaddr));
INIT_GOT(lpnt, tpnt);
};
diff --git a/ldso/ldso/ld_string.h b/ldso/ldso/ld_string.h
index d872a6f13..736836d9b 100644
--- a/ldso/ldso/ld_string.h
+++ b/ldso/ldso/ld_string.h
@@ -221,7 +221,7 @@ static inline char *_dl_simple_ltoahex(char * local, unsigned long i)
}
-#if defined mc68000 || defined __arm__
+#if defined mc68000 || defined __arm__ || defined __mips__
/* 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 ba94d7598..db7447f67 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);
-#ifdef __powerpc__
-/* PowerPC has a different calling convention for mmap(). */
+#if defined(__powerpc) || defined(__mips__)
+/* PowerPC and MIPS 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);
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
index 456205adc..3a479caf5 100644
--- a/ldso/ldso/ldso.c
+++ b/ldso/ldso/ldso.c
@@ -20,11 +20,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* Enable this to turn on debugging noise */
-//#define DL_DEBUG
-
-/* Enable mprotect protection munging. ARM Linux needs this it seems,
- * so leave this enabled by default */
+/* Enable mprotect protection munging. ARM and MIPS Linux needs this
+ * it seems, so leave this enabled by default */
#define DO_MPROTECT_HACKS
// Support a list of library preloads in /etc/ld.so.preload
@@ -209,10 +206,16 @@ DL_BOOT(unsigned long args)
Elf32_auxv_t auxvt[AT_EGID + 1];
unsigned char *malloc_buffer, *mmap_zero;
Elf32_Dyn *dpnt;
+ Elf32_Dyn *dpnt_debug = NULL;
unsigned long *hash_addr;
struct r_debug *debug_addr;
int indx;
int status;
+#if defined(__mips__)
+ unsigned long mips_gotsym = 0;
+ unsigned long mips_local_gotno = 0;
+ unsigned long mips_symtabno = 0;
+#endif
/* WARNING! -- we cannot make _any_ funtion calls until we have
@@ -223,7 +226,7 @@ DL_BOOT(unsigned long args)
/* First obtain the information on the stack that tells us more about
what binary is loaded, where it is loaded, etc, etc */
GET_ARGV(aux_dat, args);
-#if defined(__arm__) || defined(__mips__)
+#if defined (__arm__) || defined (__mips__)
aux_dat += 1;
#endif
argc = *(aux_dat - 1);
@@ -267,7 +270,7 @@ DL_BOOT(unsigned long args)
_dl_exit(0);
}
#ifdef DL_DEBUG
- SEND_STDERR("ELF header =");
+ SEND_STDERR("ELF header=");
SEND_ADDRESS_STDERR(load_addr, 1);
#endif
@@ -287,7 +290,7 @@ DL_BOOT(unsigned long args)
#elif defined(__powerpc__)
__asm__("\tbl _GLOBAL_OFFSET_TABLE_-4@local\n\t":"=l"(got));
#elif defined(__mips__)
- __asm__("\tmove %0, $28\n\t":"=r"(got));
+ __asm__("\tmove %0, $28\n\tsubu %0,%0,0x7ff0\n\t":"=r"(got));
#else
/* Do things the slow way in C */
{
@@ -334,7 +337,7 @@ DL_BOOT(unsigned long args)
_dl_exit(0);
found_got:
- got = (unsigned long *) (dynamic->d_un.d_val - tx_reloc +
+ got = (unsigned long *) (dynamic->d_un.d_val - tx_reloc +
(char *) header);
}
#endif
@@ -376,6 +379,14 @@ DL_BOOT(unsigned long args)
tpnt->dynamic_info[DT_TEXTREL] = 1;
}
}
+#if defined(__mips__)
+ if (dpnt->d_tag == DT_MIPS_GOTSYM)
+ mips_gotsym = (unsigned long) dpnt->d_un.d_val;
+ if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
+ mips_local_gotno = (unsigned long) dpnt->d_un.d_val;
+ if (dpnt->d_tag == DT_MIPS_SYMTABNO)
+ mips_symtabno = (unsigned long) dpnt->d_un.d_val;
+#endif
dpnt++;
}
@@ -394,7 +405,11 @@ DL_BOOT(unsigned long args)
}
app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
if (dpnt->d_tag == DT_DEBUG)
+#ifndef DO_MPROTECT_HACKS
dpnt->d_un.d_val = (unsigned long) debug_addr;
+#else
+ dpnt_debug = dpnt;
+#endif
if (dpnt->d_tag == DT_TEXTREL || SVR4_BUGCOMPAT)
app_tpnt->dynamic_info[DT_TEXTREL] = 1;
dpnt++;
@@ -446,6 +461,16 @@ DL_BOOT(unsigned long args)
}
}
}
+
+ /* Now we can store the debug structure address */
+ dpnt_debug->d_un.d_val = (unsigned long) debug_addr;
+#endif
+
+
+ /* For MIPS, we have to do special stuff to the GOT before we do
+ any relocations. */
+#if defined(__mips__)
+ PERFORM_BOOTSTRAP_GOT(got);
#endif
@@ -454,6 +479,7 @@ DL_BOOT(unsigned long args)
#ifdef DL_DEBUG
SEND_STDERR("About to do library loader relocations.\n");
#endif
+
goof = 0;
for (indx = 0; indx < 2; indx++) {
int i;
@@ -476,7 +502,6 @@ DL_BOOT(unsigned long args)
dynamic_info[DT_RELSZ]);
#endif
-
if (!rel_addr)
continue;
@@ -499,6 +524,7 @@ DL_BOOT(unsigned long args)
if (!_dl_symbol(strtab + symtab[symtab_index].st_name))
continue;
symbol_addr = load_addr + symtab[symtab_index].st_value;
+ SEND_NUMBER_STDERR(symbol_addr,1);
if (!symbol_addr) {
/* This will segfault - you cannot call a function until
diff --git a/ldso/ldso/mips/README b/ldso/ldso/mips/README
new file mode 100644
index 000000000..b54e25183
--- /dev/null
+++ b/ldso/ldso/mips/README
@@ -0,0 +1,43 @@
+Almost all of the code present in these source files was taken
+from GLIBC. In the descriptions below, all files mentioned are
+with respect to the top level GLIBC source directory accept for
+the code taken from the Linux kernel.
+
+boot1_arch.h
+------------
+Contains code to fix up the stack pointer so that the dynamic
+linker can find argc, argv and Auxillary Vector Table (AVT).
+The codes is taken from the function 'RTLD_START' in the
+file 'sysdeps/mips/dl-machine.h'.
+
+elfinterp.c
+-----------
+Contains '_dl_init_got' which initializes the GOT for the
+application being dynamically linked and loaded. The code is
+taken from the functions 'elf_machine_runtime_setup' and
+'elf_machine_got_rel' in the file 'sysdeps/mips/dl-machine.h'.
+
+ld_syscalls.h
+-------------
+Contains all the macro function prototypes for the system calls
+as well as the list of system calls supported. The macros were
+taken from the Linux kernel source 2.4.17 found in the file
+'include/asm-mips/unistd.h'.
+
+ld_sysdep.h
+-----------
+Contains bootstrap code for the dynamic linker, magic numbers
+for detecting MIPS target types and some macros. The macro
+function 'PERFORM_BOOTSTRAP_GOT' is used to relocate the dynamic
+linker's GOT so that function calls can be made. The code is
+taken from the function 'ELF_MACHINE_BEFORE_RTLD_RELOC' in the
+file 'sysdep/mips/dl-machine.h'. The other macro function
+'PERFORM_BOOTSTRAP_RELOC' is used to do the relocations for
+the dynamic loader. The code is taken from the function
+'elf_machine_rel' in the file 'sysdep/mips/dl-machine.h'.
+
+resolve.S
+---------
+Contains the low-level assembly code for the dynamic runtime
+resolver. The code is taken from the assembly code function
+'_dl_runtime_resolve' in the file 'sysdesp/mips/dl-machine.h'.
diff --git a/ldso/ldso/mips/boot1_arch.h b/ldso/ldso/mips/boot1_arch.h
index e86ff77cf..f439ee4bc 100644
--- a/ldso/ldso/mips/boot1_arch.h
+++ b/ldso/ldso/mips/boot1_arch.h
@@ -13,11 +13,8 @@ _dl_boot:
nop
0: .cpload $31
.set reorder
- # i386 ABI book says that the first entry of GOT holds
- # the address of the dynamic structure. Though MIPS ABI
- # doesn't say nothing about this, I emulate this here.
+ # Store offset of DYNAMIC section in first entry of GOT
la $4, _DYNAMIC
- # Subtract OFFSET_GP_GOT
sw $4, -0x7ff0($28)
move $4, $29
la $8, coff
diff --git a/ldso/ldso/mips/dl-startup.h b/ldso/ldso/mips/dl-startup.h
index e86ff77cf..f439ee4bc 100644
--- a/ldso/ldso/mips/dl-startup.h
+++ b/ldso/ldso/mips/dl-startup.h
@@ -13,11 +13,8 @@ _dl_boot:
nop
0: .cpload $31
.set reorder
- # i386 ABI book says that the first entry of GOT holds
- # the address of the dynamic structure. Though MIPS ABI
- # doesn't say nothing about this, I emulate this here.
+ # Store offset of DYNAMIC section in first entry of GOT
la $4, _DYNAMIC
- # Subtract OFFSET_GP_GOT
sw $4, -0x7ff0($28)
move $4, $29
la $8, coff
diff --git a/ldso/ldso/mips/dl-syscalls.h b/ldso/ldso/mips/dl-syscalls.h
index feb54d4cf..da17d63b9 100644
--- a/ldso/ldso/mips/dl-syscalls.h
+++ b/ldso/ldso/mips/dl-syscalls.h
@@ -142,4 +142,34 @@ type name(atype a, btype b, ctype c, dtype d) \
return (type) -1; \
}
+#define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \
+type name(atype a, btype b, ctype c, dtype d, etype e, ftype f) \
+{ \
+ register unsigned long __v0 asm("$2") = __NR_##name; \
+ register unsigned long __a0 asm("$4") = (unsigned long) a; \
+ register unsigned long __a1 asm("$5") = (unsigned long) b; \
+ register unsigned long __a2 asm("$6") = (unsigned long) c; \
+ register unsigned long __a3 asm("$7") = (unsigned long) d; \
+ \
+ __asm__ volatile ( \
+ ".set\tnoreorder\n\t" \
+ "lw\t$2, %6\n\t" \
+ "lw\t$8, %7\n\t" \
+ "subu\t$29, 32\n\t" \
+ "sw\t$2, 16($29)\n\t" \
+ "sw\t$8, 20($29)\n\t" \
+ "li\t$2, %5\t\t\t# " #name "\n\t" \
+ "syscall\n\t" \
+ "addiu\t$29, 32\n\t" \
+ ".set\treorder" \
+ : "=&r" (__v0), "+r" (__a3) \
+ : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_##name), \
+ "m" ((unsigned long)e), "m" ((unsigned long)f) \
+ : "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24"); \
+ \
+ if (__a3 == 0) \
+ return (type) __v0; \
+ return (type) -1; \
+}
+
#endif
diff --git a/ldso/ldso/mips/dl-sysdep.h b/ldso/ldso/mips/dl-sysdep.h
index 24cbc3d04..8bc6aaccd 100644
--- a/ldso/ldso/mips/dl-sysdep.h
+++ b/ldso/ldso/mips/dl-sysdep.h
@@ -8,36 +8,82 @@
*/
#undef 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)
+#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long *) ARGS)
+
/*
- * Initialization sequence for a GOT.
+ * Initialization sequence for the application GOT.
*/
-#define INIT_GOT(GOT_BASE,MODULE) \
-{ \
- GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \
- GOT_BASE[1] = (unsigned long) MODULE; \
-}
+#define INIT_GOT(GOT_BASE,MODULE) _dl_init_got(GOT_BASE,MODULE)
+
+
+/*
+ * Here is a macro to perform the GOT relocation. This is only
+ * used when bootstrapping the dynamic loader.
+ */
+#define PERFORM_BOOTSTRAP_GOT(got) \
+do { \
+ Elf32_Sym *sym; \
+ unsigned long i; \
+ \
+ /* Add load address displacement to all local GOT entries */ \
+ i = 2; \
+ while (i < mips_local_gotno) \
+ got[i++] += load_addr; \
+ \
+ /* Handle global GOT entries */ \
+ got += mips_local_gotno; \
+ sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + \
+ load_addr) + mips_gotsym; \
+ i = mips_symtabno - mips_gotsym; \
+ \
+ while (i--) { \
+ if (sym->st_shndx == SHN_UNDEF || \
+ sym->st_shndx == SHN_COMMON) \
+ *got = load_addr + sym->st_value; \
+ else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && \
+ *got != sym->st_value) \
+ *got += load_addr; \
+ else if (ELF32_ST_TYPE(sym->st_info) == STT_SECTION) { \
+ if (sym->st_other == 0) \
+ *got += load_addr; \
+ } \
+ else \
+ *got = load_addr + sym->st_value; \
+ \
+ got++; \
+ sym++; \
+ } \
+} while (0)
+
/*
* 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.
- *
- * !!!NOTE!!!
- *
- * For MIPS, we don't have any DT_JMPREL or DT_PLTRELSZ dynamic
- * entries, so this macro function is empty. The code contained
- * in elfinterp.c does the real relocation work.
+ * bootstrapping the dynamic loader.
*/
-#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD)
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD) \
+ switch(ELF32_R_TYPE((RELP)->r_info)) { \
+ case R_MIPS_REL32: \
+ if (symtab_index) { \
+ if (symtab_index < mips_gotsym) \
+ *REL += SYMBOL + LOAD; \
+ } \
+ else { \
+ *REL += LOAD; \
+ } \
+ break; \
+ case R_MIPS_NONE: \
+ break; \
+ default: \
+ SEND_STDERR("Aiieeee!"); \
+ _dl_exit(1); \
+ }
/*
@@ -45,19 +91,21 @@
* is done. This routine has to exit the current function, then
* call the _dl_elf_main function.
*/
-
#define START() return (void) _dl_elf_main;
-
/* Here we define the magic numbers that this dynamic loader should accept */
-
#define MAGIC1 EM_MIPS
#define MAGIC2 EM_MIPS_RS3_LE
+
+
/* Used for error messages */
#define ELF_TARGET "MIPS"
+
struct elf_resolve;
-unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt,
+ int reloc_entry);
+void _dl_init_got(unsigned long *got, struct elf_resolve *tpnt);
#define do_rem(result, n, base) result = (n % base)
diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c
new file mode 100644
index 000000000..c38a7ffa2
--- /dev/null
+++ b/ldso/ldso/mips/elfinterp.c
@@ -0,0 +1,49 @@
+/* Run an ELF binary on a linux system.
+
+ Copyright (C) 1993, Eric Youngdale.
+ 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. */
+
+
+extern int _dl_linux_resolve(void);
+
+void _dl_init_got(unsigned long *got, struct elf_resolve *tpnt)
+{
+ return;
+}
+
+unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+{
+ return 0;
+}
+
+int _dl_parse_relocation_information(struct elf_resolve *tpnt,
+ unsigned long rel_addr, unsigned long rel_size, int type)
+{
+ return 1;
+}
diff --git a/ldso/ldso/mips/ld_syscalls.h b/ldso/ldso/mips/ld_syscalls.h
index feb54d4cf..da17d63b9 100644
--- a/ldso/ldso/mips/ld_syscalls.h
+++ b/ldso/ldso/mips/ld_syscalls.h
@@ -142,4 +142,34 @@ type name(atype a, btype b, ctype c, dtype d) \
return (type) -1; \
}
+#define _syscall6(type,name,atype,a,btype,b,ctype,c,dtype,d,etype,e,ftype,f) \
+type name(atype a, btype b, ctype c, dtype d, etype e, ftype f) \
+{ \
+ register unsigned long __v0 asm("$2") = __NR_##name; \
+ register unsigned long __a0 asm("$4") = (unsigned long) a; \
+ register unsigned long __a1 asm("$5") = (unsigned long) b; \
+ register unsigned long __a2 asm("$6") = (unsigned long) c; \
+ register unsigned long __a3 asm("$7") = (unsigned long) d; \
+ \
+ __asm__ volatile ( \
+ ".set\tnoreorder\n\t" \
+ "lw\t$2, %6\n\t" \
+ "lw\t$8, %7\n\t" \
+ "subu\t$29, 32\n\t" \
+ "sw\t$2, 16($29)\n\t" \
+ "sw\t$8, 20($29)\n\t" \
+ "li\t$2, %5\t\t\t# " #name "\n\t" \
+ "syscall\n\t" \
+ "addiu\t$29, 32\n\t" \
+ ".set\treorder" \
+ : "=&r" (__v0), "+r" (__a3) \
+ : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_##name), \
+ "m" ((unsigned long)e), "m" ((unsigned long)f) \
+ : "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24"); \
+ \
+ if (__a3 == 0) \
+ return (type) __v0; \
+ return (type) -1; \
+}
+
#endif
diff --git a/ldso/ldso/mips/ld_sysdep.h b/ldso/ldso/mips/ld_sysdep.h
index 24cbc3d04..8bc6aaccd 100644
--- a/ldso/ldso/mips/ld_sysdep.h
+++ b/ldso/ldso/mips/ld_sysdep.h
@@ -8,36 +8,82 @@
*/
#undef 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)
+#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long *) ARGS)
+
/*
- * Initialization sequence for a GOT.
+ * Initialization sequence for the application GOT.
*/
-#define INIT_GOT(GOT_BASE,MODULE) \
-{ \
- GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \
- GOT_BASE[1] = (unsigned long) MODULE; \
-}
+#define INIT_GOT(GOT_BASE,MODULE) _dl_init_got(GOT_BASE,MODULE)
+
+
+/*
+ * Here is a macro to perform the GOT relocation. This is only
+ * used when bootstrapping the dynamic loader.
+ */
+#define PERFORM_BOOTSTRAP_GOT(got) \
+do { \
+ Elf32_Sym *sym; \
+ unsigned long i; \
+ \
+ /* Add load address displacement to all local GOT entries */ \
+ i = 2; \
+ while (i < mips_local_gotno) \
+ got[i++] += load_addr; \
+ \
+ /* Handle global GOT entries */ \
+ got += mips_local_gotno; \
+ sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + \
+ load_addr) + mips_gotsym; \
+ i = mips_symtabno - mips_gotsym; \
+ \
+ while (i--) { \
+ if (sym->st_shndx == SHN_UNDEF || \
+ sym->st_shndx == SHN_COMMON) \
+ *got = load_addr + sym->st_value; \
+ else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && \
+ *got != sym->st_value) \
+ *got += load_addr; \
+ else if (ELF32_ST_TYPE(sym->st_info) == STT_SECTION) { \
+ if (sym->st_other == 0) \
+ *got += load_addr; \
+ } \
+ else \
+ *got = load_addr + sym->st_value; \
+ \
+ got++; \
+ sym++; \
+ } \
+} while (0)
+
/*
* 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.
- *
- * !!!NOTE!!!
- *
- * For MIPS, we don't have any DT_JMPREL or DT_PLTRELSZ dynamic
- * entries, so this macro function is empty. The code contained
- * in elfinterp.c does the real relocation work.
+ * bootstrapping the dynamic loader.
*/
-#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD)
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD) \
+ switch(ELF32_R_TYPE((RELP)->r_info)) { \
+ case R_MIPS_REL32: \
+ if (symtab_index) { \
+ if (symtab_index < mips_gotsym) \
+ *REL += SYMBOL + LOAD; \
+ } \
+ else { \
+ *REL += LOAD; \
+ } \
+ break; \
+ case R_MIPS_NONE: \
+ break; \
+ default: \
+ SEND_STDERR("Aiieeee!"); \
+ _dl_exit(1); \
+ }
/*
@@ -45,19 +91,21 @@
* is done. This routine has to exit the current function, then
* call the _dl_elf_main function.
*/
-
#define START() return (void) _dl_elf_main;
-
/* Here we define the magic numbers that this dynamic loader should accept */
-
#define MAGIC1 EM_MIPS
#define MAGIC2 EM_MIPS_RS3_LE
+
+
/* Used for error messages */
#define ELF_TARGET "MIPS"
+
struct elf_resolve;
-unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry);
+extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt,
+ int reloc_entry);
+void _dl_init_got(unsigned long *got, struct elf_resolve *tpnt);
#define do_rem(result, n, base) result = (n % base)
diff --git a/ldso/ldso/readelflib1.c b/ldso/ldso/readelflib1.c
index d565b9290..913ac8778 100644
--- a/ldso/ldso/readelflib1.c
+++ b/ldso/ldso/readelflib1.c
@@ -308,7 +308,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
int flags;
char header[4096];
unsigned long dynamic_info[24];
- int *lpnt;
+ unsigned long *lpnt;
unsigned long libaddr;
unsigned long minvma = 0xffffffff, maxvma = 0;
@@ -553,10 +553,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
* resolved.
*/
- lpnt = (int *) dynamic_info[DT_PLTGOT];
+ lpnt = (unsigned long *) dynamic_info[DT_PLTGOT];
if (lpnt) {
- lpnt = (int *) (dynamic_info[DT_PLTGOT] + ((int) libaddr));
+ lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT] +
+ ((int) libaddr));
INIT_GOT(lpnt, tpnt);
};