From b9766aa08c90b6718d5497d6a6cf9e6f737e5141 Mon Sep 17 00:00:00 2001 From: Filippo Arcidiacono Date: Thu, 26 Aug 2010 12:00:03 +0200 Subject: ldso: Fix loadaddr and mappaddr when prelink support is enabled. Fixed loadaddr and mappaddr fields to correctly work when prelink support is enabled. - loadaddr is an offset relative to the first loadable segment. - mapaddr is the address where the object has been mapped in memory. Non PIC library detection fixed too. Signed-off-by: Filippo Arcidiacono Signed-off-by: Carmelo Amoroso --- ldso/ldso/dl-elf.c | 34 +++++++++++++--------------------- ldso/ldso/dl-hash.c | 5 ----- ldso/ldso/ldso.c | 4 +--- 3 files changed, 14 insertions(+), 29 deletions(-) (limited to 'ldso') diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index 9625f5ae5..d72dd5ae2 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -430,7 +430,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, if (ppnt->p_type == PT_LOAD) { /* See if this is a PIC library. */ - if (i == 0 && ppnt->p_vaddr > 0x1000000) { + if (minvma == 0xffffffff && ppnt->p_vaddr > 0x1000000) { piclib = 0; minvma = ppnt->p_vaddr; } @@ -477,8 +477,6 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, minvma = minvma & ~0xffffU; flags = MAP_PRIVATE /*| MAP_DENYWRITE */ ; - if (!piclib) - flags |= MAP_FIXED; if (piclib == 0 || piclib == 1) { status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma), @@ -497,7 +495,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, /* Get the memory to store the library */ ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; - DL_INIT_LOADADDR(lib_loadaddr, libaddr, ppnt, epnt->e_phnum); + DL_INIT_LOADADDR(lib_loadaddr, libaddr - minvma, ppnt, epnt->e_phnum); for (i = 0; i < epnt->e_phnum; i++) { if (DL_IS_SPECIAL_SEGMENT (epnt, ppnt)) { @@ -519,12 +517,6 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, char *tryaddr; ssize_t size; - /* See if this is a PIC library. */ - if (i == 0 && ppnt->p_vaddr > 0x1000000) { - piclib = 0; - /* flags |= MAP_FIXED; */ - } - if (ppnt->p_flags & PF_W) { unsigned long map_size; char *cpnt; @@ -568,7 +560,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, } tryaddr = piclib == 2 ? piclib2map - : ((char*) (piclib ? libaddr : 0) + + : ((char*) (piclib ? libaddr : lib_loadaddr) + (ppnt->p_vaddr & PAGE_ALIGN)); size = (ppnt->p_vaddr & ADDR_ALIGN) @@ -653,7 +645,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, if (map_size < ppnt->p_vaddr + ppnt->p_memsz && !piclib2map) { - tryaddr = map_size + (char*)(piclib ? libaddr : 0); + tryaddr = map_size + (char*)(piclib ? libaddr : lib_loadaddr); status = (char *) _dl_mmap(tryaddr, ppnt->p_vaddr + ppnt->p_memsz - map_size, LXFLAGS(ppnt->p_flags), flags | MAP_ANONYMOUS | MAP_FIXED, -1, 0); @@ -664,7 +656,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, } else { tryaddr = (piclib == 2 ? 0 : (char *) (ppnt->p_vaddr & PAGE_ALIGN) - + (piclib ? libaddr : 0)); + + (piclib ? libaddr : lib_loadaddr)); size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz; status = (char *) _dl_mmap (tryaddr, size, LXFLAGS(ppnt->p_flags), @@ -688,8 +680,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, } _dl_close(infile); - /* For a non-PIC library, the addresses are all absolute */ - if (piclib) { + /* + * 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) { dynamic_addr = (unsigned long) DL_RELOC_ADDR(lib_loadaddr, dynamic_addr); } @@ -710,11 +705,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, dpnt = (ElfW(Dyn) *) dynamic_addr; _dl_memset(dynamic_info, 0, sizeof(dynamic_info)); -#ifdef __LDSO_STANDALONE_SUPPORT__ - rtld_flags = _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, piclib ? lib_loadaddr : 0); -#else rtld_flags = _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, lib_loadaddr); -#endif /* If the TEXTREL is set, this means that we need to make the pages writable before we perform relocations. Do this now. They get set back again later. */ @@ -724,7 +715,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; for (i = 0; i < epnt->e_phnum; i++, ppnt++) { if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) { - _dl_mprotect((void *) ((piclib ? libaddr : 0) + + _dl_mprotect((void *) ((piclib ? libaddr : lib_loadaddr) + (ppnt->p_vaddr & PAGE_ALIGN)), (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz, PROT_READ | PROT_WRITE | PROT_EXEC); @@ -740,11 +731,12 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure, tpnt = _dl_add_elf_hash_table(libname, lib_loadaddr, dynamic_info, dynamic_addr, 0); + tpnt->mapaddr = libaddr; tpnt->relro_addr = relro_addr; 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->loadaddr, epnt->e_phoff); + tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(tpnt->mapaddr, epnt->e_phoff); tpnt->n_phent = epnt->e_phnum; tpnt->rtld_flags |= rtld_flags; #ifdef __LDSO_STANDALONE_SUPPORT__ diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c index f0683c60f..bb4c56b04 100644 --- a/ldso/ldso/dl-hash.c +++ b/ldso/ldso/dl-hash.c @@ -145,12 +145,7 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname, hash_addr += tpnt->nbucket; tpnt->chains = hash_addr; } -#ifdef __LDSO_PRELINK_SUPPORT__ - tpnt->loadaddr = dynamic_info[DT_GNU_PRELINKED_IDX] ? 0 : loadaddr; -#else tpnt->loadaddr = loadaddr; -#endif - tpnt->mapaddr = DL_RELOC_ADDR(loadaddr, 0); for (i = 0; i < DYNAMIC_SIZE; i++) tpnt->dynamic_info[i] = dynamic_info[i]; return tpnt; diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index b056f8af2..e0d323a9f 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -329,6 +329,7 @@ static struct elf_resolve * add_ldso(struct elf_resolve *tpnt, tpnt->dynamic_info, (unsigned long)tpnt->dynamic_addr, 0); + tpnt->mapaddr = load_addr; if (_dl_stat(tpnt->libname, &st) >= 0) { tpnt->st_dev = st.st_dev; tpnt->st_ino = st.st_ino; @@ -551,9 +552,6 @@ of this helper program; chances are you did not intend to run this program.\n\ 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. -- cgit v1.2.3