[PATCH] ldso: Fix loadaddr and mappaddr when prelink support is enabled.

Carmelo AMOROSO carmelo.amoroso at st.com
Mon Sep 20 08:35:58 UTC 2010


From: Filippo Arcidiacono <filippo.arcidiacono at st.com>

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 <filippo.arcidiacono at st.com>
Signed-off-by: Carmelo Amoroso <carmelo.amoroso at st.com>
---
 ldso/ldso/dl-elf.c  |   34 +++++++++++++---------------------
 ldso/ldso/dl-hash.c |    5 -----
 ldso/ldso/ldso.c    |    4 +---
 3 files changed, 14 insertions(+), 29 deletions(-)

diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
index 9625f5a..d72dd5a 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 f0683c6..bb4c56b 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 b056f8a..e0d323a 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.
-- 
1.5.5.6



More information about the uClibc mailing list