[uClibc-cvs] CVS uClibc/ldso/ldso

CVS User jocke jocke at codepoet.org
Tue Nov 2 08:14:46 UTC 2004


Update of /var/cvs/uClibc/ldso/ldso
In directory nail:/tmp/cvs-serv19564/ldso

Modified Files:
	Makefile dl-elf.c dl-hash.c dl-startup.c ldso.c 
Log Message:
- Remove dynamic_size from struct elf_resolve.
- Replace all open coded dynamic handling with a function. Reduces size.
- Fold special MIPS dynamic code into the dynamic_info item.
- Add RELRO support.
- Support linking with "-z now". 
- prepare for DT_RELACOUNT/DT_RELCOUNT optimization.
- Add -z now to ld.so linking, this is what ld.so does anyway so
  let the linker know that.


--- /var/cvs/uClibc/ldso/ldso/Makefile	2004/10/06 06:59:56	1.63
+++ /var/cvs/uClibc/ldso/ldso/Makefile	2004/11/02 08:14:45	1.64
@@ -40,7 +40,7 @@
 XXFLAGS :=$(XXFLAGS:-O0=-O1)
 
 XXFLAGS+=$(shell $(CC) -print-search-dirs | sed -ne "s/install: *\(.*\)/-I\1include/gp")
-LDFLAGS=$(CPU_LDFLAGS-y) -Bsymbolic -shared --warn-common --export-dynamic --sort-common \
+LDFLAGS=$(CPU_LDFLAGS-y) -z now -Bsymbolic -shared --warn-common --export-dynamic --sort-common \
 	-z combreloc --discard-locals --discard-all --no-undefined
 
 CSRC= ldso.c
--- /var/cvs/uClibc/ldso/ldso/dl-elf.c	2004/10/11 20:57:11	1.87
+++ /var/cvs/uClibc/ldso/ldso/dl-elf.c	2004/11/02 08:14:45	1.88
@@ -114,6 +114,25 @@
 }
 #endif
 
+
+void 
+_dl_protect_relro (struct elf_resolve *l)
+{
+	ElfW(Addr) start = ((l->loadaddr + l->relro_addr)
+			    & ~(_dl_pagesize - 1));
+	ElfW(Addr) end = ((l->loadaddr + l->relro_addr + l->relro_size)
+			  & ~(_dl_pagesize - 1));
+#if defined (__SUPPORT_LD_DEBUG__)
+	if (_dl_debug)
+		_dl_dprintf(2, "RELRO protecting %s:  start:%x, end:%x\n", l->libname, start, end);
+#endif
+	if (start != end &&
+	    _dl_mprotect ((void *) start, end - start, PROT_READ) < 0) {
+		_dl_dprintf(2, "%s: cannot apply additional memory protection after relocation", l->libname);
+		_dl_exit(0);
+	}
+}
+
 /* This function's behavior must exactly match that
  * in uClibc/ldso/util/ldd.c */
 static struct elf_resolve *
@@ -390,16 +409,17 @@
 {
 	ElfW(Ehdr) *epnt;
 	unsigned long dynamic_addr = 0;
-	unsigned long dynamic_size = 0;
 	Elf32_Dyn *dpnt;
 	struct elf_resolve *tpnt;
 	ElfW(Phdr) *ppnt;
 	char *status, *header;
-	unsigned long dynamic_info[24];
+	unsigned long dynamic_info[DYNAMIC_SIZE];
 	unsigned long *lpnt;
 	unsigned long libaddr;
 	unsigned long minvma = 0xffffffff, maxvma = 0;
 	int i, flags, piclib, infile;
+	ElfW(Addr) relro_addr = 0;
+	size_t relro_size = 0;
 
 	/* If this file is already loaded, skip this step */
 	tpnt = _dl_check_hashed_files(libname);
@@ -493,7 +513,6 @@
 				_dl_dprintf(2, "%s: '%s' has more than one dynamic section\n",
 						_dl_progname, libname);
 			dynamic_addr = ppnt->p_vaddr;
-			dynamic_size = ppnt->p_filesz;
 		};
 
 		if (ppnt->p_type == PT_LOAD) {
@@ -535,6 +554,10 @@
 	ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
 
 	for (i = 0; i < epnt->e_phnum; i++) {
+		if (ppnt->p_type == PT_GNU_RELRO) {
+			relro_addr = ppnt->p_vaddr;
+			relro_size = ppnt->p_memsz;
+		}
 		if (ppnt->p_type == PT_LOAD) {
 
 			/* See if this is a PIC library. */
@@ -627,40 +650,8 @@
 	}
 
 	dpnt = (Elf32_Dyn *) dynamic_addr;
-
-	dynamic_size = dynamic_size / sizeof(Elf32_Dyn);
 	_dl_memset(dynamic_info, 0, sizeof(dynamic_info));
-
-#if defined(__mips__)
-	{
-
-		int indx = 1;
-		Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr;
-
-		while(dpnt->d_tag) {
-			dpnt++;
-			indx++;
-		}
-		dynamic_size = indx;
-	}
-#endif
-
-	{
-		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)
-				dynamic_info[DT_TEXTREL] = 1;
-			dpnt++;
-		};
-	}
-
+	_dl_parse_dynamic_info(dpnt, dynamic_info, NULL);
 	/* 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
 	   back again later. */
@@ -682,8 +673,9 @@
 	}
 
 	tpnt = _dl_add_elf_hash_table(libname, (char *) libaddr, dynamic_info,
-			dynamic_addr, dynamic_size);
-
+			dynamic_addr, 0);
+	tpnt->relro_addr = relro_addr;
+	tpnt->relro_size = relro_size;
 	tpnt->ppnt = (ElfW(Phdr) *)(intptr_t) (tpnt->loadaddr + epnt->e_phoff);
 	tpnt->n_phent = epnt->e_phnum;
 
@@ -718,8 +710,8 @@
 #if defined (__SUPPORT_LD_DEBUG__)
 	if(_dl_debug) {
 		_dl_dprintf(2, "\n\tfile='%s';  generating link map\n", libname);
-		_dl_dprintf(2, "\t\tdynamic: %x  base: %x   size: %x\n",
-				dynamic_addr, libaddr, dynamic_size);
+		_dl_dprintf(2, "\t\tdynamic: %x  base: %x\n",
+				dynamic_addr, libaddr);
 		_dl_dprintf(2, "\t\t  entry: %x  phdr: %x  phnum: %x\n\n",
 				epnt->e_entry + libaddr, tpnt->ppnt, tpnt->n_phent);
 
@@ -769,6 +761,8 @@
 				tpnt->dynamic_info[DT_RELOC_TABLE_ADDR],
 				reloc_size);
 	}
+	if (tpnt->dynamic_info[DT_BIND_NOW])
+		now_flag = RTLD_NOW;
 	if (tpnt->dynamic_info[DT_JMPREL] &&
 	    (!(tpnt->init_flag & JMP_RELOCS_DONE) ||
 	     (now_flag && !(tpnt->rtld_flags & now_flag)))) {
@@ -784,7 +778,6 @@
 					tpnt->dynamic_info[DT_PLTRELSZ]);
 		}
 	}
-
 	return goof;
 }
 
@@ -880,6 +873,11 @@
 	_dl_strcpy(retval, string);
 	return retval;
 }
+
+void _dl_parse_dynamic_info(Elf32_Dyn *dpnt, unsigned long dynamic_info[], void *debug_addr)
+{
+	__dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr);
+}
 #ifdef __USE_GNU
 #if ! defined LIBDL || (! defined PIC && ! defined __PIC__)
 int
--- /var/cvs/uClibc/ldso/ldso/dl-hash.c	2004/08/26 14:00:04	1.24
+++ /var/cvs/uClibc/ldso/ldso/dl-hash.c	2004/11/02 08:14:45	1.25
@@ -116,7 +116,6 @@
 	tpnt->init_flag = 0;
 	tpnt->libname = _dl_strdup(libname);
 	tpnt->dynamic_addr = (ElfW(Dyn) *)dynamic_addr;
-	tpnt->dynamic_size = dynamic_size;
 	tpnt->libtype = loaded_file;
 
 	if (dynamic_info[DT_HASH] != 0) {
@@ -128,23 +127,8 @@
 		tpnt->chains = hash_addr;
 	}
 	tpnt->loadaddr = (ElfW(Addr))loadaddr;
-	for (i = 0; i < 24; i++)
+	for (i = 0; i < DYNAMIC_SIZE; i++)
 		tpnt->dynamic_info[i] = dynamic_info[i];
-#ifdef __mips__
-	{
-		Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr;
-
-		while(dpnt->d_tag) {
-			if (dpnt->d_tag == DT_MIPS_GOTSYM)
-				tpnt->mips_gotsym = dpnt->d_un.d_val;
-			if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
-				tpnt->mips_local_gotno = dpnt->d_un.d_val;
-			if (dpnt->d_tag == DT_MIPS_SYMTABNO)
-				tpnt->mips_symtabno = dpnt->d_un.d_val;
-			dpnt++;
-		}
-	}
-#endif
 	return tpnt;
 }
 
--- /var/cvs/uClibc/ldso/ldso/dl-startup.c	2004/10/06 06:59:57	1.21
+++ /var/cvs/uClibc/ldso/ldso/dl-startup.c	2004/11/02 08:14:45	1.22
@@ -281,23 +281,14 @@
 #ifdef __SUPPORT_LD_DEBUG_EARLY__
 	SEND_STDERR("scanning DYNAMIC section\n");
 #endif
-	while (dpnt->d_tag) {
-#if defined(__mips__)
-		if (dpnt->d_tag == DT_MIPS_GOTSYM)
-			tpnt->mips_gotsym = (unsigned long) dpnt->d_un.d_val;
-		if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
-			tpnt->mips_local_gotno = (unsigned long) dpnt->d_un.d_val;
-		if (dpnt->d_tag == DT_MIPS_SYMTABNO)
-			tpnt->mips_symtabno = (unsigned long) dpnt->d_un.d_val;
-#endif
-		if (dpnt->d_tag < 24) {
-			tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
-			if (dpnt->d_tag == DT_TEXTREL) {
-				tpnt->dynamic_info[DT_TEXTREL] = 1;
-			}
-		}
-		dpnt++;
-	}
+	tpnt->dynamic_addr = dpnt;
+#ifdef __mips__
+	/* MIPS cannot call functions here, must inline */
+	__dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL);
+#else
+	_dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL);
+#endif
+
 #ifdef __SUPPORT_LD_DEBUG_EARLY__
 	SEND_STDERR("done scanning DYNAMIC section\n");
 #endif
@@ -335,7 +326,7 @@
 	SEND_STDERR("About to do MIPS specific GOT bootstrap\n");
 #endif
 	/* For MIPS we have to do stuff to the GOT before we do relocations.  */
-	PERFORM_BOOTSTRAP_GOT(got);
+	PERFORM_BOOTSTRAP_GOT(got, tpnt);
 #endif
 
 	/* OK, now do the relocations.  We do not do a lazy binding here, so
--- /var/cvs/uClibc/ldso/ldso/ldso.c	2004/10/27 22:07:52	1.126
+++ /var/cvs/uClibc/ldso/ldso/ldso.c	2004/11/02 08:14:45	1.127
@@ -97,9 +97,11 @@
 	struct elf_resolve app_tpnt_tmp;
 	struct elf_resolve *app_tpnt = &app_tpnt_tmp;
 	struct r_debug *debug_addr;
-	unsigned long brk_addr, *lpnt;
+	unsigned long *lpnt;
 	int (*_dl_atexit) (void *);
 	unsigned long *_dl_envp;		/* The environment address */
+	ElfW(Addr) relro_addr = 0;
+	size_t relro_size = 0;
 #if defined (__SUPPORT_LD_DEBUG__)
 	int (*_dl_on_exit) (void (*FUNCTION)(int STATUS, void *ARG),void*);
 #endif
@@ -132,23 +134,6 @@
 	 * go from there.  Eventually we will run across ourself, and we
 	 * will need to properly deal with that as well.
 	 */
-	{
-		ElfW(Ehdr) *epnt;
-		ElfW(Phdr) *myppnt;
-		int j;
-
-		epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr;
-		tpnt->n_phent = epnt->e_phnum;
-		tpnt->ppnt = myppnt = (ElfW(Phdr) *) (load_addr + epnt->e_phoff);
-		for (j = 0; j < epnt->e_phnum; j++, myppnt++) {
-			if (myppnt->p_type == PT_DYNAMIC) {
-				tpnt->dynamic_addr = (ElfW(Dyn) *)(myppnt->p_vaddr + load_addr);
-				tpnt->dynamic_size = myppnt->p_filesz;
-			}
-		}
-	}
-
-	brk_addr = 0;
 	rpnt = NULL;
 	if (_dl_getenv("LD_BIND_NOW", envp))
 		unlazy = RTLD_NOW;
@@ -189,46 +174,13 @@
 
 	ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
 	for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
-		if (ppnt->p_type == PT_LOAD) {
-			if (ppnt->p_vaddr + app_tpnt->loadaddr + ppnt->p_memsz > brk_addr)
-				brk_addr = ppnt->p_vaddr + app_tpnt->loadaddr + ppnt->p_memsz;
+		if (ppnt->p_type == PT_GNU_RELRO) {
+			relro_addr = ppnt->p_vaddr;
+			relro_size = ppnt->p_memsz;
 		}
 		if (ppnt->p_type == PT_DYNAMIC) {
 			dpnt = (Elf32_Dyn *) (ppnt->p_vaddr + app_tpnt->loadaddr);
-			while (dpnt->d_tag) {
-#if defined(__mips__)
-				if (dpnt->d_tag == DT_MIPS_GOTSYM)
-					app_tpnt->mips_gotsym =
-						(unsigned long) dpnt->d_un.d_val;
-				if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
-					app_tpnt->mips_local_gotno =
-						(unsigned long) dpnt->d_un.d_val;
-				if (dpnt->d_tag == DT_MIPS_SYMTABNO)
-					app_tpnt->mips_symtabno =
-						(unsigned long) dpnt->d_un.d_val;
-				/* Remember... DT_MIPS_RLD_MAP > DT_JMPREL. */
-				if (dpnt->d_tag == DT_MIPS_RLD_MAP) {
-					*(ElfW(Addr) *)(dpnt->d_un.d_ptr) =  (ElfW(Addr)) debug_addr;
-				}
-				if (dpnt->d_tag > DT_JMPREL) {
-					dpnt++;
-					continue;
-				}
-				app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
-#else
-				if (dpnt->d_tag > DT_JMPREL) {
-						dpnt++;
-						continue;
-				}
-				app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
-				if (dpnt->d_tag == DT_DEBUG) {
-					dpnt->d_un.d_val = (unsigned long) debug_addr;
-				}
-#endif
-				if (dpnt->d_tag == DT_TEXTREL)
-					app_tpnt->dynamic_info[DT_TEXTREL] = 1;
-				dpnt++;
-			}
+			_dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr);
 #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
 			/* Ugly, ugly.  We need to call mprotect to change the
 			 * protection of the text pages so that we can do the
@@ -315,6 +267,8 @@
 #endif
 		}
 	}
+	app_tpnt->relro_addr = relro_addr;
+	app_tpnt->relro_size = relro_size;
 
 	/* Now we need to figure out what kind of options are selected.
 	 * Note that for SUID programs we ignore the settings in
@@ -728,10 +682,24 @@
 	 * again once all libs are loaded.
 	 */
 	if (tpnt) {
+		ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr;
+		ElfW(Phdr) *myppnt = (ElfW(Phdr) *) (load_addr + epnt->e_phoff);
+		int j;
+		
 		tpnt = _dl_add_elf_hash_table(tpnt->libname, (char *)load_addr,
 					      tpnt->dynamic_info,
 					      (unsigned long)tpnt->dynamic_addr,
-					      tpnt->dynamic_size);
+					      0);
+
+		tpnt->n_phent = epnt->e_phnum;
+		tpnt->ppnt = myppnt;
+		for (j = 0; j < epnt->e_phnum; j++, myppnt++) {
+			if (myppnt->p_type ==  PT_GNU_RELRO) {
+				tpnt->relro_addr = myppnt->p_vaddr;
+				tpnt->relro_size = myppnt->p_memsz;
+				break;
+			}
+		}
 		tpnt->libtype = program_interpreter;
 		tpnt->usage_count++;
 		tpnt->symbol_scope = _dl_symbol_tables;
@@ -791,6 +759,13 @@
 	if (_dl_symbol_tables)
 		goof += _dl_fixup(_dl_symbol_tables, unlazy);
 
+	for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
+		if (tpnt->relro_size)
+			_dl_protect_relro (tpnt);
+	}
+
+
+
 
 	/* OK, at this point things are pretty much ready to run.  Now we need
 	 * to touch up a few items that are required, and then we can let the



More information about the uClibc-cvs mailing list