_dl_strcpy(mylibname, "."); /* Assume current dir if empty path */
_dl_strcat(mylibname, "/");
_dl_strcat(mylibname, name);
- if ((tpnt = _dl_load_elf_shared_library(rflags, rpnt, mylibname)) != NULL)
- return tpnt;
+#ifdef __LDSO_SAFE_RUNPATH__
+ if (*mylibname == '/')
+#endif
+ if ((tpnt = _dl_load_elf_shared_library(rflags, rpnt, mylibname)) != NULL)
+ return tpnt;
path_n = path+1;
}
path++;
return NULL;
}
+/* Define the _dl_library_offset for the architectures that need it */
+DL_DEF_LIB_OFFSET;
+
/*
* Make a writeable mapping of a segment, regardless of whether PF_W is
* set or not.
}
tryaddr = piclib == 2 ? piclib2map
- : ((char*) (piclib ? libaddr : 0) +
+ : ((char *) (piclib ? libaddr : DL_GET_LIB_OFFSET()) +
(ppnt->p_vaddr & PAGE_ALIGN));
size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
size_t relro_size = 0;
struct stat st;
uint32_t *p32;
- DL_LOADADDR_TYPE lib_loadaddr = 0;
+ DL_LOADADDR_TYPE lib_loadaddr;
DL_INIT_LOADADDR_EXTRA_DECLS
libaddr = 0;
return NULL;
}
header = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZE, -1, 0);
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZED, -1, 0);
if (_dl_mmap_check_error(header)) {
_dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname);
_dl_internal_error_number = LD_ERROR_MMAP_FAILED;
ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
DL_INIT_LOADADDR(lib_loadaddr, libaddr - minvma, ppnt, epnt->e_phnum);
+ /* Set _dl_library_offset to lib_loadaddr or 0. */
+ DL_SET_LIB_OFFSET(lib_loadaddr);
for (i = 0; i < epnt->e_phnum; i++) {
if (DL_IS_SPECIAL_SEGMENT (epnt, ppnt)) {
} else {
tryaddr = (piclib == 2 ? 0
: (char *) (ppnt->p_vaddr & PAGE_ALIGN)
- + (piclib ? libaddr : lib_loadaddr));
+ + (piclib ? libaddr : DL_GET_LIB_OFFSET()));
size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
status = (char *) _dl_mmap
(tryaddr, size, LXFLAGS(ppnt->p_flags),
* The dynamic_addr must be take into acount lib_loadaddr value, to note
* it is zero when the SO has been mapped to the elf's physical addr
*/
- if (lib_loadaddr) {
+#ifdef __LDSO_PRELINK_SUPPORT__
+ if (DL_GET_LIB_OFFSET()) {
+#else
+ if (piclib) {
+#endif
dynamic_addr = (unsigned long) DL_RELOC_ADDR(lib_loadaddr, dynamic_addr);
}
for (i = 0; i < epnt->e_phnum; i++, ppnt++) {
if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) {
#ifdef __ARCH_USE_MMU__
- _dl_mprotect((void *) ((piclib ? libaddr : lib_loadaddr) +
+ _dl_mprotect((void *) ((piclib ? libaddr : DL_GET_LIB_OFFSET()) +
(ppnt->p_vaddr & PAGE_ALIGN)),
(ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz,
PROT_READ | PROT_WRITE | PROT_EXEC);
}
}
#else
- _dl_dprintf(_dl_debug_file, "Can't modify %s's text section."
+ _dl_dprintf(2, "Can't modify %s's text section."
" Use GCC option -fPIC for shared objects, please.\n",
libname);
_dl_exit(1);
tpnt->relro_size = relro_size;
tpnt->st_dev = st.st_dev;
tpnt->st_ino = st.st_ino;
- tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(tpnt->mapaddr, epnt->e_phoff);
+ tpnt->ppnt = (ElfW(Phdr) *)
+ DL_RELOC_ADDR(DL_GET_RUN_ADDR(tpnt->loadaddr, tpnt->mapaddr),
+ epnt->e_phoff);
tpnt->n_phent = epnt->e_phnum;
tpnt->rtld_flags |= rtld_flags;
#ifdef __LDSO_STANDALONE_SUPPORT__
#endif
{
# ifdef __SUPPORT_LD_DEBUG_EARLY__
- unsigned int tmp = (unsigned int) tpnt->l_tls_initimage;
+ char *tmp = (char *) tpnt->l_tls_initimage;
tpnt->l_tls_initimage = (char *) tlsppnt->p_vaddr + tpnt->loadaddr;
_dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n", tmp, tpnt->l_tls_initimage, tpnt->l_tls_initimage_size);
tmp = 0;
/* Handle DSBT initialization */
{
struct elf_resolve *t, *ref;
- int idx = tpnt->loadaddr.map->dsbt_index;
- unsigned *dsbt = tpnt->loadaddr.map->dsbt_table;
+ int idx = tpnt->dsbt_index;
+ void **dsbt = tpnt->dsbt_table;
- if (idx == 0) {
+ /*
+ * It is okay (required actually) to have zero idx for an executable.
+ * This is the case when running ldso standalone and the program
+ * is being mapped in via _dl_load_shared_library().
+ */
+ if (idx == 0 && tpnt->libtype != elf_executable) {
if (!dynamic_info[DT_TEXTREL]) {
/* This DSO has not been assigned an index. */
_dl_dprintf(2, "%s: '%s' is missing a dsbt index assignment!\n",
break;
}
}
- idx = tpnt->loadaddr.map->dsbt_size;
+ idx = tpnt->dsbt_size;
while (idx-- > 0)
- if (!ref || ref->loadaddr.map->dsbt_table[idx] == NULL)
+ if (!ref || ref->dsbt_table[idx] == NULL)
break;
if (idx <= 0) {
_dl_dprintf(2, "%s: '%s' caused DSBT table overflow!\n",
}
_dl_if_debug_dprint("\n\tfile='%s'; assigned index %d\n",
libname, idx);
- tpnt->loadaddr.map->dsbt_index = idx;
+ tpnt->dsbt_index = idx;
+ }
+
+ /* make sure index is not already used */
+ if (_dl_ldso_dsbt[idx]) {
+ struct elf_resolve *dup;
+ const char *dup_name;
+ for (dup = _dl_loaded_modules; dup; dup = dup->next)
+ if (dup != tpnt && dup->dsbt_index == idx)
+ break;
+ if (dup)
+ dup_name = dup->libname;
+ else if (idx == 1)
+ dup_name = "runtime linker";
+ else
+ dup_name = "unknown library";
+ _dl_dprintf(2, "%s: '%s' dsbt index %d already used by %s!\n",
+ _dl_progname, libname, idx, dup_name);
+ _dl_exit(1);
}
/*
* Setup dsbt slot for this module in dsbt of all modules.
*/
- ref = NULL;
- for (t = _dl_loaded_modules; t; t = t->next) {
- /* find a dsbt table from another module */
- if (ref == NULL && t != tpnt) {
- ref = t;
-
- /* make sure index is not already used */
- if (t->loadaddr.map->dsbt_table[idx]) {
- struct elf_resolve *dup;
- char *dup_name;
-
- for (dup = _dl_loaded_modules; dup; dup = dup->next)
- if (dup != tpnt && dup->loadaddr.map->dsbt_index == idx)
- break;
- if (dup)
- dup_name = dup->libname;
- else if (idx == 1)
- dup_name = "runtime linker";
- else
- dup_name = "unknown library";
- _dl_dprintf(2, "%s: '%s' dsbt index %d already used by %s!\n",
- _dl_progname, libname, idx, dup_name);
- _dl_exit(1);
- }
- }
- t->loadaddr.map->dsbt_table[idx] = (unsigned)dsbt;
- }
- if (ref)
- _dl_memcpy(dsbt, ref->loadaddr.map->dsbt_table,
- tpnt->loadaddr.map->dsbt_size * sizeof(unsigned *));
+ for (t = _dl_loaded_modules; t; t = t->next)
+ t->dsbt_table[idx] = dsbt;
+ _dl_ldso_dsbt[idx] = dsbt;
+ _dl_memcpy(dsbt, _dl_ldso_dsbt,
+ tpnt->dsbt_size * sizeof(tpnt->dsbt_table[0]));
}
#endif
_dl_if_debug_dprint("\n\tfile='%s'; generating link map\n", libname);
relative_count = tpnt->dynamic_info[DT_RELCONT_IDX];
if (relative_count) { /* Optimize the XX_RELATIVE relocations if possible */
reloc_size -= relative_count * sizeof(ELF_RELOC);
- if (tpnt->loadaddr
#ifdef __LDSO_PRELINK_SUPPORT__
- || (!tpnt->dynamic_info[DT_GNU_PRELINKED_IDX])
+ if (tpnt->loadaddr || (!tpnt->dynamic_info[DT_GNU_PRELINKED_IDX]))
#endif
- )
elf_machine_relative(tpnt->loadaddr, reloc_addr, relative_count);
reloc_addr += relative_count * sizeof(ELF_RELOC);
}
return goof;
}
+#ifdef IS_IN_rtld
/* Minimal printf which handles only %s, %d, and %x */
void _dl_dprintf(int fd, const char *fmt, ...)
{
break;
}
case 'x':
- case 'X':
+ case 'p':
{
char tmp[22];
#if __WORDSIZE > 32
_dl_strcpy(retval, string);
return retval;
}
+#endif
unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
void *debug_addr, DL_LOADADDR_TYPE load_off)