diff options
Diffstat (limited to 'trunk/src/rtld/dl-load.c')
-rw-r--r-- | trunk/src/rtld/dl-load.c | 60 |
1 files changed, 53 insertions, 7 deletions
diff --git a/trunk/src/rtld/dl-load.c b/trunk/src/rtld/dl-load.c index f73f17f..5dc913e 100644 --- a/trunk/src/rtld/dl-load.c +++ b/trunk/src/rtld/dl-load.c @@ -80,6 +80,7 @@ add_name_to_object (struct link_map *l, const char *name) const char *rtld_progname; static Elf64_Addr load_addr = 0xdead0000; +static Elf64_Addr dynamic_addr = 0xfeed0000; /* mimic behavior of _dl_map_object_from_fd(...) Note: this is not a copy of the function! */ @@ -104,8 +105,9 @@ create_map_object_from_dso_ent (struct dso_list *cur_dso_ent) /* Print debug message. */ - if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) - printf("\tfile=%s; generating link map\n", name); + if ((l_type == lt_library && !is_ldso_soname(soname)) && + __glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES)) + _dl_debug_printf("file=%s [0]; generating link map\n", soname); l = _dl_new_object (realname, name, l_type); @@ -207,14 +209,58 @@ create_map_object_from_dso_ent (struct dso_list *cur_dso_ent) } } - /* Set up the symbol hash table. */ - _dl_setup_hash (l); - - l->l_map_start = load_addr; - load_addr += 0x1000; + if (dso->base) { + l->l_map_start = dso->base; + + /* We need to ensure that we don't have two DSOs loading at the same place! */ + struct dso_list * dso_list_ptr; + for (dso_list_ptr = cur_dso_ent->prev; dso_list_ptr; dso_list_ptr = dso_list_ptr->prev) + { + /* This looks for fairly obvious overlaps... */ + if ((dso_list_ptr->dso->base <= dso->base && dso->base <= dso_list_ptr->dso->end) || \ + (dso->base <= dso_list_ptr->dso->base && dso_list_ptr->dso->base <= dso->end)) + { + l->l_map_start = (Elf64_Addr)NULL; + break; + } + } + } + + if (l->l_map_start == (Elf64_Addr)NULL) + { + l->l_map_start = load_addr; + load_addr += ( ((dso->end - dso->base) + (0x1000 - 1)) & (~(0x1000-1)) ); + } l->sym_base = dso->info[DT_SYMTAB] - dso->base; + if ((l_type == lt_library && !is_ldso_soname(soname)) + && (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))) { + _dl_debug_printf ("\ + dynamic: 0x%0*lx base: 0x%0*lx size: 0x%0*Zx\n", + (int) sizeof (void *) * (gelf_getclass (dso->elf) == ELFCLASS64 ? 2 : 1), + (unsigned long int) dynamic_addr, + (int) sizeof (void *) * (gelf_getclass (dso->elf) == ELFCLASS64 ? 2 : 1), + (unsigned long int) l->l_map_start, + (int) sizeof (void *) * (gelf_getclass (dso->elf) == ELFCLASS64 ? 2 : 1), + (dso->end - dso->base)); + _dl_debug_printf ("\ + entry: 0x%0*lx phdr: 0x%0*lx phnum: %*u\n", + (int) sizeof (void *) * (gelf_getclass (dso->elf) == ELFCLASS64 ? 2 : 1), + (unsigned long int) l->l_map_start + dso->ehdr.e_entry, + (int) sizeof (void *) * (gelf_getclass (dso->elf) == ELFCLASS64 ? 2 : 1), + (unsigned long int) l->l_map_start + dso->ehdr.e_ehsize, + (int) sizeof (void *) * (gelf_getclass (dso->elf) == ELFCLASS64 ? 2 : 1), + dso->ehdr.e_phnum); + _dl_debug_printf ("\n"); + + /* Only used for debugging output */ + dynamic_addr += ( ((dso->end - dso->base) + (0x1000 - 1)) & (~(0x1000-1)) ); + } + + /* Set up the symbol hash table. */ + _dl_setup_hash (l); + for (i = 0; i < dso->ehdr.e_phnum; ++i) if (dso->phdr[i].p_type == PT_TLS) { |