summaryrefslogtreecommitdiff
path: root/ldso/ldso/mips
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2002-05-02 13:36:53 +0000
committerEric Andersen <andersen@codepoet.org>2002-05-02 13:36:53 +0000
commit4a5a81ac165c040935a8807a580db49d381dc443 (patch)
tree7fcd5458f95399731b537e1cfd22538ee2d03c19 /ldso/ldso/mips
parent776eae615326f6439734b05fa39c335bf2dc681b (diff)
Patch from Steven J. Hill <sjhill@realitydiluted.com>:
I am very pleased to announce that the MIPS dynamic linker/loader for uClibc is now working. It works on big and little endian platforms. A few minor changes were needed to avoid breaking ldd, and since this makes some non-trivial changes, I have tested on x86, arm, and powerpc to be sure thoese arches didn't get broken. Excellent work Steven!
Diffstat (limited to 'ldso/ldso/mips')
-rw-r--r--ldso/ldso/mips/README35
-rw-r--r--ldso/ldso/mips/boot1_arch.h12
-rw-r--r--ldso/ldso/mips/dl-startup.h12
-rw-r--r--ldso/ldso/mips/dl-sysdep.h175
-rw-r--r--ldso/ldso/mips/elfinterp.c105
-rw-r--r--ldso/ldso/mips/ld_sysdep.h175
-rw-r--r--ldso/ldso/mips/resolve.S23
7 files changed, 381 insertions, 156 deletions
diff --git a/ldso/ldso/mips/README b/ldso/ldso/mips/README
index b54e25183..520a5eeb6 100644
--- a/ldso/ldso/mips/README
+++ b/ldso/ldso/mips/README
@@ -1,28 +1,29 @@
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.
+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'.
+The code 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'.
+Contains the runtime resolver code taken from the function
+'__dl_runtime_resolve' in 'sysdeps/mips/dl-machine.h'. Also
+contains the function to perform relocations for objects
+other than the linker itself. The code was taken from the
+function 'elf_machine_rel' in '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'.
+Contains all the macro functions for the system calls as well
+as the list of system calls supported. The functions were taken
+from the Linux kernel source 2.4.17 and can be found in the
+file 'include/asm-mips/unistd.h'.
ld_sysdep.h
-----------
@@ -31,13 +32,19 @@ 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
+file 'sysdeps/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'.
+'elf_machine_rel' in the file 'sysdeps/mips/dl-machine.h'. The
+final macro function is '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 'sysdeps/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'.
+'_dl_runtime_resolve' in the file 'sysdeps/mips/dl-machine.h'.
+The code looks a bit different since we only need to pass the
+symbol index and the old GP register.
diff --git a/ldso/ldso/mips/boot1_arch.h b/ldso/ldso/mips/boot1_arch.h
index f439ee4bc..05aaf9ebb 100644
--- a/ldso/ldso/mips/boot1_arch.h
+++ b/ldso/ldso/mips/boot1_arch.h
@@ -1,7 +1,6 @@
/* 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. See arm/boot1_arch.h for an example of what
- * can be done.
+ * needed for this architecture.
*/
asm("
@@ -13,7 +12,6 @@ _dl_boot:
nop
0: .cpload $31
.set reorder
- # Store offset of DYNAMIC section in first entry of GOT
la $4, _DYNAMIC
sw $4, -0x7ff0($28)
move $4, $29
@@ -23,6 +21,14 @@ coff: subu $8, $31, $8
la $25, _dl_boot2
addu $25, $8
jalr $25
+ lw $4, 0($29)
+ la $5, 4($29)
+ sll $6, $4, 2
+ addu $6, $6, $5
+ addu $6, $6, 4
+ la $7, _dl_elf_main
+ lw $25, 0($7)
+ jr $25
");
#define _dl_boot _dl_boot2
diff --git a/ldso/ldso/mips/dl-startup.h b/ldso/ldso/mips/dl-startup.h
index f439ee4bc..05aaf9ebb 100644
--- a/ldso/ldso/mips/dl-startup.h
+++ b/ldso/ldso/mips/dl-startup.h
@@ -1,7 +1,6 @@
/* 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. See arm/boot1_arch.h for an example of what
- * can be done.
+ * needed for this architecture.
*/
asm("
@@ -13,7 +12,6 @@ _dl_boot:
nop
0: .cpload $31
.set reorder
- # Store offset of DYNAMIC section in first entry of GOT
la $4, _DYNAMIC
sw $4, -0x7ff0($28)
move $4, $29
@@ -23,6 +21,14 @@ coff: subu $8, $31, $8
la $25, _dl_boot2
addu $25, $8
jalr $25
+ lw $4, 0($29)
+ la $5, 4($29)
+ sll $6, $4, 2
+ addu $6, $6, $5
+ addu $6, $6, 4
+ la $7, _dl_elf_main
+ lw $25, 0($7)
+ jr $25
");
#define _dl_boot _dl_boot2
diff --git a/ldso/ldso/mips/dl-sysdep.h b/ldso/ldso/mips/dl-sysdep.h
index 8bc6aaccd..f54e812b7 100644
--- a/ldso/ldso/mips/dl-sysdep.h
+++ b/ldso/ldso/mips/dl-sysdep.h
@@ -1,5 +1,7 @@
+/* vi: set sw=4 ts=4: */
+
/*
- * Various assmbly language/system dependent hacks that are required
+ * Various assmbly language/system dependent hacks that are required
* so that we can minimize the amount of platform specific code.
*/
@@ -20,46 +22,102 @@
/*
* Initialization sequence for the application GOT.
*/
-#define INIT_GOT(GOT_BASE,MODULE) _dl_init_got(GOT_BASE,MODULE)
+#define INIT_GOT(GOT_BASE,MODULE) \
+do { \
+ Elf32_Sym *sym; \
+ char *strtab; \
+ unsigned long i; \
+ \
+ /* Check if this is the dynamic linker itself */ \
+ if (MODULE->libtype == program_interpreter) \
+ continue; \
+ \
+ /* Fill in first two GOT entries according to the ABI */ \
+ GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \
+ GOT_BASE[1] = (unsigned long) MODULE; \
+ \
+ /* Add load address displacement to all local GOT entries */ \
+ i = 2; \
+ while (i < MODULE->mips_local_gotno) \
+ GOT_BASE[i++] += (unsigned long) MODULE->loadaddr; \
+ \
+ /* Handle global GOT entries */ \
+ GOT_BASE += MODULE->mips_local_gotno; \
+ sym = (Elf32_Sym *) (MODULE->dynamic_info[DT_SYMTAB] + \
+ (unsigned long) MODULE->loadaddr) + MODULE->mips_gotsym; \
+ strtab = (char *) (MODULE->dynamic_info[DT_STRTAB] + \
+ (unsigned long) MODULE->loadaddr); \
+ i = MODULE->mips_symtabno - MODULE->mips_gotsym; \
+ while (i--) { \
+ if (sym->st_shndx == SHN_UNDEF) { \
+ if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && \
+ sym->st_value) \
+ *GOT_BASE = sym->st_value + \
+ (unsigned long) MODULE->loadaddr; \
+ else { \
+ *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \
+ sym->st_name, MODULE->symbol_scope, NULL, 0); \
+ } \
+ } \
+ else if (sym->st_shndx == SHN_COMMON) { \
+ *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \
+ sym->st_name, MODULE->symbol_scope, NULL, 0); \
+ } \
+ else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && \
+ *GOT_BASE != sym->st_value) \
+ *GOT_BASE += (unsigned long) MODULE->loadaddr; \
+ else if (ELF32_ST_TYPE(sym->st_info) == STT_SECTION) { \
+ if (sym->st_other == 0) \
+ *GOT_BASE += (unsigned long) MODULE->loadaddr; \
+ } \
+ else { \
+ *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \
+ sym->st_name, MODULE->symbol_scope, NULL, 0); \
+ } \
+ \
+ ++GOT_BASE; \
+ ++sym; \
+ } \
+} while (0)
/*
- * Here is a macro to perform the GOT relocation. This is only
+ * 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++; \
- } \
+#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 < tpnt->mips_local_gotno) \
+ got[i++] += load_addr; \
+ \
+ /* Handle global GOT entries */ \
+ got += tpnt->mips_local_gotno; \
+ sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + \
+ load_addr) + tpnt->mips_gotsym; \
+ i = tpnt->mips_symtabno - tpnt->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)
@@ -67,31 +125,33 @@ do { \
* Here is a macro to perform a relocation. This is only used when
* bootstrapping the dynamic loader.
*/
-#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); \
+#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 < tpnt->mips_gotsym) \
+ *REL += SYMBOL; \
+ } \
+ else { \
+ *REL += LOAD; \
+ } \
+ break; \
+ case R_MIPS_NONE: \
+ break; \
+ default: \
+ SEND_STDERR("Aiieeee!"); \
+ _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.
+ * call the _dl_elf_main function. For MIPS, we do it in assembly
+ * because the stack doesn't get properly restored otherwise. Got look
+ * at boot1_arch.h
*/
-#define START() return (void) _dl_elf_main;
+#define START()
/* Here we define the magic numbers that this dynamic loader should accept */
@@ -103,9 +163,8 @@ do { \
#define ELF_TARGET "MIPS"
-struct elf_resolve;
-extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt,
- int reloc_entry);
-void _dl_init_got(unsigned long *got, struct elf_resolve *tpnt);
+unsigned long _dl_linux_resolver(unsigned long sym_index,
+ unsigned long old_gpreg);
+
#define do_rem(result, n, base) result = (n % base)
diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c
index c38a7ffa2..e6c3781b8 100644
--- a/ldso/ldso/mips/elfinterp.c
+++ b/ldso/ldso/mips/elfinterp.c
@@ -1,6 +1,7 @@
+/* vi: set sw=4 ts=4: */
+
/* 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
@@ -32,18 +33,112 @@
extern int _dl_linux_resolve(void);
-void _dl_init_got(unsigned long *got, struct elf_resolve *tpnt)
+#define OFFSET_GP_GOT 0x7ff0
+
+unsigned long _dl_linux_resolver(unsigned long sym_index,
+ unsigned long old_gpreg)
{
+ unsigned long *got = (unsigned long *) (old_gpreg - OFFSET_GP_GOT);
+ struct elf_resolve *tpnt = (struct elf_resolve *) got[1];
+ Elf32_Sym *sym;
+ char *strtab;
+ unsigned long local_gotno;
+ unsigned long gotsym;
+ unsigned long value;
+
+ gotsym = tpnt->mips_gotsym;
+ local_gotno = tpnt->mips_local_gotno;
+
+ sym = ((Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr)) +
+ 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);
+
+ *(got + local_gotno + sym_index - gotsym) = value;
+
+#ifdef DL_DEBUG
+ _dl_dprintf(2, "---RESOLVER---\n");
+ _dl_dprintf(2, "SYMTAB INDEX: %i\n", sym_index);
+ _dl_dprintf(2, " GOTSYM: %i\n", gotsym);
+ _dl_dprintf(2, " LOCAL GOTNO: %i\n", local_gotno);
+ _dl_dprintf(2, " VALUE: %x\n", value);
+ _dl_dprintf(2, " SYMBOL: %s\n\n", strtab + sym->st_name);
+#endif
+
+ return value;
+}
+
+void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt,
+ unsigned long rel_addr, unsigned long rel_size, int type)
+{
+ /* Nothing to do */
return;
}
-unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
+int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
+ unsigned long rel_size, int type)
{
+ /* Nothing to do */
return 0;
}
-
+
int _dl_parse_relocation_information(struct elf_resolve *tpnt,
unsigned long rel_addr, unsigned long rel_size, int type)
{
- return 1;
+ Elf32_Sym *symtab;
+ Elf32_Rel *rpnt;
+ char *strtab;
+ unsigned long *got;
+ unsigned long *reloc_addr;
+ unsigned long symbol_addr;
+ int i, reloc_type, symtab_index;
+
+ /* Now parse the relocation information */
+ rel_size = rel_size / sizeof(Elf32_Rel);
+ rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
+
+ symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
+ strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
+ got = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT] + 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);
+ symtab_index = ELF32_R_SYM(rpnt->r_info);
+ symbol_addr = 0;
+
+ if (!symtab_index && tpnt->libtype == program_interpreter)
+ continue;
+
+ switch (reloc_type) {
+ case R_MIPS_REL32:
+ if (symtab_index) {
+ if (symtab_index < tpnt->mips_gotsym)
+ *reloc_addr +=
+ symtab[symtab_index].st_value +
+ (unsigned long) tpnt->loadaddr;
+ else {
+ *reloc_addr += got[symtab_index + tpnt->mips_local_gotno -
+ tpnt->mips_gotsym];
+ }
+ }
+ else {
+ *reloc_addr += (unsigned long) tpnt->loadaddr;
+ }
+ break;
+ case R_MIPS_NONE:
+ break;
+ default:
+ _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
+ if (symtab_index)
+ _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
+ _dl_exit(1);
+ };
+
+ };
+ return 0;
}
diff --git a/ldso/ldso/mips/ld_sysdep.h b/ldso/ldso/mips/ld_sysdep.h
index 8bc6aaccd..f54e812b7 100644
--- a/ldso/ldso/mips/ld_sysdep.h
+++ b/ldso/ldso/mips/ld_sysdep.h
@@ -1,5 +1,7 @@
+/* vi: set sw=4 ts=4: */
+
/*
- * Various assmbly language/system dependent hacks that are required
+ * Various assmbly language/system dependent hacks that are required
* so that we can minimize the amount of platform specific code.
*/
@@ -20,46 +22,102 @@
/*
* Initialization sequence for the application GOT.
*/
-#define INIT_GOT(GOT_BASE,MODULE) _dl_init_got(GOT_BASE,MODULE)
+#define INIT_GOT(GOT_BASE,MODULE) \
+do { \
+ Elf32_Sym *sym; \
+ char *strtab; \
+ unsigned long i; \
+ \
+ /* Check if this is the dynamic linker itself */ \
+ if (MODULE->libtype == program_interpreter) \
+ continue; \
+ \
+ /* Fill in first two GOT entries according to the ABI */ \
+ GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \
+ GOT_BASE[1] = (unsigned long) MODULE; \
+ \
+ /* Add load address displacement to all local GOT entries */ \
+ i = 2; \
+ while (i < MODULE->mips_local_gotno) \
+ GOT_BASE[i++] += (unsigned long) MODULE->loadaddr; \
+ \
+ /* Handle global GOT entries */ \
+ GOT_BASE += MODULE->mips_local_gotno; \
+ sym = (Elf32_Sym *) (MODULE->dynamic_info[DT_SYMTAB] + \
+ (unsigned long) MODULE->loadaddr) + MODULE->mips_gotsym; \
+ strtab = (char *) (MODULE->dynamic_info[DT_STRTAB] + \
+ (unsigned long) MODULE->loadaddr); \
+ i = MODULE->mips_symtabno - MODULE->mips_gotsym; \
+ while (i--) { \
+ if (sym->st_shndx == SHN_UNDEF) { \
+ if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && \
+ sym->st_value) \
+ *GOT_BASE = sym->st_value + \
+ (unsigned long) MODULE->loadaddr; \
+ else { \
+ *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \
+ sym->st_name, MODULE->symbol_scope, NULL, 0); \
+ } \
+ } \
+ else if (sym->st_shndx == SHN_COMMON) { \
+ *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \
+ sym->st_name, MODULE->symbol_scope, NULL, 0); \
+ } \
+ else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC && \
+ *GOT_BASE != sym->st_value) \
+ *GOT_BASE += (unsigned long) MODULE->loadaddr; \
+ else if (ELF32_ST_TYPE(sym->st_info) == STT_SECTION) { \
+ if (sym->st_other == 0) \
+ *GOT_BASE += (unsigned long) MODULE->loadaddr; \
+ } \
+ else { \
+ *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \
+ sym->st_name, MODULE->symbol_scope, NULL, 0); \
+ } \
+ \
+ ++GOT_BASE; \
+ ++sym; \
+ } \
+} while (0)
/*
- * Here is a macro to perform the GOT relocation. This is only
+ * 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++; \
- } \
+#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 < tpnt->mips_local_gotno) \
+ got[i++] += load_addr; \
+ \
+ /* Handle global GOT entries */ \
+ got += tpnt->mips_local_gotno; \
+ sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + \
+ load_addr) + tpnt->mips_gotsym; \
+ i = tpnt->mips_symtabno - tpnt->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)
@@ -67,31 +125,33 @@ do { \
* Here is a macro to perform a relocation. This is only used when
* bootstrapping the dynamic loader.
*/
-#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); \
+#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 < tpnt->mips_gotsym) \
+ *REL += SYMBOL; \
+ } \
+ else { \
+ *REL += LOAD; \
+ } \
+ break; \
+ case R_MIPS_NONE: \
+ break; \
+ default: \
+ SEND_STDERR("Aiieeee!"); \
+ _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.
+ * call the _dl_elf_main function. For MIPS, we do it in assembly
+ * because the stack doesn't get properly restored otherwise. Got look
+ * at boot1_arch.h
*/
-#define START() return (void) _dl_elf_main;
+#define START()
/* Here we define the magic numbers that this dynamic loader should accept */
@@ -103,9 +163,8 @@ do { \
#define ELF_TARGET "MIPS"
-struct elf_resolve;
-extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt,
- int reloc_entry);
-void _dl_init_got(unsigned long *got, struct elf_resolve *tpnt);
+unsigned long _dl_linux_resolver(unsigned long sym_index,
+ unsigned long old_gpreg);
+
#define do_rem(result, n, base) result = (n % base)
diff --git a/ldso/ldso/mips/resolve.S b/ldso/ldso/mips/resolve.S
index b160b1cfb..b6dda82d7 100644
--- a/ldso/ldso/mips/resolve.S
+++ b/ldso/ldso/mips/resolve.S
@@ -1,4 +1,4 @@
-/*
+ /*
* Linux dynamic resolving code for MIPS. Fixes up the GOT entry as
* indicated in register t8 and jumps to the resolved address. Shamelessly
* ripped from 'sysdeps/mips/dl-machine.h' in glibc-2.2.5.
@@ -23,26 +23,19 @@ _dl_linux_resolve:
addu $25, 8 # t9 ($25) now points at .cpload instruction
.cpload $25 # Compute GP
.set reorder
- move $2, $31 # Save slot call pc
- subu $29, 40 # Save arguments and sp value in stack
- .cprestore 32
- sw $15, 36($29)
+ subu $29, 32
+ .cprestore 28
sw $4, 16($29)
sw $5, 20($29)
- sw $6, 24($29)
- sw $7, 28($29)
+ sw $15, 24($29)
move $4, $24
- move $5, $15
- move $6, $3
- move $7, $2
+ move $5, $3
jal _dl_linux_resolver
- lw $31, 36($29)
+ lw $31, 24($29)
lw $4, 16($29)
lw $5, 20($29)
- lw $6, 24($29)
- lw $7, 28($29)
- addu $29, 40
+ addu $29, 32
move $25, $2
- jr $25
+ jr $25
.size _dl_linux_resolve,.-_dl_linux_resolve
.end _dl_linux_resolve