[uClibc][PATCH] MIPS dynamic linker patch (1/2) for 20020425...
Steven J. Hill
sjhill at realitydiluted.com
Thu Apr 25 13:39:42 UTC 2002
This patch fixes a little buglet in the clean target of the top-level
makefile and contains MIPS specific updates for the ldso directory.
Please apply.
-Steve
diff -urN uclibc/Makefile uclibc-patched/Makefile
--- uclibc/Makefile Thu Apr 25 06:30:03 2002
+++ uclibc-patched/Makefile Thu Apr 25 07:55:00 2002
@@ -347,6 +347,7 @@
$(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 -urN uclibc/ldso/ldso/mips/README uclibc-patched/ldso/ldso/mips/README
--- uclibc/ldso/ldso/mips/README Tue Apr 2 15:12:37 2002
+++ uclibc-patched/ldso/ldso/mips/README Thu Apr 4 09:41:13 2002
@@ -7,22 +7,18 @@
------------
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'.
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 +27,17 @@
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'.
diff -urN uclibc/ldso/ldso/mips/boot1_arch.h uclibc-patched/ldso/ldso/mips/boot1_arch.h
--- uclibc/ldso/ldso/mips/boot1_arch.h Tue Apr 9 10:46:45 2002
+++ uclibc-patched/ldso/ldso/mips/boot1_arch.h Wed Apr 24 18:41:54 2002
@@ -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("
@@ -23,6 +22,14 @@
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 -urN uclibc/ldso/ldso/mips/elfinterp.c uclibc-patched/ldso/ldso/mips/elfinterp.c
--- uclibc/ldso/ldso/mips/elfinterp.c Tue Apr 2 15:12:37 2002
+++ uclibc-patched/ldso/ldso/mips/elfinterp.c Tue Apr 23 15:52:03 2002
@@ -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 at 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 return_addr, unsigned long old_gpreg, unsigned long stub_pc)
+{
+ 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 */
+ rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr);
+ rel_size = rel_size / sizeof(Elf32_Rel);
+
+ 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 -urN uclibc/ldso/ldso/mips/ld_sysdep.h uclibc-patched/ldso/ldso/mips/ld_sysdep.h
--- uclibc/ldso/ldso/mips/ld_sysdep.h Tue Apr 9 10:46:45 2002
+++ uclibc-patched/ldso/ldso/mips/ld_sysdep.h Wed Apr 24 18:46:20 2002
@@ -1,3 +1,5 @@
+/* vi: set sw=4 ts=4: */
+
/*
* Various assmbly language/system dependent hacks that are required
* so that we can minimize the amount of platform specific code.
@@ -20,46 +22,111 @@
/*
* 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); \
+ if (*GOT_BASE == 0) \
+ _dl_dprintf(2, "INIT_GOT(SHN_UNDEF) zero: %s\n", \
+ strtab + sym->st_name); \
+ } \
+ } \
+ else if (sym->st_shndx == SHN_COMMON) { \
+ *GOT_BASE = (unsigned long) _dl_find_hash(strtab + \
+ sym->st_name, MODULE->symbol_scope, NULL, 0); \
+ if (*GOT_BASE == 0) \
+ _dl_dprintf(2, "INIT_GOT(SHN_COMMON) zero: %s\n", \
+ strtab + sym->st_name); \
+ } \
+ 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); \
+ if (*GOT_BASE == 0) \
+ _dl_dprintf(2, "INIT_GOT(END) zero: %s\n", \
+ strtab + sym->st_name); \
+ } \
+ \
+ ++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 +134,33 @@
* 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 +172,8 @@
#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 return_addr, unsigned long old_gpreg, unsigned long stub_pc);
+
#define do_rem(result, n, base) result = (n % base)
diff -urN uclibc/ldso/ldso/mips/resolve.S uclibc-patched/ldso/ldso/mips/resolve.S
--- uclibc/ldso/ldso/mips/resolve.S Tue Mar 19 11:05:51 2002
+++ uclibc-patched/ldso/ldso/mips/resolve.S Wed Apr 24 10:22:37 2002
@@ -23,7 +23,7 @@
addu $25, 8 # t9 ($25) now points at .cpload instruction
.cpload $25 # Compute GP
.set reorder
- move $2, $31 # Save slot call pc
+ move $2, $31 # Save stub pc of caller
subu $29, 40 # Save arguments and sp value in stack
.cprestore 32
sw $15, 36($29)
@@ -43,6 +43,6 @@
lw $7, 28($29)
addu $29, 40
move $25, $2
- jr $25
+ jr $25
.size _dl_linux_resolve,.-_dl_linux_resolve
.end _dl_linux_resolve
More information about the uClibc
mailing list