[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