Parcourir la source

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 <filippo.arcidiacono@st.com>
Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
Filippo Arcidiacono il y a 15 ans
Parent
commit
b9766aa08c
3 fichiers modifiés avec 14 ajouts et 29 suppressions
  1. 13 21
      ldso/ldso/dl-elf.c
  2. 0 5
      ldso/ldso/dl-hash.c
  3. 1 3
      ldso/ldso/ldso.c

+ 13 - 21
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) {
 		if (ppnt->p_type == PT_LOAD) {
 			/* See if this is a PIC library. */
 			/* See if this is a PIC library. */
-			if (i == 0 && ppnt->p_vaddr > 0x1000000) {
+			if (minvma == 0xffffffff && ppnt->p_vaddr > 0x1000000) {
 				piclib = 0;
 				piclib = 0;
 				minvma = ppnt->p_vaddr;
 				minvma = ppnt->p_vaddr;
 			}
 			}
@@ -477,8 +477,6 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	minvma = minvma & ~0xffffU;
 	minvma = minvma & ~0xffffU;
 
 
 	flags = MAP_PRIVATE /*| MAP_DENYWRITE */ ;
 	flags = MAP_PRIVATE /*| MAP_DENYWRITE */ ;
-	if (!piclib)
-		flags |= MAP_FIXED;
 
 
 	if (piclib == 0 || piclib == 1) {
 	if (piclib == 0 || piclib == 1) {
 		status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma),
 		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 */
 	/* Get the memory to store the library */
 	ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
 	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++) {
 	for (i = 0; i < epnt->e_phnum; i++) {
 		if (DL_IS_SPECIAL_SEGMENT (epnt, ppnt)) {
 		if (DL_IS_SPECIAL_SEGMENT (epnt, ppnt)) {
@@ -519,12 +517,6 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 			char *tryaddr;
 			char *tryaddr;
 			ssize_t size;
 			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) {
 			if (ppnt->p_flags & PF_W) {
 				unsigned long map_size;
 				unsigned long map_size;
 				char *cpnt;
 				char *cpnt;
@@ -568,7 +560,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 				  }
 				  }
 
 
 				tryaddr = piclib == 2 ? piclib2map
 				tryaddr = piclib == 2 ? piclib2map
-				  : ((char*) (piclib ? libaddr : 0) +
+				  : ((char*) (piclib ? libaddr : lib_loadaddr) +
 				     (ppnt->p_vaddr & PAGE_ALIGN));
 				     (ppnt->p_vaddr & PAGE_ALIGN));
 
 
 				size = (ppnt->p_vaddr & ADDR_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
 				if (map_size < ppnt->p_vaddr + ppnt->p_memsz
 				    && !piclib2map) {
 				    && !piclib2map) {
-					tryaddr = map_size + (char*)(piclib ? libaddr : 0);
+					tryaddr = map_size + (char*)(piclib ? libaddr : lib_loadaddr);
 					status = (char *) _dl_mmap(tryaddr,
 					status = (char *) _dl_mmap(tryaddr,
 						ppnt->p_vaddr + ppnt->p_memsz - map_size,
 						ppnt->p_vaddr + ppnt->p_memsz - map_size,
 						LXFLAGS(ppnt->p_flags), flags | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
 						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 {
 			} else {
 				tryaddr = (piclib == 2 ? 0
 				tryaddr = (piclib == 2 ? 0
 					   : (char *) (ppnt->p_vaddr & PAGE_ALIGN)
 					   : (char *) (ppnt->p_vaddr & PAGE_ALIGN)
-					   + (piclib ? libaddr : 0));
+					   + (piclib ? libaddr : lib_loadaddr));
 				size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
 				size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz;
 				status = (char *) _dl_mmap
 				status = (char *) _dl_mmap
 					   (tryaddr, size, LXFLAGS(ppnt->p_flags),
 					   (tryaddr, size, LXFLAGS(ppnt->p_flags),
@@ -688,8 +680,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 	}
 	}
 	_dl_close(infile);
 	_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);
 		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;
 	dpnt = (ElfW(Dyn) *) dynamic_addr;
 	_dl_memset(dynamic_info, 0, sizeof(dynamic_info));
 	_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);
 	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
 	/* 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
 	   writable before we perform relocations.  Do this now. They get set
 	   back again later. */
 	   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];
 		ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
 		for (i = 0; i < epnt->e_phnum; i++, ppnt++) {
 		for (i = 0; i < epnt->e_phnum; i++, ppnt++) {
 			if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) {
 			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 & PAGE_ALIGN)),
 						(ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz,
 						(ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz,
 						PROT_READ | PROT_WRITE | PROT_EXEC);
 						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,
 	tpnt = _dl_add_elf_hash_table(libname, lib_loadaddr, dynamic_info,
 			dynamic_addr, 0);
 			dynamic_addr, 0);
+	tpnt->mapaddr = libaddr;
 	tpnt->relro_addr = relro_addr;
 	tpnt->relro_addr = relro_addr;
 	tpnt->relro_size = relro_size;
 	tpnt->relro_size = relro_size;
 	tpnt->st_dev = st.st_dev;
 	tpnt->st_dev = st.st_dev;
 	tpnt->st_ino = st.st_ino;
 	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->n_phent = epnt->e_phnum;
 	tpnt->rtld_flags |= rtld_flags;
 	tpnt->rtld_flags |= rtld_flags;
 #ifdef __LDSO_STANDALONE_SUPPORT__
 #ifdef __LDSO_STANDALONE_SUPPORT__

+ 0 - 5
ldso/ldso/dl-hash.c

@@ -145,12 +145,7 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
 		hash_addr += tpnt->nbucket;
 		hash_addr += tpnt->nbucket;
 		tpnt->chains = hash_addr;
 		tpnt->chains = hash_addr;
 	}
 	}
-#ifdef __LDSO_PRELINK_SUPPORT__
-	tpnt->loadaddr = dynamic_info[DT_GNU_PRELINKED_IDX] ? 0 : loadaddr;
-#else
 	tpnt->loadaddr = loadaddr;
 	tpnt->loadaddr = loadaddr;
-#endif
-	tpnt->mapaddr = DL_RELOC_ADDR(loadaddr, 0);
 	for (i = 0; i < DYNAMIC_SIZE; i++)
 	for (i = 0; i < DYNAMIC_SIZE; i++)
 		tpnt->dynamic_info[i] = dynamic_info[i];
 		tpnt->dynamic_info[i] = dynamic_info[i];
 	return tpnt;
 	return tpnt;

+ 1 - 3
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,
 					      tpnt->dynamic_info, (unsigned long)tpnt->dynamic_addr,
 					      0);
 					      0);
 
 
+		tpnt->mapaddr = load_addr;
 		if (_dl_stat(tpnt->libname, &st) >= 0) {
 		if (_dl_stat(tpnt->libname, &st) >= 0) {
 			tpnt->st_dev = st.st_dev;
 			tpnt->st_dev = st.st_dev;
 			tpnt->st_ino = st.st_ino;
 			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;
 		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
 		 * This is used by gdb to locate the chain of shared libraries that are
 		 * currently loaded.
 		 * currently loaded.