Browse Source

- 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 years ago
parent
commit
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);
 extern int _dl_linux_resolve(void);
 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
@@ -42,16 +42,63 @@ extern int _dl_fixup(struct dyn_elf *rpnt, int flag);
 # define ELF_RELOC	ElfW(Rela)
 # define DT_RELOC_TABLE_ADDR	DT_RELA
 # define DT_RELOC_TABLE_SIZE	DT_RELASZ
+# define DT_RELOCCOUNT		DT_RELACOUNT
 # define UNSUPPORTED_RELOC_TYPE	DT_REL
 # define UNSUPPORTED_RELOC_STR	"REL"
 #else
 # define ELF_RELOC	ElfW(Rel)
 # define DT_RELOC_TABLE_ADDR	DT_REL
 # define DT_RELOC_TABLE_SIZE	DT_RELSZ
+# define DT_RELOCCOUNT		DT_RELCOUNT
 # define UNSUPPORTED_RELOC_TYPE	DT_RELA
 # define UNSUPPORTED_RELOC_STR	"RELA"
 #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().
    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

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

@@ -41,18 +41,13 @@ struct elf_resolve{
    */
   unsigned long nchain;
   unsigned long * chains;
-  unsigned long dynamic_info[24];
+  unsigned long dynamic_info[DYNAMIC_SIZE];
 
-  unsigned long dynamic_size;
   unsigned long n_phent;
   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__
   /* 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+=$(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

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

@@ -114,6 +114,25 @@ int _dl_unmap_cache(void)
 }
 #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 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 {
 	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 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 				_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 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	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 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	}
 
 	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 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	}
 
 	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 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 #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 @@ int _dl_fixup(struct dyn_elf *rpnt, int now_flag)
 				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 @@ int _dl_fixup(struct dyn_elf *rpnt, int now_flag)
 					tpnt->dynamic_info[DT_PLTRELSZ]);
 		}
 	}
-
 	return goof;
 }
 
@@ -880,6 +873,11 @@ char *_dl_strdup(const char *string)
 	_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

+ 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->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 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
 		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;
 }
 

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

@@ -281,23 +281,14 @@ found_got:
 #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;
+	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
-		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__
 	SEND_STDERR("done scanning DYNAMIC section\n");
 #endif
@@ -335,7 +326,7 @@ found_got:
 	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

+ 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 = &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 @@ 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
 	 * 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 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
 
 	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 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
 #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 @@ next_lib2:
 	 * 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 @@ next_lib2:
 	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

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

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

@@ -8,6 +8,22 @@
 /* Define this if the system 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.  */
 #define INIT_GOT(GOT_BASE,MODULE)						\
@@ -24,7 +40,7 @@ do {										\
 										\
 	/* Add load address displacement to all local GOT entries */		\
 	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;		\
 										\
 } 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 *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;
 	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) {
 		case R_MIPS_REL32:
 			if (symtab_index) {
-				if (symtab_index < tpnt->mips_gotsym)
+				if (symtab_index < tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX])
 					*reloc_addr +=
 						symtab[symtab_index].st_value +
 						(unsigned long) tpnt->loadaddr;
 				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 {
@@ -270,12 +270,12 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
 
 		/* Setup the loop variables */
 		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] +
-			(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] +
 			(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(_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__));
 extern int _dl_fixup(struct dyn_elf *rpnt, int lazy)
 	 __attribute__ ((__weak__));
+extern void _dl_protect_relro(struct elf_resolve * tpnt)
+	__attribute__ ((__weak__));
 extern int _dl_errno __attribute__ ((__weak__));
 extern struct dyn_elf *_dl_symbol_tables __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)
 {
 	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;
 	ElfW(Addr) from;
 	struct elf_resolve *tpnt1;
@@ -168,6 +170,8 @@ void *dlopen(const char *libname, int flag)
 			tfrom = tpnt;
 	}
 	for(rpnt = _dl_symbol_tables; rpnt->next; rpnt=rpnt->next);
+
+	relro_ptr = rpnt;
 	/* Try to load the specified library */
 #ifdef __SUPPORT_LD_DEBUG__
 	if(_dl_debug)
@@ -311,6 +315,10 @@ void *dlopen(const char *libname, int flag)
 	if (_dl_fixup(dyn_chain, now_flag))
 		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 ? */