Преглед изворни кода

- 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.

Joakim Tjernlund пре 19 година
родитељ
комит
dc0f822bfe

+ 48 - 1
ldso/include/dl-elf.h

@@ -33,7 +33,7 @@ extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full
 	int trace_loaded_objects);
 	int trace_loaded_objects);
 extern int _dl_linux_resolve(void);
 extern int _dl_linux_resolve(void);
 extern int _dl_fixup(struct dyn_elf *rpnt, int flag);
 extern int _dl_fixup(struct dyn_elf *rpnt, int flag);
-
+extern void _dl_protect_relro (struct elf_resolve *l);
 
 
 /*
 /*
  * Datatype of a relocation on this platform
  * Datatype of a relocation on this platform
@@ -42,16 +42,63 @@ extern int _dl_fixup(struct dyn_elf *rpnt, int flag);
 # define ELF_RELOC	ElfW(Rela)
 # define ELF_RELOC	ElfW(Rela)
 # define DT_RELOC_TABLE_ADDR	DT_RELA
 # define DT_RELOC_TABLE_ADDR	DT_RELA
 # define DT_RELOC_TABLE_SIZE	DT_RELASZ
 # define DT_RELOC_TABLE_SIZE	DT_RELASZ
+# define DT_RELOCCOUNT		DT_RELACOUNT
 # define UNSUPPORTED_RELOC_TYPE	DT_REL
 # define UNSUPPORTED_RELOC_TYPE	DT_REL
 # define UNSUPPORTED_RELOC_STR	"REL"
 # define UNSUPPORTED_RELOC_STR	"REL"
 #else
 #else
 # define ELF_RELOC	ElfW(Rel)
 # define ELF_RELOC	ElfW(Rel)
 # define DT_RELOC_TABLE_ADDR	DT_REL
 # define DT_RELOC_TABLE_ADDR	DT_REL
 # define DT_RELOC_TABLE_SIZE	DT_RELSZ
 # define DT_RELOC_TABLE_SIZE	DT_RELSZ
+# define DT_RELOCCOUNT		DT_RELCOUNT
 # define UNSUPPORTED_RELOC_TYPE	DT_RELA
 # define UNSUPPORTED_RELOC_TYPE	DT_RELA
 # define UNSUPPORTED_RELOC_STR	"RELA"
 # define UNSUPPORTED_RELOC_STR	"RELA"
 #endif
 #endif
 
 
+/* OS and/or GNU dynamic extensions */
+#define OS_NUM 1
+#define DT_RELCONT_IDX DT_NUM
+
+#ifndef ARCH_DYNAMIC_INFO
+  /* define in arch specific code, if needed */
+# define ARCH_NUM 0
+#endif
+
+#define DYNAMIC_SIZE (DT_NUM+OS_NUM+ARCH_NUM)
+
+extern void _dl_parse_dynamic_info(Elf32_Dyn *dpnt, unsigned long dynamic_info[], void *debug_addr);
+
+static inline __attribute__((always_inline))
+void __dl_parse_dynamic_info(Elf32_Dyn *dpnt, unsigned long dynamic_info[], void *debug_addr)
+{
+	for (; dpnt->d_tag; dpnt++) {
+		if (dpnt->d_tag < DT_NUM) {
+			dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
+#ifndef __mips__
+			if (dpnt->d_tag == DT_DEBUG)
+				dpnt->d_un.d_val = (unsigned long)debug_addr;
+#endif
+			if (dpnt->d_tag == DT_BIND_NOW)
+				dynamic_info[DT_BIND_NOW] = 1;
+			if (dpnt->d_tag == DT_FLAGS &&
+			    (dpnt->d_un.d_val & DF_BIND_NOW))
+				dynamic_info[DT_BIND_NOW] = 1;
+			if (dpnt->d_tag == DT_TEXTREL)
+				dynamic_info[DT_TEXTREL] = 1;
+		} else if (dpnt->d_tag < DT_LOPROC) {
+			if (dpnt->d_tag == DT_RELOCCOUNT)
+				dynamic_info[DT_RELCONT_IDX] = dpnt->d_un.d_val;
+			if (dpnt->d_tag == DT_FLAGS_1 &&
+			    (dpnt->d_un.d_val & DF_1_NOW))
+				dynamic_info[DT_BIND_NOW] = 1;
+		}
+#ifdef ARCH_DYNAMIC_INFO
+		else {
+			ARCH_DYNAMIC_INFO(dpnt, dynamic_info, debug_addr);
+		}
+#endif
+	}
+}
+
 /* Reloc type classes as returned by elf_machine_type_class().
 /* Reloc type classes as returned by elf_machine_type_class().
    ELF_RTYPE_CLASS_PLT means this reloc should not be satisfied by
    ELF_RTYPE_CLASS_PLT means this reloc should not be satisfied by
    some PLT symbol, ELF_RTYPE_CLASS_COPY means this reloc should not be
    some PLT symbol, ELF_RTYPE_CLASS_COPY means this reloc should not be

+ 3 - 8
ldso/include/dl-hash.h

@@ -41,18 +41,13 @@ struct elf_resolve{
    */
    */
   unsigned long nchain;
   unsigned long nchain;
   unsigned long * chains;
   unsigned long * chains;
-  unsigned long dynamic_info[24];
+  unsigned long dynamic_info[DYNAMIC_SIZE];
 
 
-  unsigned long dynamic_size;
   unsigned long n_phent;
   unsigned long n_phent;
   Elf32_Phdr * ppnt;
   Elf32_Phdr * ppnt;
 
 
-#if defined(__mips__)
-  /* Needed for MIPS relocation */
-  unsigned long mips_gotsym;
-  unsigned long mips_local_gotno;
-  unsigned long mips_symtabno;
-#endif
+  ElfW(Addr) relro_addr;
+  size_t relro_size;
 
 
 #ifdef __powerpc__
 #ifdef __powerpc__
   /* this is used to store the address of relocation data words, so
   /* this is used to store the address of relocation data words, so

+ 1 - 1
ldso/ldso/Makefile

@@ -40,7 +40,7 @@ XXFLAGS+= $(XARCH_CFLAGS) $(CPU_CFLAGS) $(PICFLAG) \
 XXFLAGS :=$(XXFLAGS:-O0=-O1)
 XXFLAGS :=$(XXFLAGS:-O0=-O1)
 
 
 XXFLAGS+=$(shell $(CC) -print-search-dirs | sed -ne "s/install: *\(.*\)/-I\1include/gp")
 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
 	-z combreloc --discard-locals --discard-all --no-undefined
 
 
 CSRC= ldso.c
 CSRC= ldso.c

+ 39 - 41
ldso/ldso/dl-elf.c

@@ -114,6 +114,25 @@ int _dl_unmap_cache(void)
 }
 }
 #endif
 #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
 /* This function's behavior must exactly match that
  * in uClibc/ldso/util/ldd.c */
  * in uClibc/ldso/util/ldd.c */
 static struct elf_resolve *
 static struct elf_resolve *
@@ -390,16 +409,17 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 {
 {
 	ElfW(Ehdr) *epnt;
 	ElfW(Ehdr) *epnt;
 	unsigned long dynamic_addr = 0;
 	unsigned long dynamic_addr = 0;
-	unsigned long dynamic_size = 0;
 	Elf32_Dyn *dpnt;
 	Elf32_Dyn *dpnt;
 	struct elf_resolve *tpnt;
 	struct elf_resolve *tpnt;
 	ElfW(Phdr) *ppnt;
 	ElfW(Phdr) *ppnt;
 	char *status, *header;
 	char *status, *header;
-	unsigned long dynamic_info[24];
+	unsigned long dynamic_info[DYNAMIC_SIZE];
 	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, flags, piclib, infile;
 	int i, flags, piclib, infile;
+	ElfW(Addr) relro_addr = 0;
+	size_t relro_size = 0;
 
 
 	/* 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);
@@ -493,7 +513,6 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 				_dl_dprintf(2, "%s: '%s' has more than one dynamic section\n",
 				_dl_dprintf(2, "%s: '%s' has more than one dynamic section\n",
 						_dl_progname, libname);
 						_dl_progname, libname);
 			dynamic_addr = ppnt->p_vaddr;
 			dynamic_addr = ppnt->p_vaddr;
-			dynamic_size = ppnt->p_filesz;
 		};
 		};
 
 
 		if (ppnt->p_type == PT_LOAD) {
 		if (ppnt->p_type == PT_LOAD) {
@@ -535,6 +554,10 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
 	ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
 
 
 	for (i = 0; i < epnt->e_phnum; i++) {
 	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) {
 		if (ppnt->p_type == PT_LOAD) {
 
 
 			/* See if this is a PIC library. */
 			/* See if this is a PIC library. */
@@ -627,40 +650,8 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	}
 	}
 
 
 	dpnt = (Elf32_Dyn *) dynamic_addr;
 	dpnt = (Elf32_Dyn *) dynamic_addr;
-
-	dynamic_size = dynamic_size / sizeof(Elf32_Dyn);
 	_dl_memset(dynamic_info, 0, sizeof(dynamic_info));
 	_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
 	/* 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
 	   back again later. */
 	   back again later. */
@@ -682,8 +673,9 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	}
 	}
 
 
 	tpnt = _dl_add_elf_hash_table(libname, (char *) libaddr, dynamic_info,
 	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->ppnt = (ElfW(Phdr) *)(intptr_t) (tpnt->loadaddr + epnt->e_phoff);
 	tpnt->n_phent = epnt->e_phnum;
 	tpnt->n_phent = epnt->e_phnum;
 
 
@@ -718,8 +710,8 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 #if defined (__SUPPORT_LD_DEBUG__)
 #if defined (__SUPPORT_LD_DEBUG__)
 	if(_dl_debug) {
 	if(_dl_debug) {
 		_dl_dprintf(2, "\n\tfile='%s';  generating link map\n", libname);
 		_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",
 		_dl_dprintf(2, "\t\t  entry: %x  phdr: %x  phnum: %x\n\n",
 				epnt->e_entry + libaddr, tpnt->ppnt, tpnt->n_phent);
 				epnt->e_entry + libaddr, tpnt->ppnt, tpnt->n_phent);
 
 
@@ -769,6 +761,8 @@ int _dl_fixup(struct dyn_elf *rpnt, int now_flag)
 				tpnt->dynamic_info[DT_RELOC_TABLE_ADDR],
 				tpnt->dynamic_info[DT_RELOC_TABLE_ADDR],
 				reloc_size);
 				reloc_size);
 	}
 	}
+	if (tpnt->dynamic_info[DT_BIND_NOW])
+		now_flag = RTLD_NOW;
 	if (tpnt->dynamic_info[DT_JMPREL] &&
 	if (tpnt->dynamic_info[DT_JMPREL] &&
 	    (!(tpnt->init_flag & JMP_RELOCS_DONE) ||
 	    (!(tpnt->init_flag & JMP_RELOCS_DONE) ||
 	     (now_flag && !(tpnt->rtld_flags & now_flag)))) {
 	     (now_flag && !(tpnt->rtld_flags & now_flag)))) {
@@ -784,7 +778,6 @@ int _dl_fixup(struct dyn_elf *rpnt, int now_flag)
 					tpnt->dynamic_info[DT_PLTRELSZ]);
 					tpnt->dynamic_info[DT_PLTRELSZ]);
 		}
 		}
 	}
 	}
-
 	return goof;
 	return goof;
 }
 }
 
 
@@ -880,6 +873,11 @@ char *_dl_strdup(const char *string)
 	_dl_strcpy(retval, string);
 	_dl_strcpy(retval, string);
 	return retval;
 	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
 #ifdef __USE_GNU
 #if ! defined LIBDL || (! defined PIC && ! defined __PIC__)
 #if ! defined LIBDL || (! defined PIC && ! defined __PIC__)
 int
 int

+ 1 - 17
ldso/ldso/dl-hash.c

@@ -116,7 +116,6 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
 	tpnt->init_flag = 0;
 	tpnt->init_flag = 0;
 	tpnt->libname = _dl_strdup(libname);
 	tpnt->libname = _dl_strdup(libname);
 	tpnt->dynamic_addr = (ElfW(Dyn) *)dynamic_addr;
 	tpnt->dynamic_addr = (ElfW(Dyn) *)dynamic_addr;
-	tpnt->dynamic_size = dynamic_size;
 	tpnt->libtype = loaded_file;
 	tpnt->libtype = loaded_file;
 
 
 	if (dynamic_info[DT_HASH] != 0) {
 	if (dynamic_info[DT_HASH] != 0) {
@@ -128,23 +127,8 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
 		tpnt->chains = hash_addr;
 		tpnt->chains = hash_addr;
 	}
 	}
 	tpnt->loadaddr = (ElfW(Addr))loadaddr;
 	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];
 		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;
 	return tpnt;
 }
 }
 
 

+ 8 - 17
ldso/ldso/dl-startup.c

@@ -281,23 +281,14 @@ found_got:
 #ifdef __SUPPORT_LD_DEBUG_EARLY__
 #ifdef __SUPPORT_LD_DEBUG_EARLY__
 	SEND_STDERR("scanning DYNAMIC section\n");
 	SEND_STDERR("scanning DYNAMIC section\n");
 #endif
 #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;
+	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
 #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++;
-	}
+
 #ifdef __SUPPORT_LD_DEBUG_EARLY__
 #ifdef __SUPPORT_LD_DEBUG_EARLY__
 	SEND_STDERR("done scanning DYNAMIC section\n");
 	SEND_STDERR("done scanning DYNAMIC section\n");
 #endif
 #endif
@@ -335,7 +326,7 @@ found_got:
 	SEND_STDERR("About to do MIPS specific GOT bootstrap\n");
 	SEND_STDERR("About to do MIPS specific GOT bootstrap\n");
 #endif
 #endif
 	/* For MIPS we have to do stuff to the GOT before we do relocations.  */
 	/* For MIPS we have to do stuff to the GOT before we do relocations.  */
-	PERFORM_BOOTSTRAP_GOT(got);
+	PERFORM_BOOTSTRAP_GOT(got, tpnt);
 #endif
 #endif
 
 
 	/* OK, now do the relocations.  We do not do a lazy binding here, so
 	/* OK, now do the relocations.  We do not do a lazy binding here, so

+ 31 - 56
ldso/ldso/ldso.c

@@ -97,9 +97,11 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
 	struct elf_resolve app_tpnt_tmp;
 	struct elf_resolve app_tpnt_tmp;
 	struct elf_resolve *app_tpnt = &app_tpnt_tmp;
 	struct elf_resolve *app_tpnt = &app_tpnt_tmp;
 	struct r_debug *debug_addr;
 	struct r_debug *debug_addr;
-	unsigned long brk_addr, *lpnt;
+	unsigned long *lpnt;
 	int (*_dl_atexit) (void *);
 	int (*_dl_atexit) (void *);
 	unsigned long *_dl_envp;		/* The environment address */
 	unsigned long *_dl_envp;		/* The environment address */
+	ElfW(Addr) relro_addr = 0;
+	size_t relro_size = 0;
 #if defined (__SUPPORT_LD_DEBUG__)
 #if defined (__SUPPORT_LD_DEBUG__)
 	int (*_dl_on_exit) (void (*FUNCTION)(int STATUS, void *ARG),void*);
 	int (*_dl_on_exit) (void (*FUNCTION)(int STATUS, void *ARG),void*);
 #endif
 #endif
@@ -132,23 +134,6 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
 	 * go from there.  Eventually we will run across ourself, and we
 	 * go from there.  Eventually we will run across ourself, and we
 	 * will need to properly deal with that as well.
 	 * 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;
 	rpnt = NULL;
 	if (_dl_getenv("LD_BIND_NOW", envp))
 	if (_dl_getenv("LD_BIND_NOW", envp))
 		unlazy = RTLD_NOW;
 		unlazy = RTLD_NOW;
@@ -189,46 +174,13 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
 
 
 	ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
 	ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
 	for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
 	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) {
 		if (ppnt->p_type == PT_DYNAMIC) {
 			dpnt = (Elf32_Dyn *) (ppnt->p_vaddr + app_tpnt->loadaddr);
 			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__
 #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
 			/* Ugly, ugly.  We need to call mprotect to change the
 			/* Ugly, ugly.  We need to call mprotect to change the
 			 * protection of the text pages so that we can do the
 			 * protection of the text pages so that we can do the
@@ -315,6 +267,8 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
 #endif
 #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.
 	/* Now we need to figure out what kind of options are selected.
 	 * Note that for SUID programs we ignore the settings in
 	 * Note that for SUID programs we ignore the settings in
@@ -728,10 +682,24 @@ next_lib2:
 	 * again once all libs are loaded.
 	 * again once all libs are loaded.
 	 */
 	 */
 	if (tpnt) {
 	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 = _dl_add_elf_hash_table(tpnt->libname, (char *)load_addr,
 					      tpnt->dynamic_info,
 					      tpnt->dynamic_info,
 					      (unsigned long)tpnt->dynamic_addr,
 					      (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->libtype = program_interpreter;
 		tpnt->usage_count++;
 		tpnt->usage_count++;
 		tpnt->symbol_scope = _dl_symbol_tables;
 		tpnt->symbol_scope = _dl_symbol_tables;
@@ -791,6 +759,13 @@ next_lib2:
 	if (_dl_symbol_tables)
 	if (_dl_symbol_tables)
 		goof += _dl_fixup(_dl_symbol_tables, unlazy);
 		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
 	/* 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
 	 * to touch up a few items that are required, and then we can let the

+ 7 - 7
ldso/ldso/mips/dl-startup.h

@@ -48,21 +48,21 @@ asm("" \
  * 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.
  * used when bootstrapping the dynamic loader.
  */
  */
-#define PERFORM_BOOTSTRAP_GOT(got)						\
+#define PERFORM_BOOTSTRAP_GOT(got, tpnt)					\
 do {										\
 do {										\
 	Elf32_Sym *sym;								\
 	Elf32_Sym *sym;								\
 	unsigned long i;							\
 	unsigned long i;							\
 										\
 										\
 	/* Add load address displacement to all local GOT entries */		\
 	/* Add load address displacement to all local GOT entries */		\
 	i = 2;									\
 	i = 2;									\
-	while (i < tpnt->mips_local_gotno)					\
+	while (i < tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX])			\
 		got[i++] += load_addr;						\
 		got[i++] += load_addr;						\
 										\
 										\
 	/* Handle global GOT entries */						\
 	/* Handle global GOT entries */						\
-	got += tpnt->mips_local_gotno;						\
+	got += tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX];			\
 	sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] +			\
 	sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] +			\
-		 load_addr) + tpnt->mips_gotsym;				\
-	i = tpnt->mips_symtabno - tpnt->mips_gotsym;				\
+		 load_addr) + tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];		\
+	i = tpnt->dynamic_info[DT_MIPS_SYMTABNO_IDX] - tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];\
 										\
 										\
 	while (i--) {								\
 	while (i--) {								\
 		if (sym->st_shndx == SHN_UNDEF ||				\
 		if (sym->st_shndx == SHN_UNDEF ||				\
@@ -91,8 +91,8 @@ do {										\
 #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB)			\
 #define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB)			\
 	switch(ELF32_R_TYPE((RELP)->r_info)) {					\
 	switch(ELF32_R_TYPE((RELP)->r_info)) {					\
 	case R_MIPS_REL32:							\
 	case R_MIPS_REL32:							\
-		if (symtab_index) {						\
-			if (symtab_index < tpnt->mips_gotsym)			\
+		if (SYMTAB) {							\
+			if (symtab_index<tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX])\
 				*REL += SYMBOL;					\
 				*REL += SYMBOL;					\
 		}								\
 		}								\
 		else {								\
 		else {								\

+ 17 - 1
ldso/ldso/mips/dl-sysdep.h

@@ -8,6 +8,22 @@
 /* Define this if the system uses RELOCA.  */
 /* Define this if the system uses RELOCA.  */
 #undef ELF_USES_RELOCA
 #undef ELF_USES_RELOCA
 
 
+#define ARCH_NUM 3
+#define DT_MIPS_GOTSYM_IDX	(DT_NUM + OS_NUM)
+#define DT_MIPS_LOCAL_GOTNO_IDX	(DT_NUM + OS_NUM +1)
+#define DT_MIPS_SYMTABNO_IDX	(DT_NUM + OS_NUM +2)
+
+#define ARCH_DYNAMIC_INFO(dpnt,  dynamic, debug_addr) \
+do { \
+if (dpnt->d_tag == DT_MIPS_GOTSYM) \
+     dynamic[DT_MIPS_GOTSYM_IDX] = dpnt->d_un.d_val; \
+else if(dpnt->d_tag == DT_MIPS_LOCAL_GOTNO) \
+     dynamic[DT_MIPS_LOCAL_GOTNO_IDX] = dpnt->d_un.d_val; \
+else if(dpnt->d_tag == DT_MIPS_SYMTABNO) \
+     dynamic[DT_MIPS_SYMTABNO_IDX] = dpnt->d_un.d_val; \
+else if (dpnt->d_tag == DT_MIPS_RLD_MAP) \
+     *(Elf32_Addr *)(dpnt->d_un.d_ptr) =  (Elf32_Addr) debug_addr; \
+} while (0)
 
 
 /* Initialization sequence for the application/library GOT.  */
 /* Initialization sequence for the application/library GOT.  */
 #define INIT_GOT(GOT_BASE,MODULE)						\
 #define INIT_GOT(GOT_BASE,MODULE)						\
@@ -24,7 +40,7 @@ do {										\
 										\
 										\
 	/* Add load address displacement to all local GOT entries */		\
 	/* Add load address displacement to all local GOT entries */		\
 	i = 2;									\
 	i = 2;									\
-	while (i < MODULE->mips_local_gotno)					\
+	while (i < MODULE->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX])		\
 		GOT_BASE[i++] += (unsigned long) MODULE->loadaddr;		\
 		GOT_BASE[i++] += (unsigned long) MODULE->loadaddr;		\
 										\
 										\
 } while (0)
 } while (0)

+ 8 - 8
ldso/ldso/mips/elfinterp.c

@@ -121,8 +121,8 @@ unsigned long _dl_linux_resolver(unsigned long sym_index,
 	char **got_addr;
 	char **got_addr;
 	char *symname;
 	char *symname;
 
 
-	gotsym = tpnt->mips_gotsym;
-	local_gotno = tpnt->mips_local_gotno;
+	gotsym = tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];
+	local_gotno = tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX];
 
 
 	sym = ((Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr)) + sym_index;
 	sym = ((Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr)) + sym_index;
 	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
 	strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
@@ -213,13 +213,13 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
 		switch (reloc_type) {
 		switch (reloc_type) {
 		case R_MIPS_REL32:
 		case R_MIPS_REL32:
 			if (symtab_index) {
 			if (symtab_index) {
-				if (symtab_index < tpnt->mips_gotsym)
+				if (symtab_index < tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX])
 					*reloc_addr +=
 					*reloc_addr +=
 						symtab[symtab_index].st_value +
 						symtab[symtab_index].st_value +
 						(unsigned long) tpnt->loadaddr;
 						(unsigned long) tpnt->loadaddr;
 				else {
 				else {
-					*reloc_addr += got[symtab_index + tpnt->mips_local_gotno -
-						tpnt->mips_gotsym];
+					*reloc_addr += got[symtab_index + tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX] -
+						tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]];
 				}
 				}
 			}
 			}
 			else {
 			else {
@@ -270,12 +270,12 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
 
 
 		/* Setup the loop variables */
 		/* Setup the loop variables */
 		got_entry = (unsigned long *) (tpnt->loadaddr +
 		got_entry = (unsigned long *) (tpnt->loadaddr +
-			tpnt->dynamic_info[DT_PLTGOT]) + tpnt->mips_local_gotno;
+			tpnt->dynamic_info[DT_PLTGOT]) + tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX];
 		sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] +
 		sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] +
-			(unsigned long) tpnt->loadaddr) + tpnt->mips_gotsym;
+			(unsigned long) tpnt->loadaddr) + tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];
 		strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] +
 		strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] +
 			(unsigned long) tpnt->loadaddr);
 			(unsigned long) tpnt->loadaddr);
-		i = tpnt->mips_symtabno - tpnt->mips_gotsym;
+		i = tpnt->dynamic_info[DT_MIPS_SYMTABNO_IDX] - tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];
 
 
 #if defined (__SUPPORT_LD_DEBUG__)
 #if defined (__SUPPORT_LD_DEBUG__)
 		if(_dl_debug_reloc)
 		if(_dl_debug_reloc)

+ 9 - 1
ldso/libdl/libdl.c

@@ -47,6 +47,8 @@ extern struct elf_resolve * _dl_check_if_named_library_is_loaded(const char *, i
 	__attribute__ ((__weak__));
 	__attribute__ ((__weak__));
 extern int _dl_fixup(struct dyn_elf *rpnt, int lazy)
 extern int _dl_fixup(struct dyn_elf *rpnt, int lazy)
 	 __attribute__ ((__weak__));
 	 __attribute__ ((__weak__));
+extern void _dl_protect_relro(struct elf_resolve * tpnt)
+	__attribute__ ((__weak__));
 extern int _dl_errno __attribute__ ((__weak__));
 extern int _dl_errno __attribute__ ((__weak__));
 extern struct dyn_elf *_dl_symbol_tables __attribute__ ((__weak__));
 extern struct dyn_elf *_dl_symbol_tables __attribute__ ((__weak__));
 extern struct dyn_elf *_dl_handles __attribute__ ((__weak__));
 extern struct dyn_elf *_dl_handles __attribute__ ((__weak__));
@@ -128,7 +130,7 @@ void __attribute__ ((destructor)) dl_cleanup(void)
 void *dlopen(const char *libname, int flag)
 void *dlopen(const char *libname, int flag)
 {
 {
 	struct elf_resolve *tpnt, *tfrom, *tcurr;
 	struct elf_resolve *tpnt, *tfrom, *tcurr;
-	struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr;
+	struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr;
 	struct dyn_elf *dpnt;
 	struct dyn_elf *dpnt;
 	ElfW(Addr) from;
 	ElfW(Addr) from;
 	struct elf_resolve *tpnt1;
 	struct elf_resolve *tpnt1;
@@ -168,6 +170,8 @@ void *dlopen(const char *libname, int flag)
 			tfrom = tpnt;
 			tfrom = tpnt;
 	}
 	}
 	for(rpnt = _dl_symbol_tables; rpnt->next; rpnt=rpnt->next);
 	for(rpnt = _dl_symbol_tables; rpnt->next; rpnt=rpnt->next);
+
+	relro_ptr = rpnt;
 	/* Try to load the specified library */
 	/* Try to load the specified library */
 #ifdef __SUPPORT_LD_DEBUG__
 #ifdef __SUPPORT_LD_DEBUG__
 	if(_dl_debug)
 	if(_dl_debug)
@@ -311,6 +315,10 @@ void *dlopen(const char *libname, int flag)
 	if (_dl_fixup(dyn_chain, now_flag))
 	if (_dl_fixup(dyn_chain, now_flag))
 		goto oops;
 		goto oops;
 
 
+	for (rpnt = relro_ptr->next; rpnt; rpnt = rpnt->next) {
+		if (rpnt->dyn->relro_size)
+			_dl_protect_relro(rpnt->dyn);
+	}
 	/* TODO:  Should we set the protections of all pages back to R/O now ? */
 	/* TODO:  Should we set the protections of all pages back to R/O now ? */