From 6d6f3a5c26adcf6b105edfb4b53e97ceee81944c Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Tue, 17 Aug 2004 13:37:54 +0000 Subject: Let ldso decide if it should relocate itselft a second time. This is needed if ldso should use libcs malloc whenever possible. Fix RTLD_LAZY propagation to RTLD_NOW relocation when requested by libdl. --- ldso/ldso/arm/elfinterp.c | 5 ---- ldso/ldso/cris/elfinterp.c | 12 -------- ldso/ldso/dl-elf.c | 27 ++++++++---------- ldso/ldso/frv/elfinterp.c | 14 ---------- ldso/ldso/i386/elfinterp.c | 5 ---- ldso/ldso/ldso.c | 65 +++++++++++++++++-------------------------- ldso/ldso/m68k/elfinterp.c | 17 ----------- ldso/ldso/mips/elfinterp.c | 9 ------ ldso/ldso/powerpc/elfinterp.c | 9 ------ ldso/ldso/sh/elfinterp.c | 9 ------ ldso/ldso/sh64/elfinterp.c | 9 ------ ldso/ldso/sparc/elfinterp.c | 19 ------------- 12 files changed, 37 insertions(+), 163 deletions(-) (limited to 'ldso/ldso') diff --git a/ldso/ldso/arm/elfinterp.c b/ldso/ldso/arm/elfinterp.c index 93ae35e8b..ab66eed1a 100644 --- a/ldso/ldso/arm/elfinterp.c +++ b/ldso/ldso/arm/elfinterp.c @@ -189,11 +189,6 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, ELF_RELOC *rpnt; int symtab_index; - /* When the dynamic linker bootstrapped itself, it resolved some symbols. - Make sure we do not do them again */ - if (tpnt->libtype == program_interpreter) - return 0; - /* Now parse the relocation information */ rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr); rel_size = rel_size / sizeof(ELF_RELOC); diff --git a/ldso/ldso/cris/elfinterp.c b/ldso/ldso/cris/elfinterp.c index 2fed69e74..6030a6575 100644 --- a/ldso/ldso/cris/elfinterp.c +++ b/ldso/ldso/cris/elfinterp.c @@ -182,18 +182,6 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, unsigned long rel_add for (i = 0; i < rel_size; i++, rpnt++) { symtab_index = ELF32_R_SYM(rpnt->r_info); - - /* - * Make sure the same symbols that the linker resolved when it - * bootstapped itself isn't resolved again. - */ - if (!symtab_index && tpnt->libtype == program_interpreter) - continue; - - if (symtab_index && tpnt->libtype == program_interpreter && - _dl_symbol(strtab + symtab[symtab_index].st_name)) - continue; - #if defined (__SUPPORT_LD_DEBUG__) debug_sym(symtab, strtab, symtab_index); debug_reloc(symtab, strtab, rpnt); diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index 25c82401f..8af9e78f6 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -730,15 +730,15 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, return tpnt; } - -int _dl_fixup(struct dyn_elf *rpnt, int flag) +/* now_flag must be RTLD_NOW or zero */ +int _dl_fixup(struct dyn_elf *rpnt, int now_flag) { int goof = 0; struct elf_resolve *tpnt; unsigned long reloc_size; if (rpnt->next) - goof += _dl_fixup(rpnt->next, flag); + goof += _dl_fixup(rpnt->next, now_flag); tpnt = rpnt->dyn; #if defined (__SUPPORT_LD_DEBUG__) @@ -756,28 +756,25 @@ int _dl_fixup(struct dyn_elf *rpnt, int flag) return goof; } + reloc_size = tpnt->dynamic_info[DT_RELOC_TABLE_SIZE]; /* On some machines, notably SPARC & PPC, DT_REL* includes DT_JMPREL in its range. Note that according to the ELF spec, this is completely legal! */ #ifdef ELF_MACHINE_PLTREL_OVERLAP - reloc_size = tpnt->dynamic_info[DT_RELOC_TABLE_SIZE] - - tpnt->dynamic_info [DT_PLTRELSZ]; -#else - reloc_size = tpnt->dynamic_info[DT_RELOC_TABLE_SIZE]; + reloc_size -= tpnt->dynamic_info [DT_PLTRELSZ]; #endif - if (tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]) { - if (tpnt->init_flag & RELOCS_DONE) - return goof; + if (tpnt->dynamic_info[DT_RELOC_TABLE_ADDR] && + !(tpnt->init_flag & RELOCS_DONE)) { tpnt->init_flag |= RELOCS_DONE; goof += _dl_parse_relocation_information(rpnt, tpnt->dynamic_info[DT_RELOC_TABLE_ADDR], reloc_size, 0); } - - if (tpnt->dynamic_info[DT_JMPREL]) { - if (tpnt->init_flag & JMP_RELOCS_DONE) - return goof; + if (tpnt->dynamic_info[DT_JMPREL] && + (!(tpnt->init_flag & JMP_RELOCS_DONE) || + (now_flag && !(tpnt->rtld_flags & now_flag)))) { + tpnt->rtld_flags |= now_flag; tpnt->init_flag |= JMP_RELOCS_DONE; - if (flag & RTLD_LAZY) { + if (!(tpnt->rtld_flags & RTLD_NOW)) { _dl_parse_lazy_relocation_information(rpnt, tpnt->dynamic_info[DT_JMPREL], tpnt->dynamic_info [DT_PLTRELSZ], 0); diff --git a/ldso/ldso/frv/elfinterp.c b/ldso/ldso/frv/elfinterp.c index 227ef8cad..7e61763ae 100644 --- a/ldso/ldso/frv/elfinterp.c +++ b/ldso/ldso/frv/elfinterp.c @@ -213,15 +213,6 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, int res; symtab_index = ELF32_R_SYM(rpnt->r_info); - - /* When the dynamic linker bootstrapped itself, it resolved some symbols. - Make sure we do not do them again */ - if (!symtab_index && tpnt->libtype == program_interpreter) - continue; - if (symtab_index && tpnt->libtype == program_interpreter && - _dl_symbol(strtab + symtab[symtab_index].st_name)) - continue; - #if defined (__SUPPORT_LD_DEBUG__) debug_sym(symtab,strtab,symtab_index); debug_reloc(symtab,strtab,rpnt); @@ -444,11 +435,6 @@ _dl_parse_relocation_information (struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size, int type __attribute_used__) { - /* The interpreter initial self-relocation is complete, and we - can't re-apply relocations. */ - if (rpnt->dyn->libtype == program_interpreter) - return 0; - return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); } diff --git a/ldso/ldso/i386/elfinterp.c b/ldso/ldso/i386/elfinterp.c index dca5fe54d..4cb9047be 100644 --- a/ldso/ldso/i386/elfinterp.c +++ b/ldso/ldso/i386/elfinterp.c @@ -183,11 +183,6 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, ELF_RELOC *rpnt; int symtab_index; - /* When the dynamic linker bootstrapped itself, it resolved some symbols. - Make sure we do not do them again */ - if (tpnt->libtype == program_interpreter) - return 0; - /* Now parse the relocation information */ rpnt = (ELF_RELOC *)(intptr_t) (rel_addr + tpnt->loadaddr); rel_size = rel_size / sizeof(ELF_RELOC); diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 4256189e7..62b6c7437 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -91,7 +91,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt { ElfW(Phdr) *ppnt; char *lpntstr; - int i, goof = 0, be_lazy = RTLD_LAZY, trace_loaded_objects = 0; + int i, goof = 0, unlazy = 0, trace_loaded_objects = 0; struct dyn_elf *rpnt; struct elf_resolve *tcurr; struct elf_resolve *tpnt1; @@ -127,26 +127,6 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt * this beast to run. We start with the basic executable, and then * go from there. Eventually we will run across ourself, and we * will need to properly deal with that as well. */ - lpnt = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT] + load_addr); - - tpnt->chains = hash_addr; - tpnt->next = 0; - tpnt->libname = 0; - tpnt->libtype = program_interpreter; - tpnt->loadaddr = (ElfW(Addr)) load_addr; - -#ifdef ALLOW_ZERO_PLTGOT - if (tpnt->dynamic_info[DT_PLTGOT]) -#endif - { - INIT_GOT(lpnt, tpnt); -#ifdef __SUPPORT_LD_DEBUG_EARLY__ - _dl_dprintf(_dl_debug_file, "GOT found at %x\n", lpnt); -#endif - } - - /* OK, this was a big step, now we need to scan all of the user images - and load them properly. */ { ElfW(Ehdr) *epnt; ElfW(Phdr) *myppnt; @@ -165,6 +145,8 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt brk_addr = 0; rpnt = NULL; + if (_dl_getenv("LD_BIND_NOW", envp)) + unlazy = RTLD_NOW; /* At this point we are now free to examine the user application, and figure out which libraries are supposed to be called. Until @@ -191,6 +173,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt _dl_symbol_tables = rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); _dl_memset(rpnt, 0, sizeof(struct dyn_elf)); rpnt->dyn = _dl_loaded_modules; + app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL; app_tpnt->usage_count++; app_tpnt->symbol_scope = _dl_symbol_tables; lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT] + app_tpnt->loadaddr); @@ -236,13 +219,9 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt } } - /* Now we need to figure out what kind of options are selected. Note that for SUID programs we ignore the settings in LD_LIBRARY_PATH */ { - if (_dl_getenv("LD_BIND_NOW", envp)) - be_lazy = 0; - if ((auxvt[AT_UID].a_un.a_val == -1 && _dl_suid_ok()) || (auxvt[AT_UID].a_un.a_val != -1 && auxvt[AT_UID].a_un.a_val == auxvt[AT_EUID].a_un.a_val @@ -383,6 +362,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt _dl_exit(15); } } else { + tpnt1->rtld_flags = unlazy | RTLD_GLOBAL; #ifdef __SUPPORT_LD_DEBUG_EARLY__ _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname); #endif @@ -468,6 +448,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt _dl_exit(15); } } else { + tpnt1->rtld_flags = unlazy | RTLD_GLOBAL; #ifdef __SUPPORT_LD_DEBUG_EARLY__ _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname); #endif @@ -525,6 +506,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt _dl_exit(16); } } else { + tpnt1->rtld_flags = unlazy | RTLD_GLOBAL; #ifdef __SUPPORT_LD_DEBUG_EARLY__ _dl_dprintf(_dl_debug_file, "Loading:\t(%x) %s\n", tpnt1->loadaddr, tpnt1->libname); #endif @@ -545,23 +527,14 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt /* * If the program interpreter is not in the module chain, add it. This will * be required for dlopen to be able to access the internal functions in the - * dynamic linker. + * dynamic linker and to relocate the interpreter again once all libs are loaded. */ if (tpnt) { - tcurr = _dl_loaded_modules; - if (tcurr) - while (tcurr->next) - tcurr = tcurr->next; - tpnt->next = NULL; + tpnt = _dl_add_elf_hash_table(tpnt->libname, (char *)load_addr, tpnt->dynamic_info, + (unsigned long)tpnt->dynamic_addr, tpnt->dynamic_size); + tpnt->libtype = program_interpreter; tpnt->usage_count++; - - if (tcurr) { - tcurr->next = tpnt; - tpnt->prev = tcurr; - } else { - _dl_loaded_modules = tpnt; - tpnt->prev = NULL; - } + tpnt->symbol_scope = _dl_symbol_tables; if (rpnt) { rpnt->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); _dl_memset(rpnt->next, 0, sizeof(struct dyn_elf)); @@ -572,6 +545,18 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt _dl_memset(rpnt, 0, sizeof(struct dyn_elf)); } rpnt->dyn = tpnt; + tpnt->rtld_flags = RTLD_NOW | RTLD_GLOBAL; /* Must not be LAZY */ +#ifdef RERELOCATE_LDSO + /* Only rerelocate functions for now. */ + tpnt->init_flag = RELOCS_DONE | COPY_RELOCS_DONE; + lpnt = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT] + load_addr); +# ifdef ALLOW_ZERO_PLTGOT + if (tpnt->dynamic_info[DT_PLTGOT]) +# endif + INIT_GOT(lpnt, tpnt); +#else + tpnt->init_flag = RELOCS_DONE | JMP_RELOCS_DONE | COPY_RELOCS_DONE; +#endif tpnt = NULL; } @@ -602,7 +587,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, struct elf_resolve *app_tpnt * to the GOT tables. We need to do this in reverse order so that COPY * directives work correctly */ if (_dl_symbol_tables) - goof += _dl_fixup(_dl_symbol_tables, be_lazy); + goof += _dl_fixup(_dl_symbol_tables, unlazy); /* OK, at this point things are pretty much ready to run. Now we diff --git a/ldso/ldso/m68k/elfinterp.c b/ldso/ldso/m68k/elfinterp.c index a3f529402..5e8249504 100644 --- a/ldso/ldso/m68k/elfinterp.c +++ b/ldso/ldso/m68k/elfinterp.c @@ -152,13 +152,6 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, reloc_type = ELF32_R_TYPE (rpnt->r_info); symtab_index = ELF32_R_SYM (rpnt->r_info); - /* When the dynamic linker bootstrapped itself, it resolved some symbols. - Make sure we do not do them again. */ - if (tpnt->libtype == program_interpreter - && (!symtab_index - || _dl_symbol (strtab + symtab[symtab_index].st_name))) - continue; - switch (reloc_type) { case R_68K_NONE: @@ -207,12 +200,6 @@ int _dl_parse_relocation_information(struct dyn_elf *rpnt, reloc_type = ELF32_R_TYPE (rpnt->r_info); symtab_index = ELF32_R_SYM (rpnt->r_info); symbol_addr = 0; - - if (tpnt->libtype == program_interpreter - && (!symtab_index - || _dl_symbol (strtab + symtab[symtab_index].st_name))) - continue; - if (symtab_index) { symbol_addr = (unsigned int) @@ -334,10 +321,6 @@ int _dl_parse_copy_information(struct dyn_elf *xpnt, continue; symtab_index = ELF32_R_SYM (rpnt->r_info); symbol_addr = 0; - if (tpnt->libtype == program_interpreter - && (!symtab_index - || _dl_symbol (strtab + symtab[symtab_index].st_name))) - continue; if (symtab_index) { symbol_addr = (unsigned int) diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c index dfbc88fdc..5457e6d7a 100644 --- a/ldso/ldso/mips/elfinterp.c +++ b/ldso/ldso/mips/elfinterp.c @@ -186,10 +186,6 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt, #if defined (__SUPPORT_LD_DEBUG__) unsigned long old_val=0; #endif - - if (tpnt->libtype == program_interpreter) - return 0; - /* Now parse the relocation information */ rel_size = rel_size / sizeof(Elf32_Rel); rpnt = (Elf32_Rel *) (rel_addr + tpnt->loadaddr); @@ -264,11 +260,6 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt) unsigned long *got_entry; for (; tpnt ; tpnt = tpnt->next) { - - /* We don't touch the dynamic linker */ - if (tpnt->libtype == program_interpreter) - continue; - /* Setup the loop variables */ got_entry = (unsigned long *) (tpnt->loadaddr + tpnt->dynamic_info[DT_PLTGOT]) + tpnt->mips_local_gotno; diff --git a/ldso/ldso/powerpc/elfinterp.c b/ldso/ldso/powerpc/elfinterp.c index 0cecf7dc8..103a0fb56 100644 --- a/ldso/ldso/powerpc/elfinterp.c +++ b/ldso/ldso/powerpc/elfinterp.c @@ -396,10 +396,6 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, (void) type; num_plt_entries = rel_size / sizeof(ELF_RELOC); - /* When the dynamic linker bootstrapped itself, it resolved some symbols. - Make sure we do not do them again */ - if (tpnt->libtype == program_interpreter) - return; rel_offset_words = PLT_DATA_START_WORDS(num_plt_entries); plt = (Elf32_Word *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr); @@ -443,11 +439,6 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, ELF_RELOC *rpnt; int symtab_index; - /* When the dynamic linker bootstrapped itself, it resolved some symbols. - Make sure we do not do them again */ - if (tpnt->libtype == program_interpreter) - return 0; - /* Now parse the relocation information */ rpnt = (ELF_RELOC *)(intptr_t) (rel_addr + tpnt->loadaddr); rel_size = rel_size / sizeof(ELF_RELOC); diff --git a/ldso/ldso/sh/elfinterp.c b/ldso/ldso/sh/elfinterp.c index fe920bb9a..3899b70b4 100644 --- a/ldso/ldso/sh/elfinterp.c +++ b/ldso/ldso/sh/elfinterp.c @@ -199,15 +199,6 @@ _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, int res; symtab_index = ELF32_R_SYM(rpnt->r_info); - - /* When the dynamic linker bootstrapped itself, it resolved some symbols. - Make sure we do not do them again */ - if (!symtab_index && tpnt->libtype == program_interpreter) - continue; - if (symtab_index && tpnt->libtype == program_interpreter && - _dl_symbol(strtab + symtab[symtab_index].st_name)) - continue; - #if defined (__SUPPORT_LD_DEBUG__) debug_sym(symtab,strtab,symtab_index); debug_reloc(symtab,strtab,rpnt); diff --git a/ldso/ldso/sh64/elfinterp.c b/ldso/ldso/sh64/elfinterp.c index 3a2b4172c..886349dd2 100644 --- a/ldso/ldso/sh64/elfinterp.c +++ b/ldso/ldso/sh64/elfinterp.c @@ -244,15 +244,6 @@ static int _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, int res; symtab_index = ELF32_R_SYM(rpnt->r_info); - - /* When the dynamic linker bootstrapped itself, it resolved - some symbols. Make sure we do not do them again */ - if (!symtab_index && tpnt->libtype == program_interpreter) - continue; - if (symtab_index && tpnt->libtype == program_interpreter && - _dl_symbol(strtab + symtab[symtab_index].st_name)) - continue; - #ifdef __SUPPORT_LD_DEBUG__ debug_sym(symtab,strtab,symtab_index); debug_reloc(symtab,strtab,rpnt); diff --git a/ldso/ldso/sparc/elfinterp.c b/ldso/ldso/sparc/elfinterp.c index 98435cbd4..44d889ff2 100644 --- a/ldso/ldso/sparc/elfinterp.c +++ b/ldso/ldso/sparc/elfinterp.c @@ -169,13 +169,6 @@ void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, reloc_type = ELF32_R_TYPE(rpnt->r_info); symtab_index = ELF32_R_SYM(rpnt->r_info); - /* When the dynamic linker bootstrapped itself, it resolved some symbols. - Make sure we do not do them again */ - if(!symtab_index && tpnt->libtype == program_interpreter) continue; - if(symtab_index && tpnt->libtype == program_interpreter && - _dl_symbol(strtab + symtab[symtab_index].st_name)) - continue; - switch(reloc_type){ case R_SPARC_NONE: break; @@ -219,14 +212,8 @@ int _dl_parse_relocation_information(struct dyn_elf *rpnt, symtab_index = ELF32_R_SYM(rpnt->r_info); symbol_addr = 0; - if(!symtab_index && tpnt->libtype == program_interpreter) continue; - if(symtab_index) { - if(tpnt->libtype == program_interpreter && - _dl_symbol(strtab + symtab[symtab_index].st_name)) - continue; - symbol_addr = (unsigned int) _dl_find_hash(strtab + symtab[symtab_index].st_name, tpnt->symbol_scope, elf_machine_type_class(reloc_type)); @@ -337,13 +324,7 @@ int _dl_parse_copy_information(struct dyn_elf *xpnt, if(reloc_type != R_SPARC_COPY) continue; symtab_index = ELF32_R_SYM(rpnt->r_info); symbol_addr = 0; - if(!symtab_index && tpnt->libtype == program_interpreter) continue; if(symtab_index) { - - if(tpnt->libtype == program_interpreter && - _dl_symbol(strtab + symtab[symtab_index].st_name)) - continue; - symbol_addr = (unsigned int) _dl_find_hash(strtab + symtab[symtab_index].st_name, xpnt->next, ELF_RTYPE_CLASS_COPY); -- cgit v1.2.3