From 02f56b3ae9f620528c3c1bb42662b4499d19f383 Mon Sep 17 00:00:00 2001 From: Filippo Arcidiacono Date: Fri, 30 Jul 2010 14:18:38 +0200 Subject: ldso: Do not add the ld.so at the end of the loaded modules list The dynamic linker was included indifferently at the end of the loaded modules list. In order to be used with prelink, it is required to included the ld.so in the local scope of each shared libraries that depends directly on it. Also it is included in the global scope at the first occurrence. Signed-off-by: Filippo Arcidiacono Signed-off-by: Carmelo Amoroso --- ldso/ldso/ldso.c | 119 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 64 insertions(+), 55 deletions(-) diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 8c6e4d185..4a7b6398f 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -291,7 +291,6 @@ static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void) } #ifdef __LDSO_PRELINK_SUPPORT__ - static void trace_objects(struct elf_resolve *tpnt, char *str_name) { if (_dl_strcmp(_dl_trace_prelink, tpnt->libname) == 0) @@ -312,9 +311,50 @@ static void trace_objects(struct elf_resolve *tpnt, char *str_name) else _dl_dprintf (1, "\n"); } - #endif +static struct elf_resolve * add_ldso(struct elf_resolve *tpnt, + DL_LOADADDR_TYPE load_addr, + ElfW(auxv_t) auxvt[AT_EGID + 1], + struct dyn_elf *rpnt) +{ + ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val; + ElfW(Phdr) *myppnt = (ElfW(Phdr) *) + DL_RELOC_ADDR(load_addr, epnt->e_phoff); + int j; + struct stat st; + + tpnt = _dl_add_elf_hash_table(tpnt->libname, tpnt->loadaddr, + tpnt->dynamic_info, (unsigned long)tpnt->dynamic_addr, + 0); + + if (_dl_stat(tpnt->libname, &st) >= 0) { + tpnt->st_dev = st.st_dev; + tpnt->st_ino = st.st_ino; + } + 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; + if (rpnt) { + rpnt->next = _dl_zalloc(sizeof(struct dyn_elf)); + rpnt->next->prev = rpnt; + rpnt = rpnt->next; + } else { + rpnt = _dl_zalloc(sizeof(struct dyn_elf)); + } + rpnt->dyn = tpnt; + tpnt->rtld_flags = RTLD_NOW | RTLD_GLOBAL; /* Must not be LAZY */ + + return tpnt; +} + static ptrdiff_t _dl_build_local_scope (struct elf_resolve **list, struct elf_resolve *map) { @@ -343,6 +383,7 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, struct dyn_elf *rpnt; struct elf_resolve *tcurr; struct elf_resolve *tpnt1; + struct elf_resolve *ldso_tpnt = NULL; struct elf_resolve app_tpnt_tmp; struct elf_resolve *app_tpnt = &app_tpnt_tmp; struct r_debug *debug_addr; @@ -353,7 +394,6 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, struct r_scope_elem *global_scope; struct elf_resolve **local_scope; - struct stat st; #if defined(USE_TLS) && USE_TLS void *tcbp = NULL; #endif @@ -944,12 +984,19 @@ of this helper program; chances are you did not intend to run this program.\n\ lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + this_dpnt->d_un.d_val); name = _dl_get_last_path_component(lpntstr); - if (_dl_strcmp(name, UCLIBC_LDSO) == 0) - continue; - _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", lpntstr, _dl_progname); - if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects))) { + if (_dl_strcmp(name, UCLIBC_LDSO) == 0) { + if (!ldso_tpnt) { + /* Insert the ld.so only once */ + ldso_tpnt = add_ldso(tpnt, load_addr, auxvt, rpnt); + } + ldso_tpnt->usage_count++; + tpnt1 = ldso_tpnt; + } else + tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects); + + if (!tpnt1) { #ifdef __LDSO_LDD_SUPPORT__ if (trace_loaded_objects || _dl_trace_prelink) { _dl_dprintf(1, "\t%s => not found\n", lpntstr); @@ -1041,41 +1088,12 @@ of this helper program; chances are you did not intend to run this program.\n\ * functions in the dynamic linker and to relocate the interpreter * again once all libs are loaded. */ - if (tpnt) { - ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val; - ElfW(Phdr) *myppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(load_addr, epnt->e_phoff); - int j; - - tpnt = _dl_add_elf_hash_table(tpnt->libname, load_addr, - tpnt->dynamic_info, - (unsigned long)tpnt->dynamic_addr, - 0); - - if (_dl_stat(tpnt->libname, &st) >= 0) { - tpnt->st_dev = st.st_dev; - tpnt->st_ino = st.st_ino; - } - 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; + if (!ldso_tpnt) { + tpnt = add_ldso(tpnt, load_addr, auxvt, rpnt); tpnt->usage_count++; nscope_elem++; - if (rpnt) { - rpnt->next = _dl_zalloc(sizeof(struct dyn_elf)); - rpnt->next->prev = rpnt; - rpnt = rpnt->next; - } else { - rpnt = _dl_zalloc(sizeof(struct dyn_elf)); - } - rpnt->dyn = tpnt; - tpnt->rtld_flags = RTLD_NOW | RTLD_GLOBAL; /* Must not be LAZY */ + } else + tpnt = ldso_tpnt; #ifdef RERELOCATE_LDSO /* Only rerelocate functions for now. */ @@ -1089,7 +1107,6 @@ of this helper program; chances are you did not intend to run this program.\n\ tpnt->init_flag = RELOCS_DONE | JMP_RELOCS_DONE; #endif tpnt = NULL; - } /* * Allocate the global scope array. @@ -1124,13 +1141,9 @@ of this helper program; chances are you did not intend to run this program.\n\ _dl_free(local_scope); #ifdef __LDSO_LDD_SUPPORT__ - /* End of the line for ldd.... */ - if (trace_loaded_objects && !_dl_trace_prelink) { - _dl_dprintf(1, "\t%s => %s (%x)\n", - rpnt->dyn->libname + _dl_strlen(_dl_ldsopath) + 1, - rpnt->dyn->libname, DL_LOADADDR_BASE(rpnt->dyn->loadaddr)); + /* Exit if LD_TRACE_LOADED_OBJECTS is on. */ + if (trace_loaded_objects && !_dl_trace_prelink) _dl_exit(0); - } #endif #if defined(USE_TLS) && USE_TLS @@ -1160,16 +1173,12 @@ of this helper program; chances are you did not intend to run this program.\n\ # endif #endif - - /* FIXME: The glibc code doesn't trace the ldso when LD_TRACE_OBJECT is set, - * here has been trace to mantain the original one. - * Another difference Vs Glibc is the check to verify if an object is - * "statically linked" (only if LD_TRACE_OBJECT is on). - */ - #ifdef __LDSO_PRELINK_SUPPORT__ if (_dl_trace_prelink) { - for (i = 0; i < nscope_elem; i++) + + unsigned int nscope_trace = ldso_tpnt ? nscope_elem : (nscope_elem - 1); + + for (i = 0; i < nscope_trace; i++) trace_objects(scope_elem_list[i], _dl_get_last_path_component(scope_elem_list[i]->libname)); -- cgit v1.2.3