#include LDSO_ELFINTERP
/* Global variables used within the shared library loader */
+#ifdef __LDSO_LD_LIBRARY_PATH__
char *_dl_library_path = NULL; /* Where we look for libraries */
+#endif
#ifdef __LDSO_PRELOAD_ENV_SUPPORT__
char *_dl_preload = NULL; /* Things to be loaded before the libs */
#endif
-char *_dl_ldsopath = NULL; /* Location of the shared lib loader */
int _dl_errno = 0; /* We can't use the real errno in ldso */
size_t _dl_pagesize = 0; /* Store the page size for use later */
struct r_debug *_dl_debug_addr = NULL; /* Used to communicate with the gdb debugger */
char *_dl_trace_prelink = NULL; /* Library for prelinking trace */
struct elf_resolve *_dl_trace_prelink_map = NULL; /* Library module for prelinking trace */
bool _dl_verbose = true; /* On by default */
+bool prelinked = false;
#endif
-static int _dl_secure = 1; /* Are we dealing with setuid stuff? */
+int _dl_secure = 1; /* Are we dealing with setuid stuff? */
#ifdef __SUPPORT_LD_DEBUG__
char *_dl_debug = NULL;
int _dl_debug_file = 2;
#endif
-#if defined (__LDSO_STANDALONE_SUPPORT__) && defined (__sh__)
-/* Not hidden, needed for standalone execution. */
-/*
- * FIXME: align dl_start for SH to other archs so that we can keep this symbol
- * hidden and we don't need to handle in __uClibc_main
- */
+#ifdef __DSBT__
+void **_dl_ldso_dsbt = NULL;
+#endif
-unsigned long _dl_skip_args = 0;
-#else
unsigned long attribute_hidden _dl_skip_args = 0;
-#endif
const char *_dl_progname = UCLIBC_LDSO; /* The name of the executable being run */
#include "dl-startup.c"
#ifdef __UCLIBC_HAS_SSP__
# include <dl-osinfo.h>
-uintptr_t stack_chk_guard;
+static uintptr_t stack_chk_guard;
# ifndef THREAD_SET_STACK_GUARD
/* Only exported for architectures that don't store the stack guard canary
* in local thread area. */
uintptr_t __stack_chk_guard attribute_relro;
-# ifdef __UCLIBC_HAS_SSP_COMPAT__
-strong_alias(__stack_chk_guard,__guard)
-# endif
-# elif __UCLIBC_HAS_SSP_COMPAT__
+# endif
+# ifdef __UCLIBC_HAS_SSP_COMPAT__
uintptr_t __guard attribute_relro;
# endif
#endif
+#ifdef __LDSO_SEARCH_INTERP_PATH__
+const char *_dl_ldsopath = NULL; /* Location of the shared lib loader */
+
+static void _dl_ldsopath_init(struct elf_resolve *tpnt)
+{
+ char *ldsopath, *ptmp;
+
+ /*
+ * Store the path where the shared lib loader was found for later use.
+ * Note that this logic isn't bullet proof when it comes to relative
+ * paths: if you use "./lib/ldso.so", and then the app does chdir()
+ * followed by dlopen(), the old ldso path won't get searched. But
+ * that is a fairly pathological use case, so if you don't like that,
+ * then set a full path to your interp and be done :P.
+ */
+ ldsopath = _dl_strdup(tpnt->libname);
+ ptmp = _dl_strrchr(ldsopath, '/');
+ /*
+ * If there is no "/", then set the path to "", and the code
+ * later on will take this to implicitly mean "search $PWD".
+ */
+ if (!ptmp)
+ ptmp = ldsopath;
+ *ptmp = '\0';
+
+ _dl_ldsopath = ldsopath;
+ _dl_debug_early("Lib Loader: (%x) %s: using path: %s\n",
+ (unsigned) DL_LOADADDR_BASE(tpnt->loadaddr), tpnt->libname,
+ _dl_ldsopath);
+}
+#else
+#define _dl_ldsopath_init(tpnt)
+#endif
+
char *_dl_getenv(const char *symbol, char **envp)
{
char *pnt;
_dl_debug_early("mmapping more memory\n");
_dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, rounded_size,
- PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZE, -1, 0);
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZED, -1, 0);
if (_dl_mmap_check_error(_dl_mmap_zero)) {
- _dl_dprintf(_dl_debug_file, "%s: mmap of a spare page failed!\n", _dl_progname);
+ _dl_dprintf(2, "%s: mmap of a spare page failed!\n", _dl_progname);
_dl_exit(20);
}
}
}
#ifdef __LDSO_PRELINK_SUPPORT__
-
static void trace_objects(struct elf_resolve *tpnt, char *str_name)
{
if (_dl_strcmp(_dl_trace_prelink, tpnt->libname) == 0)
tpnt->mapaddr, DL_LOADADDR_BASE(tpnt->loadaddr));
}
+#if defined USE_TLS && USE_TLS
if ((tpnt->libtype != program_interpreter) && (tpnt->l_tls_modid))
_dl_dprintf (1, " TLS(%x, %x)\n", tpnt->l_tls_modid,
(size_t) tpnt->l_tls_offset);
else
+#endif
_dl_dprintf (1, "\n");
}
-
#endif
+static struct elf_resolve * add_ldso(struct elf_resolve *tpnt,
+ DL_LOADADDR_TYPE load_addr,
+ ElfW(Addr) ldso_mapaddr,
+ 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(DL_GET_RUN_ADDR(load_addr, ldso_mapaddr),
+ 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);
+
+ tpnt->mapaddr = ldso_mapaddr;
+ 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)
{
ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv
DL_GET_READY_TO_RUN_EXTRA_PARMS)
{
- ElfW(Addr) app_mapaddr = 0;
+ ElfW(Addr) app_mapaddr = 0, ldso_mapaddr = 0;
ElfW(Phdr) *ppnt;
ElfW(Dyn) *dpnt;
char *lpntstr;
- unsigned int i, cnt, k, nscope_elem;
+ unsigned int i, cnt, nscope_elem;
int unlazy = 0, trace_loaded_objects = 0;
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;
struct r_scope_elem *global_scope;
struct elf_resolve **local_scope;
- struct stat st;
#if defined(USE_TLS) && USE_TLS
void *tcbp = NULL;
#endif
_dl_progname = argv[0];
}
+#ifdef __DSBT__
+ _dl_ldso_dsbt = (void *)tpnt->dynamic_info[DT_DSBT_BASE_IDX];
+ _dl_ldso_dsbt[tpnt->dynamic_info[DT_DSBT_INDEX_IDX]] = _dl_ldso_dsbt;
+#endif
+
#ifndef __LDSO_STANDALONE_SUPPORT__
if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
- _dl_dprintf(_dl_debug_file, "Standalone execution is not enabled\n");
+ _dl_dprintf(2, "Standalone execution is not enabled\n");
_dl_exit(1);
}
#endif
#ifdef __LDSO_PRELOAD_ENV_SUPPORT__
_dl_preload = _dl_getenv("LD_PRELOAD", envp);
#endif
+#ifdef __LDSO_LD_LIBRARY_PATH__
_dl_library_path = _dl_getenv("LD_LIBRARY_PATH", envp);
+#endif
} else {
static const char unsecure_envvars[] =
#ifdef EXTRA_UNSECURE_ENVVARS
const char *nextp;
_dl_secure = 1;
+#ifdef __LDSO_PRELOAD_ENV_SUPPORT__
+ _dl_preload = _dl_getenv("LD_PRELOAD", envp);
+#endif
nextp = unsecure_envvars;
do {
_dl_unsetenv (nextp, envp);
/* We could use rawmemchr but this need not be fast. */
nextp = _dl_strchr(nextp, '\0') + 1;
} while (*nextp != '\0');
-#ifdef __LDSO_PRELOAD_ENV_SUPPORT__
- _dl_preload = NULL;
-#endif
+#ifdef __LDSO_LD_LIBRARY_PATH__
_dl_library_path = NULL;
+#endif
/* SUID binaries can be exploited if they do LAZY relocation. */
unlazy = RTLD_NOW;
}
#ifdef __LDSO_STANDALONE_SUPPORT__
if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) {
- char *ptmp;
- unsigned int *aux_dat = (unsigned int *) argv;
- int argc = aux_dat[-1];
+ ElfW(Addr) *aux_dat = (ElfW(Addr) *) argv;
+ int argc = (int) aux_dat[-1];
tpnt->libname = argv[0];
while (argc > 1)
if (! _dl_strcmp (argv[1], "--library-path") && argc > 2) {
+#ifdef __LDSO_LD_LIBRARY_PATH__
_dl_library_path = argv[2];
+#endif
_dl_skip_args += 2;
argc -= 2;
argv += 2;
*/
app_tpnt = _dl_load_elf_shared_library(_dl_secure, &rpnt, _dl_progname);
if (!app_tpnt) {
- _dl_dprintf(_dl_debug_file, "can't load '%s'\n", _dl_progname);
+ _dl_dprintf(2, "can't load '%s'\n", _dl_progname);
_dl_exit(16);
}
/*
app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
- if (app_tpnt->libtype == elf_executable)
- app_tpnt->loadaddr = 0;
-
/*
* This is used by gdb to locate the chain of shared libraries that are
* currently loaded.
}
}
- /* Store the path where the shared lib loader was found
- * for later use
- */
- _dl_ldsopath = _dl_strdup(tpnt->libname);
- ptmp = _dl_strrchr(_dl_ldsopath, '/');
- if (ptmp != _dl_ldsopath)
- *ptmp = '\0';
-
- _dl_debug_early("Lib Loader: (%x) %s\n", (unsigned) DL_LOADADDR_BASE(tpnt->loadaddr), tpnt->libname);
+ _dl_ldsopath_init(tpnt);
} else {
#endif
}
#else
if (app_tpnt->dynamic_info[DT_TEXTREL]) {
- _dl_dprintf(_dl_debug_file, "Can't modify application's text section; use the GCC option -fPIE for position-independent executables.\n");
+ _dl_dprintf(2, "Can't modify application's text section; use the GCC option -fPIE for position-independent executables.\n");
_dl_exit(1);
}
#endif
app_tpnt->mapaddr = app_mapaddr;
app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL;
app_tpnt->usage_count++;
+#ifdef __DSBT__
+ _dl_ldso_dsbt[0] = app_tpnt->dsbt_table;
+ _dl_memcpy(app_tpnt->dsbt_table, _dl_ldso_dsbt,
+ app_tpnt->dsbt_size * sizeof(tpnt->dsbt_table[0]));
+#endif
lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]);
#ifdef ALLOW_ZERO_PLTGOT
if (lpnt)
/* OK, fill this in - we did not have this before */
if (ppnt->p_type == PT_INTERP) {
tpnt->libname = (char *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr);
-#ifdef __LDSO_SEARCH_INTERP_PATH__
- {
- char *ptmp;
- /* Store the path where the shared lib loader was found
- * for later use
- */
- _dl_ldsopath = _dl_strdup(tpnt->libname);
- ptmp = _dl_strrchr(_dl_ldsopath, '/');
- if (ptmp != _dl_ldsopath)
- *ptmp = '\0';
- }
- _dl_debug_early("Lib Loader: (%x) %s\n", (unsigned) DL_LOADADDR_BASE(tpnt->loadaddr), tpnt->libname);
-#endif
+
+ _dl_ldsopath_init(tpnt);
}
/* Discover any TLS sections if the target supports them. */
_dl_tls_max_dtv_idx = app_tpnt->l_tls_modid = 1;
}
- _dl_debug_early("Found TLS header for appplication program\n");
+ _dl_debug_early("Found TLS header for application program\n");
break;
#else
- _dl_dprintf(_dl_debug_file, "Program uses unsupported TLS data!\n");
+ _dl_dprintf(2, "Program uses unsupported TLS data!\n");
_dl_exit(1);
#endif
}
* case the executable is actually an ET_DYN object.
*/
if (app_tpnt->l_tls_initimage != NULL) {
- unsigned int tmp = (unsigned int) app_tpnt->l_tls_initimage;
+ char *tmp attribute_unused =
+ (char *) app_tpnt->l_tls_initimage;
app_tpnt->l_tls_initimage =
(char *) app_tpnt->l_tls_initimage + app_tpnt->loadaddr;
_dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n",
#ifndef __LDSO_LDD_SUPPORT__
if (trace_loaded_objects) {
- _dl_dprintf(_dl_debug_file, "Use the ldd provided by uClibc\n");
+ _dl_dprintf(2, "Use the ldd provided by uClibc\n");
_dl_exit(1);
}
#endif
+ ldso_mapaddr = (ElfW(Addr)) auxvt[AT_BASE].a_un.a_val;
/*
* OK, fix one more thing - set up debug_addr so it will point
* to our chain. Later we may need to fill in more fields, but this
*/
debug_addr->r_map = (struct link_map *) _dl_loaded_modules;
debug_addr->r_version = 1;
- debug_addr->r_ldbase = (ElfW(Addr)) DL_LOADADDR_BASE(load_addr);
+ debug_addr->r_ldbase = (ElfW(Addr))
+ DL_LOADADDR_BASE(DL_GET_RUN_ADDR(load_addr, ldso_mapaddr));
debug_addr->r_brk = (unsigned long) &_dl_debug_state;
_dl_debug_addr = debug_addr;
if (!_dl_secure || _dl_strchr(str, '/') == NULL) {
_dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", str, _dl_progname);
- tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str, trace_loaded_objects);
+ tpnt1 = _dl_load_shared_library(
+ _dl_secure ? DL_RESOLVE_SECURE : 0,
+ &rpnt, NULL, str, trace_loaded_objects);
if (!tpnt1) {
#ifdef __LDSO_LDD_SUPPORT__
if (trace_loaded_objects || _dl_trace_prelink)
else
#endif
{
- _dl_dprintf(_dl_debug_file, "%s: can't load " "library '%s'\n", _dl_progname, str);
- _dl_exit(15);
+ _dl_dprintf(2, "%s: library '%s' "
+ "from LD_PRELOAD can't be preloaded: ignored.\n",
+ _dl_progname, str);
}
} else {
tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
char *preload;
int fd;
char c, *cp, *cp2;
+ struct stat st;
if (_dl_stat(LDSO_PRELOAD, &st) || st.st_size == 0) {
break;
}
if ((fd = _dl_open(LDSO_PRELOAD, O_RDONLY, 0)) < 0) {
- _dl_dprintf(_dl_debug_file, "%s: can't open file '%s'\n",
+ _dl_dprintf(2, "%s: can't open file '%s'\n",
_dl_progname, LDSO_PRELOAD);
break;
}
PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
_dl_close(fd);
if (preload == (caddr_t) -1) {
- _dl_dprintf(_dl_debug_file, "%s:%i: can't map '%s'\n",
+ _dl_dprintf(2, "%s:%i: can't map '%s'\n",
_dl_progname, __LINE__, LDSO_PRELOAD);
break;
}
else
# endif
{
- _dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, cp2);
+ _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, cp2);
_dl_exit(15);
}
} else {
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,
+ ldso_mapaddr, 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);
} else
#endif
{
- _dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, lpntstr);
+ _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, lpntstr);
_dl_exit(16);
}
}
* 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, ldso_mapaddr, 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. */
tpnt->init_flag = RELOCS_DONE | JMP_RELOCS_DONE;
#endif
tpnt = NULL;
- }
/*
* Allocate the global scope array.
local_scope = _dl_malloc(nscope_elem * sizeof(struct elf_resolve *));
i = 1;
for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) {
+ unsigned int k;
cnt = _dl_build_local_scope(local_scope, scope_elem_list[i++]);
tcurr->symbol_scope.r_list = _dl_malloc(cnt * sizeof(struct elf_resolve *));
tcurr->symbol_scope.r_nlist = cnt;
_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
stack_chk_guard = _dl_setup_stack_chk_guard ();
# ifdef THREAD_SET_STACK_GUARD
THREAD_SET_STACK_GUARD (stack_chk_guard);
-# ifdef __UCLIBC_HAS_SSP_COMPAT__
- __guard = stack_chk_guard;
-# endif
# else
__stack_chk_guard = stack_chk_guard;
# endif
+# ifdef __UCLIBC_HAS_SSP_COMPAT__
+ __guard = stack_chk_guard;
+# 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));
_dl_exit(-1);
_dl_exit(0);
}
+
+ if (_dl_loaded_modules->dynamic_info[DT_GNU_LIBLIST_IDX]) {
+ ElfW(Lib) *liblist, *liblistend;
+ struct elf_resolve **r_list, **r_listend, *l;
+ const char *strtab = (const char *)_dl_loaded_modules->dynamic_info[DT_STRTAB];
+
+ _dl_assert (_dl_loaded_modules->dynamic_info[DT_GNU_LIBLISTSZ_IDX] != 0);
+ liblist = (ElfW(Lib) *) _dl_loaded_modules->dynamic_info[DT_GNU_LIBLIST_IDX];
+ liblistend = (ElfW(Lib) *)
+ ((char *) liblist + _dl_loaded_modules->dynamic_info[DT_GNU_LIBLISTSZ_IDX]);
+ r_list = _dl_loaded_modules->symbol_scope.r_list;
+ r_listend = r_list + nscope_elem;
+
+ for (; r_list < r_listend && liblist < liblistend; r_list++) {
+ l = *r_list;
+
+ if (l == _dl_loaded_modules)
+ continue;
+
+ /* If the library is not mapped where it should, fail. */
+ if (l->loadaddr)
+ break;
+
+ /* Next, check if checksum matches. */
+ if (l->dynamic_info[DT_CHECKSUM_IDX] == 0 ||
+ l->dynamic_info[DT_CHECKSUM_IDX] != liblist->l_checksum)
+ break;
+
+ if (l->dynamic_info[DT_GNU_PRELINKED_IDX] == 0 ||
+ (l->dynamic_info[DT_GNU_PRELINKED_IDX] != liblist->l_time_stamp))
+ break;
+
+ if (_dl_strcmp(strtab + liblist->l_name, _dl_get_last_path_component(l->libname)) != 0)
+ break;
+
+ ++liblist;
+ }
+
+
+ if (r_list == r_listend && liblist == liblistend)
+ prelinked = true;
+
+ }
+
+ _dl_debug_early ("\nprelink checking: %s\n", prelinked ? "ok" : "failed");
+
+ if (prelinked) {
+ if (_dl_loaded_modules->dynamic_info[DT_GNU_CONFLICT_IDX]) {
+ ELF_RELOC *conflict;
+ unsigned long conflict_size;
+
+ _dl_assert (_dl_loaded_modules->dynamic_info[DT_GNU_CONFLICTSZ_IDX] != 0);
+ conflict = (ELF_RELOC *) _dl_loaded_modules->dynamic_info[DT_GNU_CONFLICT_IDX];
+ conflict_size = _dl_loaded_modules->dynamic_info[DT_GNU_CONFLICTSZ_IDX];
+ _dl_parse_relocation_information(_dl_symbol_tables, global_scope,
+ (unsigned long) conflict, conflict_size);
+ }
+
+ /* Mark all the objects so we know they have been already relocated. */
+ for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
+ tpnt->init_flag |= RELOCS_DONE;
+ if (tpnt->relro_size)
+ _dl_protect_relro (tpnt);
+ }
+ } else
#endif
+ {
+
_dl_debug_early("Beginning relocation fixups\n");
#ifdef __mips__
if (tpnt->relro_size)
_dl_protect_relro (tpnt);
}
+ } /* not prelinked */
#if defined(USE_TLS) && USE_TLS
if (!was_tls_init_tp_called && _dl_tls_max_dtv_idx > 0)
* ld.so.1, so we have to look up each symbol individually.
*/
- _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", global_scope, NULL, NULL, 0, NULL);
+ _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", global_scope, NULL, 0, NULL);
if (_dl_envp)
*_dl_envp = (unsigned long) envp;
/* Find the real malloc function and make ldso functions use that from now on */
_dl_malloc_function = (void* (*)(size_t)) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "malloc",
- global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+ global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
#if defined(USE_TLS) && USE_TLS
/* Find the real functions and make ldso functions use them from now on */
_dl_calloc_function = (void* (*)(size_t, size_t)) (intptr_t)
- _dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+ _dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
_dl_realloc_function = (void* (*)(void *, size_t)) (intptr_t)
- _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+ _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
_dl_free_function = (void (*)(void *)) (intptr_t)
- _dl_find_hash(__C_SYMBOL_PREFIX__ "free", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+ _dl_find_hash(__C_SYMBOL_PREFIX__ "free", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
_dl_memalign_function = (void* (*)(size_t, size_t)) (intptr_t)
- _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", global_scope, NULL, NULL, ELF_RTYPE_CLASS_PLT, NULL);
+ _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", global_scope, NULL, ELF_RTYPE_CLASS_PLT, NULL);
#endif