diff options
Diffstat (limited to 'ldso')
-rw-r--r-- | ldso/ldso/ldso.c | 119 |
1 files 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)); |