diff options
author | Joakim Tjernlund <joakim.tjernlund@transmode.se> | 2004-11-02 08:14:49 +0000 |
---|---|---|
committer | Joakim Tjernlund <joakim.tjernlund@transmode.se> | 2004-11-02 08:14:49 +0000 |
commit | dc0f822bfed430e5b4f87f27c2e63171fa5fba28 (patch) | |
tree | 01eda5fa3c42d0c8b114f76622b4794a7735aa41 /ldso | |
parent | f8f7b102217864ea382a46bb9ad173b3493e5cae (diff) |
- 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.
Diffstat (limited to 'ldso')
-rw-r--r-- | ldso/include/dl-elf.h | 49 | ||||
-rw-r--r-- | ldso/include/dl-hash.h | 11 | ||||
-rw-r--r-- | ldso/ldso/Makefile | 2 | ||||
-rw-r--r-- | ldso/ldso/dl-elf.c | 80 | ||||
-rw-r--r-- | ldso/ldso/dl-hash.c | 18 | ||||
-rw-r--r-- | ldso/ldso/dl-startup.c | 25 | ||||
-rw-r--r-- | ldso/ldso/ldso.c | 87 | ||||
-rw-r--r-- | ldso/ldso/mips/dl-startup.h | 14 | ||||
-rw-r--r-- | ldso/ldso/mips/dl-sysdep.h | 18 | ||||
-rw-r--r-- | ldso/ldso/mips/elfinterp.c | 16 | ||||
-rw-r--r-- | ldso/libdl/libdl.c | 10 |
11 files changed, 172 insertions, 158 deletions
diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h index d70d84ae4..a1237b09f 100644 --- a/ldso/include/dl-elf.h +++ b/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 diff --git a/ldso/include/dl-hash.h b/ldso/include/dl-hash.h index 67484d260..60fdd2856 100644 --- a/ldso/include/dl-hash.h +++ b/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 diff --git a/ldso/ldso/Makefile b/ldso/ldso/Makefile index 1f6476d2e..f58c3e857 100644 --- a/ldso/ldso/Makefile +++ b/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 diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index 3e4e3482c..d0144077d 100644 --- a/ldso/ldso/dl-elf.c +++ b/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 diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c index bac4a506a..a119e77f9 100644 --- a/ldso/ldso/dl-hash.c +++ b/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; } diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c index 0055435d2..91c41e730 100644 --- a/ldso/ldso/dl-startup.c +++ b/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 diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 46b59a3b2..d231969f8 100644 --- a/ldso/ldso/ldso.c +++ b/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 diff --git a/ldso/ldso/mips/dl-startup.h b/ldso/ldso/mips/dl-startup.h index 3d9b829c3..0dd92b5ba 100644 --- a/ldso/ldso/mips/dl-startup.h +++ b/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 { \ diff --git a/ldso/ldso/mips/dl-sysdep.h b/ldso/ldso/mips/dl-sysdep.h index 45a1f2e4e..8f5a56185 100644 --- a/ldso/ldso/mips/dl-sysdep.h +++ b/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) diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c index 37ef6a86c..74521823e 100644 --- a/ldso/ldso/mips/elfinterp.c +++ b/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) diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index 21dbd86ce..1bb68bdc8 100644 --- a/ldso/libdl/libdl.c +++ b/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 ? */ |