diff options
| -rw-r--r-- | ldso/include/dl-defs.h | 22 | ||||
| -rw-r--r-- | ldso/ldso/c6x/dl-sysdep.h | 11 | ||||
| -rw-r--r-- | ldso/ldso/dl-elf.c | 27 | ||||
| -rw-r--r-- | ldso/ldso/dl-startup.c | 9 | ||||
| -rw-r--r-- | ldso/ldso/fdpic/dl-sysdep.h | 12 | ||||
| -rw-r--r-- | ldso/ldso/ldso.c | 17 | 
6 files changed, 78 insertions, 20 deletions
| diff --git a/ldso/include/dl-defs.h b/ldso/include/dl-defs.h index 11edc4dfc..f71ba9b48 100644 --- a/ldso/include/dl-defs.h +++ b/ldso/include/dl-defs.h @@ -259,4 +259,26 @@ typedef struct {  # define DL_MAP_SEGMENT(EPNT, PPNT, INFILE, FLAGS) 0  #endif +/* Define this to declare the library offset. */ +#ifndef DL_DEF_LIB_OFFSET +# define DL_DEF_LIB_OFFSET static unsigned long _dl_library_offset +#endif + +/* Define this to get the library offset. */ +#ifndef DL_GET_LIB_OFFSET +# define DL_GET_LIB_OFFSET() _dl_library_offset +#endif + +/* Define this to set the library offset  as difference beetwen the mapped +   library address and the smallest virtual address of the first PT_LOAD +   segment. */ +#ifndef DL_SET_LIB_OFFSET +# define DL_SET_LIB_OFFSET(offset) (_dl_library_offset = (offset)) +#endif + +/* Define this to get the real object's runtime address. */ +#ifndef DL_GET_RUN_ADDR +# define DL_GET_RUN_ADDR(loadaddr, mapaddr) (mapaddr) +#endif +  #endif	/* _LD_DEFS_H */ diff --git a/ldso/ldso/c6x/dl-sysdep.h b/ldso/ldso/c6x/dl-sysdep.h index ff7accdf1..0dbe8bf90 100644 --- a/ldso/ldso/c6x/dl-sysdep.h +++ b/ldso/ldso/c6x/dl-sysdep.h @@ -166,6 +166,17 @@ while (0)  #define DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr) \    ((dpnt) = dl_boot_ldso_dyn_pointer) +/* Define this to declare the library offset. */ +#define DL_DEF_LIB_OFFSET + +/* Define this to get the library offset. */ +#define DL_GET_LIB_OFFSET() 0 + +/* Define this to set the library offset. */ +#define DL_SET_LIB_OFFSET(offset) + +/* Define this to get the real object's runtime address. */ +#define DL_GET_RUN_ADDR(loadaddr, mapaddr) (loadaddr)  #ifdef __USE_GNU  # include <link.h> diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index b9de19910..9e2a12ce7 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -315,6 +315,9 @@ goof:  	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. @@ -357,7 +360,7 @@ map_writeable (int infile, ElfW(Phdr) *ppnt, int piclib, int flags,  	}  	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; @@ -459,7 +462,7 @@ struct elf_resolve *_dl_load_elf_shared_library(unsigned rflags,  	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; @@ -617,6 +620,8 @@ struct elf_resolve *_dl_load_elf_shared_library(unsigned rflags,  	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)) { @@ -648,7 +653,7 @@ struct elf_resolve *_dl_load_elf_shared_library(unsigned rflags,  			} 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), @@ -675,7 +680,11 @@ struct elf_resolve *_dl_load_elf_shared_library(unsigned rflags,  	 * 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);  	} @@ -708,7 +717,7 @@ struct elf_resolve *_dl_load_elf_shared_library(unsigned rflags,  		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); @@ -746,7 +755,9 @@ struct elf_resolve *_dl_load_elf_shared_library(unsigned rflags,  	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__ @@ -954,11 +965,9 @@ int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int now_flag)  		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);  		} diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c index 75ea564c2..4893409e9 100644 --- a/ldso/ldso/dl-startup.c +++ b/ldso/ldso/dl-startup.c @@ -203,7 +203,8 @@ DL_START(unsigned long args)  		_dl_exit(0);  	}  	SEND_EARLY_STDERR_DEBUG("ELF header="); -	SEND_ADDRESS_STDERR_DEBUG(DL_LOADADDR_BASE(header), 1); +	SEND_ADDRESS_STDERR_DEBUG( +		DL_LOADADDR_BASE(DL_GET_RUN_ADDR(load_addr, header)), 1);  	/* Locate the global offset table.  Since this code must be PIC  	 * we can take advantage of the magic offset register, if we @@ -278,11 +279,9 @@ DL_START(unsigned long args)  			if (!indx && relative_count) {  				rel_size -= relative_count * sizeof(ELF_RELOC); -				if (load_addr  #ifdef __LDSO_PRELINK_SUPPORT__ -					|| !tpnt->dynamic_info[DT_GNU_PRELINKED_IDX] +				if (load_addr || !tpnt->dynamic_info[DT_GNU_PRELINKED_IDX])  #endif -					)  					elf_machine_relative(load_addr, rel_addr, relative_count);  				rel_addr += relative_count * sizeof(ELF_RELOC);  			} @@ -347,7 +346,7 @@ DL_START(unsigned long args)  	__rtld_stack_end = (void *)(argv - 1);  	_dl_elf_main = (int (*)(int, char **, char **)) -			_dl_get_ready_to_run(tpnt, (DL_LOADADDR_TYPE) header, auxvt, envp, argv +			_dl_get_ready_to_run(tpnt, load_addr, auxvt, envp, argv  					     DL_GET_READY_TO_RUN_EXTRA_ARGS);  	/* Transfer control to the application.  */ diff --git a/ldso/ldso/fdpic/dl-sysdep.h b/ldso/ldso/fdpic/dl-sysdep.h index 75d7951ac..546811ad0 100644 --- a/ldso/ldso/fdpic/dl-sysdep.h +++ b/ldso/ldso/fdpic/dl-sysdep.h @@ -115,6 +115,18 @@ struct funcdesc_ht;  #define DL_GET_READY_TO_RUN_EXTRA_ARGS \      , dl_boot_progmap, dl_boot_got_pointer +/* Define this to declare the library offset. */ +#define DL_DEF_LIB_OFFSET + +/* Define this to get the library offset. */ +#define DL_GET_LIB_OFFSET() 0 + +/* Define this to set the library offset. */ +#define DL_SET_LIB_OFFSET(offset) + +/* Define this to get the real object's runtime address. */ +#define DL_GET_RUN_ADDR(loadaddr, mapaddr) (loadaddr) +  #ifdef __USE_GNU  # include <link.h>  #else diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 014bbf5a9..85d27a3d1 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -351,12 +351,14 @@ static void trace_objects(struct elf_resolve *tpnt, char *str_name)  static struct elf_resolve * add_ldso(struct elf_resolve *tpnt,  									 DL_LOADADDR_TYPE load_addr, +									 ElfW(Addr) ldso_mapaddr,  									 ElfW(auxv_t) auxvt[AT_EGID + 1],  									 struct dyn_elf *rpnt)  {  		ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;  		ElfW(Phdr) *myppnt = (ElfW(Phdr) *) -								DL_RELOC_ADDR(load_addr, epnt->e_phoff); +				DL_RELOC_ADDR(DL_GET_RUN_ADDR(load_addr, ldso_mapaddr), +							  epnt->e_phoff);  		int j;  		struct stat st; @@ -364,7 +366,7 @@ static struct elf_resolve * add_ldso(struct elf_resolve *tpnt,  					      tpnt->dynamic_info, (unsigned long)tpnt->dynamic_addr,  					      0); -		tpnt->mapaddr = load_addr; +		tpnt->mapaddr = ldso_mapaddr;  		if (_dl_stat(tpnt->libname, &st) >= 0) {  			tpnt->st_dev = st.st_dev;  			tpnt->st_ino = st.st_ino; @@ -411,7 +413,7 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,  			  ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv  			  DL_GET_READY_TO_RUN_EXTRA_PARMS)  { -	ElfW(Addr) app_mapaddr = 0; +	ElfW(Addr) app_mapaddr = 0, ldso_mapaddr = 0;  	ElfW(Phdr) *ppnt;  	ElfW(Dyn) *dpnt;  	char *lpntstr; @@ -826,6 +828,7 @@ of this helper program; chances are you did not intend to run this program.\n\  	}  #endif +	ldso_mapaddr = (ElfW(Addr)) auxvt[AT_BASE].a_un.a_val;  	/*  	 * OK, fix one more thing - set up debug_addr so it will point  	 * to our chain.  Later we may need to fill in more fields, but this @@ -833,7 +836,8 @@ of this helper program; chances are you did not intend to run this program.\n\  	 */  	debug_addr->r_map = (struct link_map *) _dl_loaded_modules;  	debug_addr->r_version = 1; -	debug_addr->r_ldbase = (ElfW(Addr)) DL_LOADADDR_BASE(load_addr); +	debug_addr->r_ldbase = (ElfW(Addr)) +		DL_LOADADDR_BASE(DL_GET_RUN_ADDR(load_addr, ldso_mapaddr));  	debug_addr->r_brk = (unsigned long) &_dl_debug_state;  	_dl_debug_addr = debug_addr; @@ -1012,7 +1016,8 @@ of this helper program; chances are you did not intend to run this program.\n\  				if (_dl_strcmp(name, UCLIBC_LDSO) == 0) {  						if (!ldso_tpnt) {  							/* Insert the ld.so only once */ -							ldso_tpnt = add_ldso(tpnt, load_addr, auxvt, rpnt); +							ldso_tpnt = add_ldso(tpnt, load_addr, +												 ldso_mapaddr, auxvt, rpnt);  						}  						ldso_tpnt->usage_count++;  						tpnt1 = ldso_tpnt; @@ -1112,7 +1117,7 @@ of this helper program; chances are you did not intend to run this program.\n\  	 * again once all libs are loaded.  	 */  	if (!ldso_tpnt) { -		tpnt = add_ldso(tpnt, load_addr, auxvt, rpnt); +		tpnt = add_ldso(tpnt, load_addr, ldso_mapaddr, auxvt, rpnt);  		tpnt->usage_count++;  		nscope_elem++;  	} else | 
