summaryrefslogtreecommitdiff
path: root/ldso/ldso/mips/dl-sysdep.h
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/dl-sysdep.h
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/dl-sysdep.h')
-rw-r--r--ldso/ldso/mips/dl-sysdep.h175
1 files changed, 117 insertions, 58 deletions
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)