summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ldso/ldso/ldso.c119
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));