Browse Source

This commit contains a patch from Stefan Allius <allius@atecom.com> to change
how uClibc handles _init and _fini, allowing shared lib constructors and
destructors to initialize things in the correct sequence. Stefan ported the SH
architecture. I then ported x86, arm, and mips. x86 and arm are working fine,
but I don't think I quite got things correct for mips.

Eric Andersen 22 years ago
parent
commit
b58a631942

+ 3 - 4
extra/gcc-uClibc/gcc-uClibc.c

@@ -122,7 +122,7 @@ int main(int argc, char **argv)
 	int use_build_dir = 0, linking = 1, use_static_linking = 0;
 	int use_build_dir = 0, linking = 1, use_static_linking = 0;
 	int use_stdinc = 1, use_nostdinc_plus = 0, use_start = 1, use_stdlib = 1, use_pic = 0;
 	int use_stdinc = 1, use_nostdinc_plus = 0, use_start = 1, use_stdlib = 1, use_pic = 0;
 	int source_count = 0, use_rpath = 0, verbose = 0;
 	int source_count = 0, use_rpath = 0, verbose = 0;
-	int ctor_dtor = 0, cplusplus = 0;
+	int ctor_dtor = 1, cplusplus = 0;
 	int i, j, k, l, m, n;
 	int i, j, k, l, m, n;
 	char ** gcc_argv;
 	char ** gcc_argv;
 	char ** gcc_argument;
 	char ** gcc_argument;
@@ -165,7 +165,6 @@ int main(int argc, char **argv)
 		GPLUSPLUS_BIN[len-1]='+';
 		GPLUSPLUS_BIN[len-1]='+';
 		GPLUSPLUS_BIN[len-2]='+';
 		GPLUSPLUS_BIN[len-2]='+';
 	    }
 	    }
-	    ctor_dtor = 1;
 	    cplusplus = 1;
 	    cplusplus = 1;
 	    use_nostdinc_plus = 1;
 	    use_nostdinc_plus = 1;
 	}
 	}
@@ -307,8 +306,8 @@ int main(int argc, char **argv)
 					} else if (strcmp("--uclibc-use-rpath",argv[i]) == 0) {
 					} else if (strcmp("--uclibc-use-rpath",argv[i]) == 0) {
 					    use_rpath = 1;
 					    use_rpath = 1;
 					    argv[i]='\0';
 					    argv[i]='\0';
-					} else if (strcmp("--uclibc-ctors",argv[i]) == 0) {
+					} else if (strcmp("--uclibc-no-ctors",argv[i]) == 0) {
-					    ctor_dtor = 1;
+					    ctor_dtor = 0;
 					    argv[i]='\0';
 					    argv[i]='\0';
 					}
 					}
 					break;
 					break;

+ 4 - 1
extra/scripts/get-needed-libgcc-objects.sh

@@ -48,7 +48,9 @@ echo Extracting referenced libgcc.a objects ...
 
 
 rm -f obj.need.0
 rm -f obj.need.0
 touch obj.need.0
 touch obj.need.0
-while [ -s obj.need ] && ! cmp -s obj.need obj.need.0 ; do
+
+cmp -s obj.need obj.need.0 ; state=$?
+while [ -s obj.need ] && [ $state -ne 0 ] ; do
     (cd tmp-gcc && cat ../obj.need | sort | uniq | xargs $LD -r -o ../libgcc.ldr)
     (cd tmp-gcc && cat ../obj.need | sort | uniq | xargs $LD -r -o ../libgcc.ldr)
     cp obj.need obj.need.0
     cp obj.need obj.need.0
     if $NM --undefined-only libgcc.ldr > sym.need ; then
     if $NM --undefined-only libgcc.ldr > sym.need ; then
@@ -58,6 +60,7 @@ while [ -s obj.need ] && ! cmp -s obj.need obj.need.0 ; do
 	    fi
 	    fi
 	done
 	done
     fi
     fi
+    cmp -s obj.need obj.need.0 ; state=$?
 done
 done
 
 
 cat obj.need | sort | uniq > obj.need.0
 cat obj.need | sort | uniq > obj.need.0

+ 1 - 1
extra/scripts/initfini.pl

@@ -84,7 +84,7 @@ while(<INITFINI>) {
 	$omitcrtn = 0;
 	$omitcrtn = 0;
 	next;
 	next;
     }
     }
-    if (/^i_am_not_a_leaf/) {
+    if (/i_am_not_a_leaf/) {
 	$discard = 1;
 	$discard = 1;
 	next;
 	next;
     }
     }

+ 1 - 2
ldso/ldso/arm/elfinterp.c

@@ -236,8 +236,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
 		}
 		}
 		else if (res >0)
 		else if (res >0)
 		{
 		{
-			_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
+			_dl_dprintf(2, "can't resolve symbol\n");
-					_dl_progname, strtab + symtab[symtab_index].st_name);
 			goof += res;
 			goof += res;
 		}
 		}
 	  }
 	  }

+ 17 - 16
ldso/ldso/dl-elf.c

@@ -318,16 +318,13 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	Elf32_Dyn *dpnt;
 	Elf32_Dyn *dpnt;
 	struct elf_resolve *tpnt;
 	struct elf_resolve *tpnt;
 	elf_phdr *ppnt;
 	elf_phdr *ppnt;
-	int piclib;
 	char *status;
 	char *status;
-	int flags;
 	char header[4096];
 	char header[4096];
 	unsigned long dynamic_info[24];
 	unsigned long dynamic_info[24];
 	unsigned long *lpnt;
 	unsigned long *lpnt;
 	unsigned long libaddr;
 	unsigned long libaddr;
 	unsigned long minvma = 0xffffffff, maxvma = 0;
 	unsigned long minvma = 0xffffffff, maxvma = 0;
-	int i;
+	int i, flags, piclib, infile;
-	int infile;
 
 
 	/* If this file is already loaded, skip this step */
 	/* If this file is already loaded, skip this step */
 	tpnt = _dl_check_hashed_files(libname);
 	tpnt = _dl_check_hashed_files(libname);
@@ -544,28 +541,32 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 #if defined(__mips__)
 #if defined(__mips__)
 	{
 	{
 		
 		
-		int i = 1;
+		int indx = 1;
 		Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr;
 		Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr;
 
 
 		while(dpnt->d_tag) {
 		while(dpnt->d_tag) {
 			dpnt++;
 			dpnt++;
-			i++;
+			indx++;
 		}
 		}
-		dynamic_size = i;
+		dynamic_size = indx;
 	}
 	}
 #endif
 #endif
 
 
-	for (i = 0; i < dynamic_size; i++) 
 	{
 	{
-		if (dpnt->d_tag > DT_JMPREL) {
+		unsigned long indx;
+
+		for (indx = 0; indx < dynamic_size; indx++) 
+		{
+			if (dpnt->d_tag > DT_JMPREL) {
+				dpnt++;
+				continue;
+			}
+			dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
+			if (dpnt->d_tag == DT_TEXTREL || SVR4_BUGCOMPAT)
+				dynamic_info[DT_TEXTREL] = 1;
 			dpnt++;
 			dpnt++;
-			continue;
+		};
-		}
+	}
-		dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
-		if (dpnt->d_tag == DT_TEXTREL || SVR4_BUGCOMPAT)
-			dynamic_info[DT_TEXTREL] = 1;
-		dpnt++;
-	};
 
 
 	/* If the TEXTREL is set, this means that we need to make the pages
 	/* If the TEXTREL is set, this means that we need to make the pages
 	   writable before we perform relocations.  Do this now. They get set
 	   writable before we perform relocations.  Do this now. They get set

+ 1 - 2
ldso/ldso/i386/elfinterp.c

@@ -230,8 +230,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
 		}
 		}
 		else if (res >0)
 		else if (res >0)
 		{
 		{
-			_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
+			_dl_dprintf(2, "can't resolve symbol\n");
-					_dl_progname, strtab + symtab[symtab_index].st_name);
 			goof += res;
 			goof += res;
 		}
 		}
 	  }
 	  }

+ 30 - 8
ldso/ldso/ldso.c

@@ -303,12 +303,12 @@ LD_BOOT(unsigned long args)
   __asm__("\tmove %0, $28\n\tsubu %0,%0,0x7ff0\n\t":"=r"(got));
   __asm__("\tmove %0, $28\n\tsubu %0,%0,0x7ff0\n\t":"=r"(got));
 #elif defined(__sh__)
 #elif defined(__sh__)
   __asm__(
   __asm__(
-"	   mov.l    1f, %0"
+"       mov.l    1f, %0\n"
-"	   mova     1f, r0"
+"       mova     1f, r0\n"
-"	   bra      2f"
+"       bra      2f\n"
-"	   add r0,  %0"
+"       add r0,  %0\n"
-"	   .balign  4"
+"       .balign  4\n"
-"1:	   .long    _GLOBAL_OFFSET_TABLE_"
+"1:     .long    _GLOBAL_OFFSET_TABLE_\n"
 "2:" : "=r" (got) : : "r0");
 "2:" : "=r" (got) : : "r0");
 #elif defined(__cris__)
 #elif defined(__cris__)
   __asm__("\tmove.d $pc,%0\n\tsub.d .:GOTOFF,%0\n\t":"=r"(got));
   __asm__("\tmove.d $pc,%0\n\tsub.d .:GOTOFF,%0\n\t":"=r"(got));
@@ -629,6 +629,13 @@ LD_BOOT(unsigned long args)
 	START();
 	START();
 }
 }
 
 
+#if defined (SUPPORT_LD_DEBUG)
+static void debug_fini (int status, void *arg)
+{
+	(void)status;
+	_dl_dprintf(_dl_debug_file,"\ncalling fini: %s\n\n", (const char*)arg);
+}
+#endif    
 
 
 static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt, 
 static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt, 
 		unsigned long load_addr, unsigned long *hash_addr, Elf32_auxv_t auxvt[AT_EGID + 1], 
 		unsigned long load_addr, unsigned long *hash_addr, Elf32_auxv_t auxvt[AT_EGID + 1], 
@@ -642,7 +649,9 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 	struct elf_resolve *tpnt1;
 	struct elf_resolve *tpnt1;
 	unsigned long brk_addr, *lpnt;
 	unsigned long brk_addr, *lpnt;
 	int (*_dl_atexit) (void *);
 	int (*_dl_atexit) (void *);
-
+#if defined (SUPPORT_LD_DEBUG)
+	int (*_dl_on_exit) (void (*FUNCTION)(int STATUS, void *ARG),void*);
+#endif
 
 
 	/* Now we have done the mandatory linking of some things.  We are now
 	/* Now we have done the mandatory linking of some things.  We are now
 	   free to start using global variables, since these things have all been
 	   free to start using global variables, since these things have all been
@@ -1196,6 +1205,10 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 	}
 	}
 #endif
 #endif
 	_dl_atexit = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit", NULL, NULL, symbolrel);
 	_dl_atexit = (int (*)(void *)) (intptr_t) _dl_find_hash("atexit", NULL, NULL, symbolrel);
+#if defined (SUPPORT_LD_DEBUG)
+	_dl_on_exit = (int (*)(void (*)(int, void *),void*)) 
+		(intptr_t) _dl_find_hash("on_exit", NULL, NULL, symbolrel);
+#endif
 
 
 	/*
 	/*
 	 * OK, fix one more thing - set up the debug_addr structure to point
 	 * OK, fix one more thing - set up the debug_addr structure to point
@@ -1246,6 +1259,12 @@ static void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *a
 		}
 		}
 		if (_dl_atexit && tpnt->dynamic_info[DT_FINI]) {
 		if (_dl_atexit && tpnt->dynamic_info[DT_FINI]) {
 			(*_dl_atexit) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
 			(*_dl_atexit) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
+#if defined (SUPPORT_LD_DEBUG)
+			if(_dl_debug && _dl_on_exit)
+			{
+				(*_dl_on_exit)(debug_fini, tpnt->libname);
+			}
+#endif
 		}
 		}
 #ifdef LD_DEBUG
 #ifdef LD_DEBUG
 		else {
 		else {
@@ -1318,7 +1337,10 @@ int _dl_fixup(struct elf_resolve *tpnt)
 					tpnt->dynamic_info[DT_PLTRELSZ], 0);
 					tpnt->dynamic_info[DT_PLTRELSZ], 0);
 	}
 	}
 #if defined (SUPPORT_LD_DEBUG)
 #if defined (SUPPORT_LD_DEBUG)
-	if(_dl_debug) _dl_dprintf(_dl_debug_file,"\nrelocation processing: %s; finished\n\n", tpnt->libname);	
+	if(_dl_debug) {
+		_dl_dprintf(_dl_debug_file,"\nrelocation processing: %s", tpnt->libname);     
+		_dl_dprintf(_dl_debug_file,"; finished\n\n");
+	}
 #endif    
 #endif    
 	return goof;
 	return goof;
 }
 }

+ 17 - 16
ldso/ldso/readelflib1.c

@@ -318,16 +318,13 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	Elf32_Dyn *dpnt;
 	Elf32_Dyn *dpnt;
 	struct elf_resolve *tpnt;
 	struct elf_resolve *tpnt;
 	elf_phdr *ppnt;
 	elf_phdr *ppnt;
-	int piclib;
 	char *status;
 	char *status;
-	int flags;
 	char header[4096];
 	char header[4096];
 	unsigned long dynamic_info[24];
 	unsigned long dynamic_info[24];
 	unsigned long *lpnt;
 	unsigned long *lpnt;
 	unsigned long libaddr;
 	unsigned long libaddr;
 	unsigned long minvma = 0xffffffff, maxvma = 0;
 	unsigned long minvma = 0xffffffff, maxvma = 0;
-	int i;
+	int i, flags, piclib, infile;
-	int infile;
 
 
 	/* If this file is already loaded, skip this step */
 	/* If this file is already loaded, skip this step */
 	tpnt = _dl_check_hashed_files(libname);
 	tpnt = _dl_check_hashed_files(libname);
@@ -544,28 +541,32 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 #if defined(__mips__)
 #if defined(__mips__)
 	{
 	{
 		
 		
-		int i = 1;
+		int indx = 1;
 		Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr;
 		Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr;
 
 
 		while(dpnt->d_tag) {
 		while(dpnt->d_tag) {
 			dpnt++;
 			dpnt++;
-			i++;
+			indx++;
 		}
 		}
-		dynamic_size = i;
+		dynamic_size = indx;
 	}
 	}
 #endif
 #endif
 
 
-	for (i = 0; i < dynamic_size; i++) 
 	{
 	{
-		if (dpnt->d_tag > DT_JMPREL) {
+		unsigned long indx;
+
+		for (indx = 0; indx < dynamic_size; indx++) 
+		{
+			if (dpnt->d_tag > DT_JMPREL) {
+				dpnt++;
+				continue;
+			}
+			dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
+			if (dpnt->d_tag == DT_TEXTREL || SVR4_BUGCOMPAT)
+				dynamic_info[DT_TEXTREL] = 1;
 			dpnt++;
 			dpnt++;
-			continue;
+		};
-		}
+	}
-		dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
-		if (dpnt->d_tag == DT_TEXTREL || SVR4_BUGCOMPAT)
-			dynamic_info[DT_TEXTREL] = 1;
-		dpnt++;
-	};
 
 
 	/* If the TEXTREL is set, this means that we need to make the pages
 	/* If the TEXTREL is set, this means that we need to make the pages
 	   writable before we perform relocations.  Do this now. They get set
 	   writable before we perform relocations.  Do this now. They get set

+ 5 - 6
ldso/ldso/sh/boot1_arch.h

@@ -7,15 +7,14 @@ asm("\
 	.globl	_dl_boot
 	.globl	_dl_boot
 _dl_boot:
 _dl_boot:
         mov	r15, r4
         mov	r15, r4
-        mov.l	.L_dl_boot2, r1
+	mov.l   .L_dl_boot2, r0
-	mova	.L_dl_boot2, r0
+	bsrf    r0
-	add	r1, r0
+	add	#4, r4
-	jsr	@r0
+.jmp_loc:
-	 add	#4, r4
 	jmp	@r0
 	jmp	@r0
 	 mov    #0, r4        /* call _start with arg == 0 */
 	 mov    #0, r4        /* call _start with arg == 0 */
 .L_dl_boot2:\n\
 .L_dl_boot2:\n\
-	.long	_dl_boot2-.\n\
+	.long   _dl_boot2-.jmp_loc\n\
 	.previous\n\
 	.previous\n\
 ");
 ");
 
 

+ 5 - 6
ldso/ldso/sh/dl-startup.h

@@ -7,15 +7,14 @@ asm("\
 	.globl	_dl_boot
 	.globl	_dl_boot
 _dl_boot:
 _dl_boot:
         mov	r15, r4
         mov	r15, r4
-        mov.l	.L_dl_boot2, r1
+	mov.l   .L_dl_boot2, r0
-	mova	.L_dl_boot2, r0
+	bsrf    r0
-	add	r1, r0
+	add	#4, r4
-	jsr	@r0
+.jmp_loc:
-	 add	#4, r4
 	jmp	@r0
 	jmp	@r0
 	 mov    #0, r4        /* call _start with arg == 0 */
 	 mov    #0, r4        /* call _start with arg == 0 */
 .L_dl_boot2:\n\
 .L_dl_boot2:\n\
-	.long	_dl_boot2-.\n\
+	.long   _dl_boot2-.jmp_loc\n\
 	.previous\n\
 	.previous\n\
 ");
 ");
 
 

+ 4 - 3
ldso/ldso/sh/dl-sysdep.h

@@ -34,13 +34,14 @@
 #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD)		\
 #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD)		\
 	switch(ELF32_R_TYPE((RELP)->r_info)){			\
 	switch(ELF32_R_TYPE((RELP)->r_info)){			\
 	case R_SH_REL32:					\
 	case R_SH_REL32:					\
-		*(REL) += (RELP)->r_addend - (LOAD);		\
+		*(REL)  = (SYMBOL) + (RELP)->r_addend		\
+			    - (unsigned long)(REL);		\
 		break;						\
 		break;						\
 	case R_SH_DIR32:					\
 	case R_SH_DIR32:					\
-		*(REL) += (SYMBOL) + (RELP)->r_addend;		\
+		*(REL)  = (SYMBOL) + (RELP)->r_addend;		\
 		break;						\
 		break;						\
 	case R_SH_RELATIVE:					\
 	case R_SH_RELATIVE:					\
-		*(REL) += (LOAD);				\
+		*(REL)  = (LOAD) + (RELP)->r_addend;		\
 		break;						\
 		break;						\
 	case R_SH_NONE:						\
 	case R_SH_NONE:						\
 		break;						\
 		break;						\

+ 5 - 6
ldso/ldso/sh/elfinterp.c

@@ -236,8 +236,7 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
 		}
 		}
 		else if (res >0)
 		else if (res >0)
 		{
 		{
-			_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
+			_dl_dprintf(2, "can't resolve symbol\n");
-					_dl_progname, strtab + symtab[symtab_index].st_name);
 			goof += res;
 			goof += res;
 		}
 		}
 	  }
 	  }
@@ -289,17 +288,17 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
 			/* handled later on */
 			/* handled later on */
 			break;
 			break;
 		case R_SH_DIR32:
 		case R_SH_DIR32:
-			*reloc_addr += symbol_addr + rpnt->r_addend;
+			*reloc_addr = symbol_addr + rpnt->r_addend;
 			break;
 			break;
 		case R_SH_JMP_SLOT:
 		case R_SH_JMP_SLOT:
 			*reloc_addr = symbol_addr + rpnt->r_addend;
 			*reloc_addr = symbol_addr + rpnt->r_addend;
 			break;
 			break;
 		case R_SH_REL32:
 		case R_SH_REL32:
-			*reloc_addr += rpnt->r_addend -
+			*reloc_addr = symbol_addr + rpnt->r_addend -
-					(unsigned long) tpnt->loadaddr;
+					(unsigned long) reloc_addr;
 			break;
 			break;
 		case R_SH_RELATIVE:
 		case R_SH_RELATIVE:
-			*reloc_addr += (unsigned long) tpnt->loadaddr;
+			*reloc_addr = (unsigned long) tpnt->loadaddr + rpnt->r_addend;
 			break;
 			break;
 		default:
 		default:
 			return -1; /*call _dl_exit(1) */
 			return -1; /*call _dl_exit(1) */

+ 4 - 3
ldso/ldso/sh/ld_sysdep.h

@@ -34,13 +34,14 @@
 #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD)		\
 #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD)		\
 	switch(ELF32_R_TYPE((RELP)->r_info)){			\
 	switch(ELF32_R_TYPE((RELP)->r_info)){			\
 	case R_SH_REL32:					\
 	case R_SH_REL32:					\
-		*(REL) += (RELP)->r_addend - (LOAD);		\
+		*(REL)  = (SYMBOL) + (RELP)->r_addend		\
+			    - (unsigned long)(REL);		\
 		break;						\
 		break;						\
 	case R_SH_DIR32:					\
 	case R_SH_DIR32:					\
-		*(REL) += (SYMBOL) + (RELP)->r_addend;		\
+		*(REL)  = (SYMBOL) + (RELP)->r_addend;		\
 		break;						\
 		break;						\
 	case R_SH_RELATIVE:					\
 	case R_SH_RELATIVE:					\
-		*(REL) += (LOAD);				\
+		*(REL)  = (LOAD) + (RELP)->r_addend;		\
 		break;						\
 		break;						\
 	case R_SH_NONE:						\
 	case R_SH_NONE:						\
 		break;						\
 		break;						\

+ 22 - 7
ldso/ldso/sh/resolve.S

@@ -3,6 +3,7 @@
  */
  */
 
 
 	.text
 	.text
+	.globl	_dl_linux_resolver
 	.globl	_dl_linux_resolve
 	.globl	_dl_linux_resolve
 	.type	_dl_linux_resolve, @function
 	.type	_dl_linux_resolve, @function
 	.balign	16
 	.balign	16
@@ -31,13 +32,27 @@ _dl_linux_resolve:
 	fmov.s	fr4, @-r15
 	fmov.s	fr4, @-r15
 #endif
 #endif
 	sts.l	pr, @-r15
 	sts.l	pr, @-r15
+/* Note - The PLT entries have been "optimised" not to use r2.  r2 is used by
+   GCC to return the address of large structures, so it should not be
+   corrupted here.  This does mean however, that those PLTs does not conform
+   to the SH PIC ABI.  That spec says that r0 contains the type of the PLT
+   and r2 contains the GOT id.  The GNU Plt version stores the GOT id in r0 and
+   ignores the type.  We can easily detect this difference however,
+   since the type will always be 0 or 8, and the GOT ids will always be
+   greater than or equal to 12.
 
 
-	mov	r2, r4		! link map address
+   Found in binutils/bfd/elf32-sh.c by Stefan Allius <allius@atecom.com>
-
+ */
-	mov.l	3f, r0
+	mov     #8 ,r5
-	jsr	@r0		! Call resolver
+	cmp/gt  r5, r0
-	 mov	r1, r5		! Reloc offset
+	bt      1f
-
+	mov     r2, r0          ! link map address in r2 (SH PIC ABI)
+1:
+	mov     r0, r4          ! link map address in r0 (GNUs PLT)
+	mov.l   3f, r5
+	bsrf    r5
+	mov	r1, r5		! Reloc offset
+.jmp_loc:
 	lds.l	@r15+, pr	! Get register content back
 	lds.l	@r15+, pr	! Get register content back
 
 
 #ifdef HAVE_FPU
 #ifdef HAVE_FPU
@@ -64,6 +79,6 @@ _dl_linux_resolve:
 
 
 	.balign	4
 	.balign	4
 3:
 3:
-	.long	_dl_linux_resolver
+	.long   _dl_linux_resolver - .jmp_loc
 	.size	_dl_linux_resolve, . - _dl_linux_resolve
 	.size	_dl_linux_resolve, . - _dl_linux_resolve
 
 

+ 2 - 2
libc/Makefile

@@ -53,9 +53,9 @@ shared: $(TOPDIR)lib/$(LIBNAME)
 		/bin/sh $(TOPDIR)../extra/scripts/get-needed-libgcc-objects.sh)
 		/bin/sh $(TOPDIR)../extra/scripts/get-needed-libgcc-objects.sh)
 	$(LD) $(LDFLAGS) $(VERSION_SCRIPT) -soname=$(SHARED_MAJORNAME) -o $(SHARED_FULLNAME) \
 	$(LD) $(LDFLAGS) $(VERSION_SCRIPT) -soname=$(SHARED_MAJORNAME) -o $(SHARED_FULLNAME) \
 		--whole-archive ./tmp/libgcc-need.a $(LIBNAME) --no-whole-archive \
 		--whole-archive ./tmp/libgcc-need.a $(LIBNAME) --no-whole-archive \
-		$(TOPDIR)/libc/misc/internals/interp.o \
+		-init __uClibc_init $(TOPDIR)/libc/misc/internals/interp.o \
 		$(LIBGCC)
 		$(LIBGCC)
-	@/bin/true #rm -rf tmp
+	@true #rm -rf tmp
 	install -d $(TOPDIR)lib
 	install -d $(TOPDIR)lib
 	rm -f $(TOPDIR)lib/$(SHARED_FULLNAME)
 	rm -f $(TOPDIR)lib/$(SHARED_FULLNAME)
 	install -m 644 $(SHARED_FULLNAME) $(TOPDIR)lib
 	install -m 644 $(SHARED_FULLNAME) $(TOPDIR)lib

+ 111 - 56
libc/misc/internals/__uClibc_main.c

@@ -20,8 +20,6 @@
  * Prototypes.
  * Prototypes.
  */
  */
 extern int  main(int argc, char **argv, char **envp);
 extern int  main(int argc, char **argv, char **envp);
-extern void weak_function _init(void);
-extern void weak_function _fini(void);
 extern void weak_function _stdio_init(void);
 extern void weak_function _stdio_init(void);
 extern int *weak_const_function __errno_location(void);
 extern int *weak_const_function __errno_location(void);
 extern int *weak_const_function __h_errno_location(void);
 extern int *weak_const_function __h_errno_location(void);
@@ -36,10 +34,11 @@ extern void weak_function __pthread_initialize_minimal(void);
 
 
 
 
 
 
+
 /*
 /*
  * Declare the __environ global variable and create a weak alias environ.
  * Declare the __environ global variable and create a weak alias environ.
- * Note: Apparently we must initialize __environ for the weak environ
+ * Note: Apparently we must initialize __environ to ensure that the weak 
- * symbol to be included.
+ * environ symbol is also included.
  */
  */
 
 
 char **__environ = 0;
 char **__environ = 0;
@@ -47,68 +46,124 @@ weak_alias(__environ, environ);
 
 
 
 
 
 
+/* __uClibc_init completely initialize uClibc so it is ready to use.
+ *
+ * On ELF systems (with a dynamic loader) this function must be called
+ * from the dynamic loader (see TIS and ELF Specification), so that
+ * constructors of shared libraries (which depend on libc) can use all
+ * the libc code without restriction.  For this we link the shared
+ * version of the uClibc with -init __uClibc_init so DT_INIT for
+ * uClibc is the address of __uClibc_init
+ * 
+ * In all other cases we call it from the main stub
+ * __uClibc_start_main.
+ */
 
 
-void __attribute__ ((__noreturn__)) 
+void __uClibc_init(void) 
-__uClibc_main(int argc, char **argv, char **envp) 
 {
 {
-	/* If we are dynamically linked the shared lib loader
+    static int been_there_done_that = 0;
-	 * already did this for us.  But if we are statically
+
-	 * linked, we need to do this for ourselves. */
+    if (been_there_done_that) 
-	if (__environ==NULL) {
+	return;
-		/* Statically linked. */ 
+    been_there_done_that++;
-		__environ = envp;
-	}
 
 
 #ifdef __UCLIBC_HAS_THREADS__
 #ifdef __UCLIBC_HAS_THREADS__
-	if (likely(__pthread_initialize_minimal!=NULL))
+    /* Before we start initialzing uClibc we have to call
-	    __pthread_initialize_minimal();
+     * __pthread_initialize_minimal so we can use pthread_locks 
+     * whenever they are needed.
+     */
+    if (likely(__pthread_initialize_minimal!=NULL))
+	__pthread_initialize_minimal();
 #endif
 #endif
 
 
 #if 0
 #if 0
-	/* Some security at this point.  Prevent starting a SUID binary
+    /* Some security at this point.  Prevent starting a SUID binary
-	 * where the standard file descriptors are not opened.  We have
+     * where the standard file descriptors are not opened.  We have
-	 * to do this only for statically linked applications since
+     * to do this only for statically linked applications since
-	 * otherwise the dynamic loader did the work already.  */
+     * otherwise the dynamic loader did the work already.  */
-	if (unlikely (__libc_enable_secure!=NULL))
+    if (unlikely (__libc_enable_secure!=NULL))
-		__libc_check_standard_fds ();
+	__libc_check_standard_fds ();
 #endif
 #endif
 
 
 #ifdef __UCLIBC_HAS_LOCALE__
 #ifdef __UCLIBC_HAS_LOCALE__
-	/* Initialize the global locale structure. */
+    /* Initialize the global locale structure. */
-	if (likely(_locale_init!=NULL))
+    if (likely(_locale_init!=NULL))
-	    _locale_init();
+	_locale_init();
 #endif
 #endif
 
 
-	/*
+    /*
-	 * Initialize stdio here.  In the static library case, this will
+     * Initialize stdio here.  In the static library case, this will
-	 * be bypassed if not needed because of the weak alias above.
+     * be bypassed if not needed because of the weak alias above.
-	 */
+     */
-	if (likely(_stdio_init != NULL))
+    if (likely(_stdio_init != NULL))
-		_stdio_init();
+	_stdio_init();
-
+
-	/* Arrange for dtors to run at exit.  */
+}
-	if (likely(_fini!=NULL && atexit)) {
+
-		atexit (&_fini);
+
-	}
+/* __uClibc_start_main is the new main stub for uClibc. This function is 
-
+ * called from crt0 (version 0.9.16 or newer), after ALL shared libraries 
-	/* Run all ctors now.  */
+ * are initialized, just before we call the application's main function.
-	if (likely(_init!=NULL))
+ */
-		_init();
+void __attribute__ ((__noreturn__)) 
-
+__uClibc_start_main(int argc, char **argv, char **envp, 
-	/*
+	void (*app_init)(void), void (*app_fini)(void))
-	 * Note: It is possible that any initialization done above could
+{
-	 * have resulted in errno being set nonzero, so set it to 0 before
+
-	 * we call main.
+    /* If we are dynamically linked the shared lib loader already
-	 */
+     * did this for us.  But if we are statically linked, we need
-	if (likely(__errno_location!=NULL))
+     * to do this for ourselves.  */
-		*(__errno_location()) = 0;
+    if (__environ==NULL) {
-
+	/* Statically linked. */ 
-	/* Set h_errno to 0 as well */
+	__environ = envp;
-	if (likely(__h_errno_location!=NULL))
+    }
-		*(__h_errno_location()) = 0;
+
-
+    /* We need to initialize uClibc.  If we are dynamically linked this
-	/*
+     * may have already been completed by the shared lib loader.  We call 
-	 * Finally, invoke application's main and then exit.
+     * __uClibc_init() regardless, to be sure the right thing happens. */
-	 */
+    __uClibc_init();
-	exit(main(argc, argv, envp));
+
+    /* Arrange for the application's dtors to run before we exit.  */
+    if (app_fini!=NULL && atexit) {
+	atexit (app_fini);
+    }
+
+    /* Run all the application's ctors now.  */
+    if (app_init!=NULL) {
+	app_init();
+    }
+
+    /* Note: It is possible that any initialization done above could
+     * have resulted in errno being set nonzero, so set it to 0 before
+     * we call main.
+     */
+    if (likely(__errno_location!=NULL))
+	*(__errno_location()) = 0;
+
+    /* Set h_errno to 0 as well */
+    if (likely(__h_errno_location!=NULL))
+	*(__h_errno_location()) = 0;
+
+    /*
+     * Finally, invoke application's main and then exit.
+     */
+    exit(main(argc, argv, envp));
+}
+
+
+/* __uClibc_main is the old main stub of the uClibc. This
+ * function is called from crt0 (uClibc 0.9.15 and older) after
+ * ALL shared libraries are initialized, and just before we call
+ * the application's main() function.  
+ *
+ * Attention: This stub does not call the .init/.fini sections of
+ * the application. If you need this, please fix your uClibc port
+ * so that  __uClibc_start_main is called by your crt0.S with
+ * _init and _fini properly set.
+*/
+void __attribute__ ((__noreturn__)) 
+__uClibc_main(int argc, char **argv, char ** envp)
+{
+    __uClibc_start_main(argc, argv, envp, NULL, NULL);
 }
 }
+

+ 15 - 13
libc/sysdeps/linux/arm/crt0.S

@@ -50,20 +50,10 @@ ARM register quick reference:
 
 
 .text
 .text
 	.global _start
 	.global _start
-	.global __uClibc_main
-
 	.type   _start,%function
 	.type   _start,%function
-	.type   __uClibc_main,%function
 
 
 .text
 .text
 _start:
 _start:
-#if 0 /* some old code the I feel should not be here - davidm */
-	@ adjust the data segment base pointer
-	ldr r3,=__data_start
-	sub sl,sl,r3
-	mov BASEREG,sl
-#endif
-
 	/* clear the frame pointer */
 	/* clear the frame pointer */
 	mov     fp, #0
 	mov     fp, #0
 
 
@@ -78,10 +68,11 @@ _start:
 	   we find there (hopefully the environment) in r2 */
 	   we find there (hopefully the environment) in r2 */
 	add     r2, r1, r0, lsl #2
 	add     r2, r1, r0, lsl #2
 	add     r2, r2, #4
 	add     r2, r2, #4
+
 #else
 #else
 	/*
 	/*
-	 * uClinux stacks look a little different to MMU stacks
+	 * uClinux stacks look a little different from normal
-	 * for no good reason
+	 * MMU-full Linux stacks (for no good reason)
 	 */
 	 */
 	/* pull argc, argv and envp off the stack */
 	/* pull argc, argv and envp off the stack */
 	ldr r0,[sp, #0]
 	ldr r0,[sp, #0]
@@ -89,8 +80,19 @@ _start:
 	ldr r2,[sp, #8]
 	ldr r2,[sp, #8]
 #endif
 #endif
 
 
+	/* Store the address of _init in r3 as an argument to main() */
+	ldr r3, =_init
+
+	/* Push _fini onto the stack as the final argument to main() */
+	stmfd sp!, {r0}
+	ldr a1, =_fini
+	stmfd sp!, {r0}
+
 	/* Ok, now run uClibc's main() -- shouldn't return */
 	/* Ok, now run uClibc's main() -- shouldn't return */
-	bl	__uClibc_main
+	bl	__uClibc_start_main
+
+	/* Crash if somehow `exit' returns anyways.  */
+	bl abort
 
 
 /* Stick in a dummy reference to main(), so that if an application
 /* Stick in a dummy reference to main(), so that if an application
  * is linking when the main() function is in a static library (.a)
  * is linking when the main() function is in a static library (.a)

+ 12 - 15
libc/sysdeps/linux/i386/crt0.S

@@ -33,11 +33,11 @@ Cambridge, MA 02139, USA.  */
 .text
 .text
 	.align 4
 	.align 4
 
 
-.globl _start
+	.globl _start
-	.type	 _start,@function
+	.type _start,@function
 
 
 _start:
 _start:
-	/* First locate the start of the environment variables */
+	/* locate the start of the environment variables */
 	popl %ecx	/* Store argc into %ecx */
 	popl %ecx	/* Store argc into %ecx */
 	movl %esp,%ebx  /* Store argv into ebx */
 	movl %esp,%ebx  /* Store argv into ebx */
 	movl %esp,%eax  /* Store argv into eax as well*/
 	movl %esp,%eax  /* Store argv into eax as well*/
@@ -52,7 +52,6 @@ _start:
 	    %eax = env	    ; argv + (argc * 4) + 4
 	    %eax = env	    ; argv + (argc * 4) + 4
 	*/
 	*/
 
 
-
 	/* Set up an invalid (NULL return address, NULL frame pointer)
 	/* Set up an invalid (NULL return address, NULL frame pointer)
 	   callers stack frame so anybody unrolling the stack knows where
 	   callers stack frame so anybody unrolling the stack knows where
 	   to stop */
 	   to stop */
@@ -62,20 +61,18 @@ _start:
 	pushl %ebp      /* callers %ebp (frame pointer) */
 	pushl %ebp      /* callers %ebp (frame pointer) */
 	movl %esp,%ebp  /* mark callers stack frame as invalid */
 	movl %esp,%ebp  /* mark callers stack frame as invalid */
 
 
-	/* Now set the environment, argc, and argv where the app can get to them */
+	/* Push .init and .fini arguments to __uClibc_start_main() on the stack */
-	pushl %eax      /* Environment pointer */
+	pushl $_fini
-	pushl %ebx       /* Argument pointer */
+	pushl $_init
-	pushl %ecx      /* And the argument count */
 
 
-#if 0
+	/* Push envp, argc, and argc arguments to __uClibc_start_main() on the stack */ 
-	/* Make sure we are not using iBCS2 personality. (i.e. force linux).  */
+	pushl %eax	/* Environment pointer */
-	movl $136,%eax
+	pushl %ebx	/* Argument pointer */
-	sub %ebx,%ebx
+	pushl %ecx	/* And the argument count */
-	int $0x80
-#endif
 
 
 	/* Ok, now run uClibc's main() -- shouldn't return */
 	/* Ok, now run uClibc's main() -- shouldn't return */
-	call __uClibc_main
+	call __uClibc_start_main
+
 	/* Crash if somehow `exit' returns anyways.  */
 	/* Crash if somehow `exit' returns anyways.  */
 	hlt
 	hlt
 
 

+ 15 - 2
libc/sysdeps/linux/mips/crt0.S

@@ -30,9 +30,22 @@ __start:
 	addu a2, a0, 1	    /* load envp */
 	addu a2, a0, 1	    /* load envp */
         sll  a2, a2, 2
         sll  a2, a2, 2
 	add  a2, a2, a1
 	add  a2, a2, a1
+
+	/* Store the address of _init in a3 as an argument to __uClibc_start_main() */
+	la   a3, _init
+
+	/* Push _fini onto the stack as the final argument to __uClibc_start_main()
+	    I don't think I am doing this properly but it at least compiles... 
+	*/
+	la   t0, _fini
+	sw   t0,16(sp)
+	
 	/* Ok, now run uClibc's main() -- shouldn't return */
 	/* Ok, now run uClibc's main() -- shouldn't return */
-	jal	__uClibc_main
+	jal  __uClibc_start_main
-	hlt:    b hlt                   /* Crash if somehow it does return.  */
+
+	/* Crash if somehow `exit' returns anyways.  */
+hlt:
+	b   hlt
 
 
 /* Stick in a dummy reference to main(), so that if an application
 /* Stick in a dummy reference to main(), so that if an application
  * is linking when the main() function is in a static library (.a)
  * is linking when the main() function is in a static library (.a)

+ 30 - 19
libc/sysdeps/linux/sh/crt0.S

@@ -26,13 +26,6 @@
 
 
 	At this entry point, most registers' values are unspecified, except:
 	At this entry point, most registers' values are unspecified, except:
 
 
-   r4		Contains a function pointer to be registered with `atexit'.
-   		This is how the dynamic linker arranges to have DT_FINI
-		functions called for shared libraries that have been loaded
-		before this code runs.
-		WARNING: At that stage only static linker is supported. For
-		uCLinux we won't bother with r4.
-
    sp		The stack contains the arguments and environment:
    sp		The stack contains the arguments and environment:
    		0(sp)			argc
    		0(sp)			argc
 		4(sp)			argv[0]
 		4(sp)			argv[0]
@@ -42,18 +35,26 @@
 		...
 		...
 					NULL
 					NULL
 */
 */
+	.file "crt0.S"
 	.text
 	.text
 	.globl _start
 	.globl _start
 	.type _start,@function
 	.type _start,@function
 	.size _start,_start_end - _start
 	.size _start,_start_end - _start
 _start:
 _start:
-	/* Clear the frame pointer since this is the outermost frame. (in delay slot) */
+	/* Clear the frame pointer since this is the outermost frame. */
 	mov #0, r14
 	mov #0, r14
 
 
 	/* Pop argc off the stack and save a pointer to argv */
 	/* Pop argc off the stack and save a pointer to argv */
 	mov.l @r15+,r4
 	mov.l @r15+,r4
 	mov r15, r5
 	mov r15, r5
 
 
+	/* Push the finip argument to __uClibc_start_main() onto the stack */
+	mov.l L_fini,r6
+	mov.l r6,@-r15
+
+	/* Setup the value for the initp argument */
+	mov.l L_init, r7
+
 	/*
 	/*
 	 * Setup the value for the environment pointer:
 	 * Setup the value for the environment pointer:
 	 * r6 = (argc + 1) * 4
 	 * r6 = (argc + 1) * 4
@@ -62,27 +63,39 @@ _start:
 	mov r4,r6
 	mov r4,r6
 	add #1,r6
 	add #1,r6
 	shll2 r6
 	shll2 r6
-	add r5,r6
 
 
-	/* call main */
+	/* jump to __uClibc_start_main (argc, argv, envp, app_init, app_fini) */
 	mov.l L_main, r0
 	mov.l L_main, r0
 	jsr @r0
 	jsr @r0
-	nop /* delay slot */
+	add r5, r6  /* delay slot */
-
 	/* We should not get here. */
 	/* We should not get here. */
 	mov.l L_abort, r0
 	mov.l L_abort, r0
-	jsr @r0
+	jmp @r0
-	nop /* delay slot */
+	nop
 
 
 _start_end:	
 _start_end:	
 	.align	2
 	.align	2
 
 
+	.weak   _init
+	.type   _init,@function
+_init:
+	rts
+	nop
+
+.Lfe1:
+	.size   _init,.Lfe1-_init
+	.weak   _fini
+	.set    _fini,_init
 
 
 L_main:
 L_main:
-	.long	__uClibc_main
+	.long   __uClibc_start_main /* in libuClibc.*.so */
 
 
-L_abort:
+L_init:
-	.long	abort
+      .long   _init
+L_fini:
+      .long   _fini
+L_abort: 
+      .long   abort   
 
 
 /* Stick in a dummy reference to main(), so that if an application
 /* Stick in a dummy reference to main(), so that if an application
  * is linking when the main() function is in a static library (.a)
  * is linking when the main() function is in a static library (.a)
@@ -90,5 +103,3 @@ L_abort:
 L_dummy_main_reference:
 L_dummy_main_reference:
 	.long	main
 	.long	main
 
 
-	.data
-

+ 13 - 4
libpthread/Makefile

@@ -36,6 +36,15 @@ ifeq ($(strip $(DODEBUG)),true)
 endif
 endif
 endif
 endif
 
 
+GCC_LIB_DIR = $(dir $(shell $(CC) -print-libgcc-file-name ))
+ifeq ($(strip $(DOPIC)),true)
+    START_FILES  = $(TOPDIR)lib/crti.o     $(GCC_LIB_DIR)crtbeginS.o
+    END_FILES    = $(GCC_LIB_DIR)crtendS.o $(TOPDIR)lib/crtn.o
+else
+    START_FILES  = $(TOPDIR)lib/crti.o    $(GCC_LIB_DIR)crtbegin.o
+    END_FILES    = $(GCC_LIB_DIR)crtend.o $(TOPDIR)lib/crtn.o
+endif
+
 ALL_SUBDIRS = linuxthreads linuxthreads_db
 ALL_SUBDIRS = linuxthreads linuxthreads_db
 
 
 all: $(LIBPTHREAD) $(LIBTHREAD_DB)
 all: $(LIBPTHREAD) $(LIBTHREAD_DB)
@@ -67,9 +76,9 @@ shared: all
 	if [ -f $(LIBPTHREAD) ] ; then \
 	if [ -f $(LIBPTHREAD) ] ; then \
 		set -e; \
 		set -e; \
 		$(LD) $(LDFLAGS) -soname=$(LIBPTHREAD_SHARED).$(MAJOR_VERSION) \
 		$(LD) $(LDFLAGS) -soname=$(LIBPTHREAD_SHARED).$(MAJOR_VERSION) \
-			-o $(LIBPTHREAD_SHARED_FULLNAME) --whole-archive $(LIBPTHREAD) \
+			-o $(LIBPTHREAD_SHARED_FULLNAME) $(START_FILES) --whole-archive $(LIBPTHREAD) \
 			--no-whole-archive $(TOPDIR)/libc/misc/internals/interp.o \
 			--no-whole-archive $(TOPDIR)/libc/misc/internals/interp.o \
-			-L$(TOPDIR)/lib -lc; \
+			-L$(TOPDIR)/lib -lc $(END_FILES); \
 		install -d $(TOPDIR)lib; \
 		install -d $(TOPDIR)lib; \
 		rm -f $(TOPDIR)lib/$(LIBPTHREAD_SHARED_FULLNAME) \
 		rm -f $(TOPDIR)lib/$(LIBPTHREAD_SHARED_FULLNAME) \
 			$(TOPDIR)lib/$(LIBPTHREAD_SHARED).$(MAJOR_VERSION); \
 			$(TOPDIR)lib/$(LIBPTHREAD_SHARED).$(MAJOR_VERSION); \
@@ -82,9 +91,9 @@ shared: all
 	if [ -f $(LIBTHREAD_DB) ] ; then \
 	if [ -f $(LIBTHREAD_DB) ] ; then \
 		set -e; \
 		set -e; \
 		$(LD) $(LDFLAGS) -soname=$(LIBTHREAD_DB_SHARED).$(MAJOR_VERSION) \
 		$(LD) $(LDFLAGS) -soname=$(LIBTHREAD_DB_SHARED).$(MAJOR_VERSION) \
-			-o $(LIBTHREAD_DB_SHARED_FULLNAME) --whole-archive $(LIBTHREAD_DB) \
+			-o $(LIBTHREAD_DB_SHARED_FULLNAME) $(START_FILES) --whole-archive $(LIBTHREAD_DB) \
 			--no-whole-archive $(TOPDIR)/libc/misc/internals/interp.o \
 			--no-whole-archive $(TOPDIR)/libc/misc/internals/interp.o \
-			-L$(TOPDIR)/lib -lc; \
+			-L$(TOPDIR)/lib -lc $(END_FILES); \
 		install -d $(TOPDIR)lib; \
 		install -d $(TOPDIR)lib; \
 		rm -f $(TOPDIR)lib/$(LIBTHREAD_DB_SHARED_FULLNAME) \
 		rm -f $(TOPDIR)lib/$(LIBTHREAD_DB_SHARED_FULLNAME) \
 			$(TOPDIR)lib/$(LIBTHREAD_DB_SHARED).$(MAJOR_VERSION); \
 			$(TOPDIR)lib/$(LIBTHREAD_DB_SHARED).$(MAJOR_VERSION); \