summaryrefslogtreecommitdiff
path: root/ldso/ldso/ldso.c
diff options
context:
space:
mode:
authorFilippo Arcidiacono <filippo.arcidiacono@st.com>2010-07-30 14:18:38 +0200
committerCarmelo Amoroso <carmelo.amoroso@st.com>2010-09-17 16:12:14 +0200
commit02f56b3ae9f620528c3c1bb42662b4499d19f383 (patch)
treeeded946d1bb8daaa35f5b8d65123398860d13446 /ldso/ldso/ldso.c
parent4136ca46e391faf1a6ce58b9a1a709b248213fb4 (diff)
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 <filippo.arcidiacono@st.com> Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
Diffstat (limited to 'ldso/ldso/ldso.c')
-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));