diff options
| author | Mike Frysinger <vapier@gentoo.org> | 2006-06-30 02:55:57 +0000 | 
|---|---|---|
| committer | Mike Frysinger <vapier@gentoo.org> | 2006-06-30 02:55:57 +0000 | 
| commit | 1ba3a7b727b49d61b4868a06f1258a54db4dc9e0 (patch) | |
| tree | 3958d8fe8647427ecaacf38922a128d8d5c51c1a | |
| parent | 1d6903684a1f73d72fb913c62491693f35f02d62 (diff) | |
Bernd Schmidt writes: abstract away addresses so we can support FDPIC ELFs
| -rw-r--r-- | ldso/include/dl-defs.h | 66 | ||||
| -rw-r--r-- | ldso/include/dl-elf.h | 9 | ||||
| -rw-r--r-- | ldso/include/dl-hash.h | 4 | ||||
| -rw-r--r-- | ldso/include/ldso.h | 2 | ||||
| -rw-r--r-- | ldso/ldso/dl-elf.c | 38 | ||||
| -rw-r--r-- | ldso/ldso/dl-hash.c | 16 | ||||
| -rw-r--r-- | ldso/ldso/dl-startup.c | 15 | ||||
| -rw-r--r-- | ldso/ldso/ldso.c | 73 | ||||
| -rw-r--r-- | ldso/libdl/libdl.c | 22 | 
9 files changed, 167 insertions, 78 deletions
| diff --git a/ldso/include/dl-defs.h b/ldso/include/dl-defs.h index 878ebc3b8..dc6531d19 100644 --- a/ldso/include/dl-defs.h +++ b/ldso/include/dl-defs.h @@ -66,4 +66,70 @@ typedef struct {  #endif +/* Machines in which different sections may be relocated by different +   amounts should define this and LD_RELOC_ADDR.  If you change this, +   make sure you change struct link_map in include/link.h accordingly +   such that it matches a prefix of struct elf_resolve.  */ +#ifndef DL_LOADADDR_TYPE +# define DL_LOADADDR_TYPE ElfW(Addr) +#endif + +/* When DL_LOADADDR_TYPE is not a scalar value, or some different +   computation is needed to relocate an address, define this.  */ +#ifndef DL_RELOC_ADDR +# define DL_RELOC_ADDR(ADDR, LOADADDR) \ +  ((void*)((intptr_t)(ADDR) + (intptr_t)(LOADADDR))) +#endif + +/* Define if any declarations/definitions of local variables are +   needed in a function that calls DT_INIT_LOADADDR or +   DL_INIT_LOADADDR_HDR.  Declarations must be properly terminated +   with a semicolon, and non-declaration statements are forbidden.  */ +#ifndef DL_INIT_LOADADDR_EXTRA_DECLS +# define DL_INIT_LOADADDR_EXTRA_DECLS /* int i; */ +#endif + +/* Prepare a DL_LOADADDR_TYPE data structure for incremental +   initialization with DL_INIT_LOADADDR_HDR, given pointers to a base +   load address and to program headers.  */ +#ifndef DL_INIT_LOADADDR +# define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \ +  ((LOADADDR) = (BASEADDR)) +#endif + +/* Convert a DL_LOADADDR_TYPE to an identifying pointer.  Used mostly +   for debugging.  */ +#ifndef DL_LOADADDR_BASE +# define DL_LOADADDR_BASE(LOADADDR) (LOADADDR) +#endif + +/* Initialize a LOADADDR representing the loader itself.  It's only +   called from DL_BOOT, so additional arguments passed to it may be +   referenced.  */ +#ifndef DL_INIT_LOADADDR_BOOT +# define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \ +  ((LOADADDR) = (BASEADDR)) +#endif + +/* Initialize a LOADADDR representing the program.  It's called from +   DL_BOOT only.  */ +#ifndef DL_INIT_LOADADDR_PROG +# define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \ +  ((LOADADDR) = (BASEADDR)) +#endif + +/* Test whether a given ADDR is more likely to be within the memory +   region mapped to TPNT (a struct elf_resolve *) than to TFROM. +   Everywhere that this is used, TFROM is initially NULL, and whenever +   a potential match is found, it's updated.  One might want to walk +   the chain of elf_resolve to locate the best match and return false +   whenever TFROM is non-NULL, or use an exact-matching algorithm +   using additional information encoded in DL_LOADADDR_TYPE to test +   for exact containment.  */ +#ifndef DL_ADDR_IN_LOADADDR +# define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \ +  ((void*)(TPNT)->loadaddr < (void*)(ADDR)			\ +   && (! (TFROM) || (TFROM)->loadaddr < (TPNT)->loadaddr)) +#endif +  #endif	/* _LD_DEFS_H */ diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h index de404aec1..9e364d680 100644 --- a/ldso/include/dl-elf.h +++ b/ldso/include/dl-elf.h @@ -94,10 +94,12 @@ extern void _dl_protect_relro (struct elf_resolve *l);  #define DYNAMIC_SIZE (DT_NUM+OS_NUM+ARCH_NUM) -extern void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, ElfW(Addr) load_off); +extern void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, +				   DL_LOADADDR_TYPE load_off);  static __always_inline -void __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, ElfW(Addr) load_off) +void __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, +			     DL_LOADADDR_TYPE load_off)  {  	for (; dpnt->d_tag; dpnt++) {  		if (dpnt->d_tag < DT_NUM) { @@ -139,7 +141,8 @@ void __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void  #define ADJUST_DYN_INFO(tag, load_off) \  	do { \  		if (dynamic_info[tag]) \ -			dynamic_info[tag] += load_off; \ +			dynamic_info[tag] = (unsigned long)DL_RELOC_ADDR (dynamic_info[tag], \ +									  load_off); \  	} while(0)  	ADJUST_DYN_INFO(DT_HASH, load_off);  	ADJUST_DYN_INFO(DT_PLTGOT, load_off); diff --git a/ldso/include/dl-hash.h b/ldso/include/dl-hash.h index b12b36f3b..26fb334fe 100644 --- a/ldso/include/dl-hash.h +++ b/ldso/include/dl-hash.h @@ -28,7 +28,7 @@ struct dyn_elf{  struct elf_resolve{    /* These entries must be in this order to be compatible with the interface used       by gdb to obtain the list of symbols. */ -  ElfW(Addr) loadaddr;		/* Base address shared object is loaded at.  */ +  DL_LOADADDR_TYPE loadaddr;	/* Base address shared object is loaded at.  */    char *libname;		/* Absolute file name object was found in.  */    ElfW(Dyn) *dynamic_addr;	/* Dynamic section of the shared object.  */    struct elf_resolve * next; @@ -77,7 +77,7 @@ extern struct elf_resolve * _dl_loaded_modules;  extern struct dyn_elf 	  * _dl_handles;  extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname,  -	char * loadaddr, unsigned long * dynamic_info,  +	DL_LOADADDR_TYPE loadaddr, unsigned long * dynamic_info,   	unsigned long dynamic_addr, unsigned long dynamic_size);  extern char * _dl_find_hash(const char * name, struct dyn_elf * rpnt1,  diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h index 0a3f70691..573652e61 100644 --- a/ldso/include/ldso.h +++ b/ldso/include/ldso.h @@ -88,7 +88,7 @@ extern void _dl_unsetenv(const char *symbol, char **envp);  extern char *_dl_strdup(const char *string);  extern void _dl_dprintf(int, const char *, ...); -extern void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, +extern 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);  #endif /* _LDSO_H_ */ diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index d0ea4dac7..f98d76b88 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -118,10 +118,10 @@ int _dl_unmap_cache(void)  void  _dl_protect_relro (struct elf_resolve *l)  { -	ElfW(Addr) start = ((l->loadaddr + l->relro_addr) -			    & ~(_dl_pagesize - 1)); -	ElfW(Addr) end = ((l->loadaddr + l->relro_addr + l->relro_size) -			  & ~(_dl_pagesize - 1)); +	ElfW(Addr) base = (ElfW(Addr)) DL_RELOC_ADDR (l->relro_addr, +						      l->loadaddr); +	ElfW(Addr) start = (base & ~(_dl_pagesize - 1)); +	ElfW(Addr) end = ((base + l->relro_size) & ~(_dl_pagesize - 1));  	_dl_if_debug_dprint("RELRO protecting %s:  start:%x, end:%x\n", l->libname, start, end);  	if (start != end &&  	    _dl_mprotect ((void *) start, end - start, PROT_READ) < 0) { @@ -262,7 +262,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,  #ifdef __LDSO_RUNPATH__  	pnt = (tpnt ? (char *)tpnt->dynamic_info[DT_RUNPATH] : NULL);  	if (pnt) { -		pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB]; +		pnt += (intptr_t) DL_RELOC_ADDR (tpnt->dynamic_info[DT_STRTAB], +						 tpnt->loadaddr);  		_dl_if_debug_dprint("\tsearching RUNPATH='%s'\n", pnt);  		if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL)  			return tpnt1; @@ -352,6 +353,8 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  	ElfW(Addr) relro_addr = 0;  	size_t relro_size = 0;  	struct stat st; +	DL_LOADADDR_TYPE lib_loadaddr; +	DL_INIT_LOADADDR_EXTRA_DECLS  	libaddr = 0;  	infile = _dl_open(libname, O_RDONLY, 0); @@ -467,7 +470,10 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  	}  	libaddr = (unsigned long) status;  	flags |= MAP_FIXED; - +	DL_INIT_LOADADDR (lib_loadaddr, libaddr, +			  (Elf32_Phdr *)& header[epnt->e_phoff], +			  epnt->e_phnum); +	  	/* Get the memory to store the library */  	ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; @@ -547,7 +553,8 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  	/* For a non-PIC library, the addresses are all absolute */  	if (piclib) { -		dynamic_addr += (unsigned long) libaddr; +		dynamic_addr = (unsigned long) DL_RELOC_ADDR (dynamic_addr, +							      lib_loadaddr);  	}  	/* @@ -567,7 +574,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  	dpnt = (ElfW(Dyn) *) dynamic_addr;  	_dl_memset(dynamic_info, 0, sizeof(dynamic_info)); -	_dl_parse_dynamic_info(dpnt, dynamic_info, NULL, libaddr); +	_dl_parse_dynamic_info(dpnt, dynamic_info, NULL, lib_loadaddr);  	/* 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. */ @@ -588,13 +595,14 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  #endif  	} -	tpnt = _dl_add_elf_hash_table(libname, (char *) libaddr, dynamic_info, +	tpnt = _dl_add_elf_hash_table(libname, lib_loadaddr, dynamic_info,  			dynamic_addr, 0);  	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) *)(intptr_t) (tpnt->loadaddr + epnt->e_phoff); +	tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR (epnt->e_phoff, +						   tpnt->loadaddr);  	tpnt->n_phent = epnt->e_phnum;  	/* @@ -625,9 +633,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,  	}  	_dl_if_debug_dprint("\n\tfile='%s';  generating link map\n", libname); -	_dl_if_debug_dprint("\t\tdynamic: %x  base: %x\n", dynamic_addr, libaddr); +	_dl_if_debug_dprint("\t\tdynamic: %x  base: %x\n", dynamic_addr, +			    DL_LOADADDR_BASE (libaddr));  	_dl_if_debug_dprint("\t\t  entry: %x  phdr: %x  phnum: %x\n\n", -			epnt->e_entry + libaddr, tpnt->ppnt, tpnt->n_phent); +			    DL_RELOC_ADDR (epnt->e_entry, lib_loadaddr), +			    tpnt->ppnt, tpnt->n_phent);  	_dl_munmap(header, _dl_pagesize); @@ -801,7 +811,7 @@ char *_dl_strdup(const char *string)  	return retval;  } -void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, ElfW(Addr) load_off) +void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, DL_LOADADDR_TYPE load_off)  {  	__dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off);  } @@ -818,7 +828,7 @@ __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, size_t size, void  	int ret = 0;  	for (l = _dl_loaded_modules; l != NULL; l = l->next) { -		info.dlpi_addr = l->loadaddr; +		info.dlpi_addr = (ElfW(Addr))DL_LOADADDR_BASE (l->loadaddr);  		info.dlpi_name = l->libname;  		info.dlpi_phdr = l->ppnt;  		info.dlpi_phnum = l->n_phent; diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c index ed55031ed..85b2b403f 100644 --- a/ldso/ldso/dl-hash.c +++ b/ldso/ldso/dl-hash.c @@ -83,7 +83,7 @@ static inline Elf_Symndx _dl_elf_hash(const char *name)   * externals properly.   */  struct elf_resolve *_dl_add_elf_hash_table(const char *libname, -	char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr, +	DL_LOADADDR_TYPE loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr,  	attribute_unused unsigned long dynamic_size)  {  	Elf_Symndx *hash_addr; @@ -117,7 +117,7 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,  		hash_addr += tpnt->nbucket;  		tpnt->chains = hash_addr;  	} -	tpnt->loadaddr = (ElfW(Addr))loadaddr; +	tpnt->loadaddr = loadaddr;  	for (i = 0; i < DYNAMIC_SIZE; i++)  		tpnt->dynamic_info[i] = dynamic_info[i];  	return tpnt; @@ -163,8 +163,10 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *  		/* Avoid calling .urem here. */  		do_rem(hn, elf_hash_number, tpnt->nbucket); -		symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]); -		strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]); +		symtab = (ElfW(Sym) *) DL_RELOC_ADDR (tpnt->dynamic_info[DT_SYMTAB], +						      tpnt->loadaddr); +		strtab = (char *) DL_RELOC_ADDR (tpnt->dynamic_info[DT_STRTAB], +						 tpnt->loadaddr);  		for (si = tpnt->elf_buckets[hn]; si != STN_UNDEF; si = tpnt->chains[si]) {  			sym = &symtab[si]; @@ -184,11 +186,13 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *  /* Perhaps we should support old style weak symbol handling   * per what glibc does when you export LD_DYNAMIC_WEAK */  				if (!weak_result) -					weak_result = (char *)tpnt->loadaddr + sym->st_value; +					weak_result = (char *) DL_RELOC_ADDR (sym->st_value, +									      tpnt->loadaddr);  				break;  #endif  			case STB_GLOBAL: -				return (char*)tpnt->loadaddr + sym->st_value; +				return (char*) DL_RELOC_ADDR (sym->st_value, +							      tpnt->loadaddr);  			default:	/* Local symbols not handled here */  				break;  			} diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c index 96a736448..908ba7cb3 100644 --- a/ldso/ldso/dl-startup.c +++ b/ldso/ldso/dl-startup.c @@ -114,7 +114,7 @@ static void * __attribute_used__ _dl_start(unsigned long args)  {  	unsigned int argc;  	char **argv, **envp; -	unsigned long load_addr; +	DL_LOADADDR_TYPE load_addr;  	ElfW(Addr) got;  	unsigned long *aux_dat;  	ElfW(Ehdr) *header; @@ -168,7 +168,7 @@ static void * __attribute_used__ _dl_start(unsigned long args)  	 * (esp since SEND_STDERR() needs this on some platforms... */  	if (!auxvt[AT_BASE].a_un.a_val)  		auxvt[AT_BASE].a_un.a_val = elf_machine_load_address(); -	load_addr = auxvt[AT_BASE].a_un.a_val; +	DL_INIT_LOADADDR_BOOT(load_addr, auxvt[AT_BASE].a_un.a_val);  	header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;  	/* Check the ELF header to make sure everything looks ok.  */ @@ -186,14 +186,14 @@ static void * __attribute_used__ _dl_start(unsigned long args)  		_dl_exit(0);  	}  	SEND_STDERR_DEBUG("ELF header="); -	SEND_ADDRESS_STDERR_DEBUG(load_addr, 1); +	SEND_ADDRESS_STDERR_DEBUG(DL_LOADADDR_BASE (load_addr), 1);  	/* Locate the global offset table.  Since this code must be PIC  	 * we can take advantage of the magic offset register, if we  	 * happen to know what that is for this architecture.  If not,  	 * we can always read stuff out of the ELF file to find it... */  	got = elf_machine_dynamic(); -	dpnt = (ElfW(Dyn) *) (got + load_addr); +	dpnt = (ElfW(Dyn) *) DL_RELOC_ADDR (got, load_addr);  	SEND_STDERR_DEBUG("First Dynamic section entry=");  	SEND_ADDRESS_STDERR_DEBUG(dpnt, 1);  	_dl_memset(tpnt, 0, sizeof(struct elf_resolve)); @@ -259,9 +259,10 @@ static void * __attribute_used__ _dl_start(unsigned long args)  				rel_addr += relative_count * sizeof(ELF_RELOC);  			} -			rpnt = (ELF_RELOC *) (rel_addr + load_addr); +			rpnt = (ELF_RELOC *) DL_RELOC_ADDR (rel_addr, load_addr);  			for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) { -				reloc_addr = (unsigned long *) (load_addr + (unsigned long) rpnt->r_offset); +				reloc_addr = (unsigned long *) DL_RELOC_ADDR ((unsigned long) rpnt->r_offset, +									      load_addr);  				symtab_index = ELF_R_SYM(rpnt->r_info);  				symbol_addr = 0;  				sym = NULL; @@ -272,7 +273,7 @@ static void * __attribute_used__ _dl_start(unsigned long args)  					symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];  					strtab = (char *) tpnt->dynamic_info[DT_STRTAB];  					sym = &symtab[symtab_index]; -					symbol_addr = load_addr + sym->st_value; +					symbol_addr = (unsigned long) DL_RELOC_ADDR (sym->st_value, load_addr);  					SEND_STDERR_DEBUG("relocating symbol: ");  					SEND_STDERR_DEBUG(strtab + sym->st_name); diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 2234623e3..2afd97797 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -102,17 +102,18 @@ uintptr_t __guard attribute_relro;  #endif  static void _dl_run_array_forward(unsigned long array, unsigned long size, -				  ElfW(Addr) loadaddr) +				  DL_LOADADDR_TYPE loadaddr)  {  	if (array != 0) {  		unsigned int j;  		unsigned int jm;  		ElfW(Addr) *addrs;  		jm = size / sizeof (ElfW(Addr)); -		addrs = (ElfW(Addr) *) (array + loadaddr); +		addrs = (ElfW(Addr) *) DL_RELOC_ADDR (array, loadaddr);  		for (j = 0; j < jm; ++j) {  			void (*dl_elf_func) (void); -			dl_elf_func = (void (*)(void)) (intptr_t) addrs[j]; +			dl_elf_func = (void (*)(void)) DL_RELOC_ADDR (addrs[j], +								      loadaddr);  			(*dl_elf_func) ();  		}  	} @@ -136,11 +137,13 @@ void _dl_run_fini_array(struct elf_resolve *tpnt);  void _dl_run_fini_array(struct elf_resolve *tpnt)  {  	if (tpnt->dynamic_info[DT_FINI_ARRAY]) { -		ElfW(Addr) *array = (ElfW(Addr) *) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI_ARRAY]); +		ElfW(Addr) *array = (ElfW(Addr) *) DL_RELOC_ADDR (tpnt->dynamic_info[DT_FINI_ARRAY], +								  tpnt->loadaddr);  		unsigned int i = (tpnt->dynamic_info[DT_FINI_ARRAYSZ] / sizeof(ElfW(Addr)));  		while (i-- > 0) {  			void (*dl_elf_func) (void); -			dl_elf_func = (void (*)(void)) (intptr_t) array[i]; +			dl_elf_func = (void (*)(void)) DL_RELOC_ADDR (array[i], +								      tpnt->loadaddr);  			(*dl_elf_func) ();  		}  	} @@ -166,14 +169,15 @@ static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void)  		if (tpnt->dynamic_info[DT_FINI]) {  			void (*dl_elf_func) (void); -			dl_elf_func = (void (*)(void)) (intptr_t) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]); +			dl_elf_func = (void (*)(void)) DL_RELOC_ADDR (tpnt->dynamic_info[DT_FINI], +								      tpnt->loadaddr);  			_dl_if_debug_dprint("\ncalling FINI: %s\n\n", tpnt->libname);  			(*dl_elf_func) ();  		}  	}  } -void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr, +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)  { @@ -295,13 +299,13 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  		for (idx = 0; idx < auxvt[AT_PHNUM].a_un.a_val; idx++, phdr++)  			if (phdr->p_type == PT_PHDR) { -				app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - phdr->p_vaddr); +				DL_INIT_LOADADDR_PROG (app_tpnt->loadaddr, (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - ppnt->p_vaddr));  				break;  			} -		if (app_tpnt->loadaddr) +		if (DL_LOADADDR_BASE (app_tpnt->loadaddr))  			_dl_debug_early("Position Independent Executable: " -					"app_tpnt->loadaddr=%x\n", app_tpnt->loadaddr); +					"app_tpnt->loadaddr=%x\n", DL_LOADADDR_BASE (app_tpnt->loadaddr));  	}  	/* @@ -318,7 +322,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  			relro_size = ppnt->p_memsz;  		}  		if (ppnt->p_type == PT_DYNAMIC) { -			dpnt = (ElfW(Dyn) *) (ppnt->p_vaddr + app_tpnt->loadaddr); +			dpnt = (ElfW(Dyn) *) DL_RELOC_ADDR (ppnt->p_vaddr, app_tpnt->loadaddr);  			_dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr);  #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__  			/* Ugly, ugly.  We need to call mprotect to change the @@ -331,11 +335,11 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  			if (app_tpnt->dynamic_info[DT_TEXTREL]) {  				ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;  				for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) { -					if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) -						_dl_mprotect((void *) ((ppnt->p_vaddr + app_tpnt->loadaddr) & PAGE_ALIGN), -							     ((ppnt->p_vaddr + app_tpnt->loadaddr) & ADDR_ALIGN) + -							     (unsigned long) ppnt->p_filesz, +					if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) { +						void *base =  DL_RELOC_ADDR (ppnt->p_vaddr & PAGE_ALIGN, app_tpnt->loadaddr); +						_dl_mprotect(base, (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz,  							     PROT_READ | PROT_WRITE | PROT_EXEC); +					}  				}  			}  #endif @@ -346,8 +350,10 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  				continue;  #endif  			/* OK, we have what we need - slip this one into the list. */ -			app_tpnt = _dl_add_elf_hash_table(_dl_progname, (char *)app_tpnt->loadaddr, -					app_tpnt->dynamic_info, ppnt->p_vaddr + app_tpnt->loadaddr, ppnt->p_filesz); +			app_tpnt = _dl_add_elf_hash_table(_dl_progname, app_tpnt->loadaddr, +							  app_tpnt->dynamic_info, +							  (unsigned long) DL_RELOC_ADDR (ppnt->p_vaddr, app_tpnt->loadaddr), +							  ppnt->p_filesz);  			_dl_loaded_modules->libtype = elf_executable;  			_dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;  			_dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val; @@ -368,7 +374,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  		if (ppnt->p_type == PT_INTERP) {  			char *ptmp; -			tpnt->libname = (char *) ppnt->p_vaddr + app_tpnt->loadaddr; +			tpnt->libname = (char *) DL_RELOC_ADDR (ppnt->p_vaddr, app_tpnt->loadaddr);  			/* Store the path where the shared lib loader was found  			 * for later use @@ -378,7 +384,8 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  			if (ptmp != _dl_ldsopath)  				*ptmp = '\0'; -			_dl_debug_early("Lib Loader: (%x) %s\n", tpnt->loadaddr, tpnt->libname); +			_dl_debug_early("Lib Loader: (%x) %s\n", (unsigned) DL_LOADADDR_BASE (tpnt->loadaddr), +					tpnt->libname);  		}  	}  	app_tpnt->relro_addr = relro_addr; @@ -450,7 +457,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  	 */  	debug_addr->r_map = (struct link_map *) _dl_loaded_modules;  	debug_addr->r_version = 1; -	debug_addr->r_ldbase = load_addr; +	debug_addr->r_ldbase = (ElfW(Addr)) DL_LOADADDR_BASE (load_addr);  	debug_addr->r_brk = (unsigned long) &_dl_debug_state;  	_dl_debug_addr = debug_addr; @@ -497,7 +504,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  				} else {  					tpnt1->rtld_flags = unlazy | RTLD_GLOBAL; -					_dl_debug_early("Loading: (%x) %s\n", tpnt1->loadaddr, tpnt1->libname); +					_dl_debug_early("Loading: (%x) %s\n", (unsigned) DL_LOADADDR_BASE (tpnt1->loadaddr), tpnt1->libname);  #ifdef __LDSO_LDD_SUPPORT__  					if (trace_loaded_objects && @@ -509,7 +516,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  						 */  						if (_dl_strcmp(_dl_progname, str) != 0)  							_dl_dprintf(1, "\t%s => %s (%x)\n", str, tpnt1->libname, -								    tpnt1->loadaddr); +								    (unsigned) DL_LOADADDR_BASE (tpnt1->loadaddr));  					}  #endif  				} @@ -588,14 +595,14 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  			} else {  				tpnt1->rtld_flags = unlazy | RTLD_GLOBAL; -				_dl_debug_early("Loading: (%x) %s\n", tpnt1->loadaddr, tpnt1->libname); +				_dl_debug_early("Loading: (%x) %s\n", (unsigned) DL_LOADADDR_BASE (tpnt1->loadaddr), tpnt1->libname);  #ifdef __LDSO_LDD_SUPPORT__  				if (trace_loaded_objects &&  				    tpnt1->usage_count == 1) {  					_dl_dprintf(1, "\t%s => %s (%x)\n",  						    cp2, tpnt1->libname, -						    (unsigned)tpnt1->loadaddr); +						    (unsigned) DL_LOADADDR_BASE (tpnt1->loadaddr));  				}  #endif  			} @@ -647,14 +654,14 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  				tpnt1->rtld_flags = unlazy | RTLD_GLOBAL; -				_dl_debug_early("Loading: (%x) %s\n", tpnt1->loadaddr, tpnt1->libname); +				_dl_debug_early("Loading: (%x) %s\n", (unsigned) DL_LOADADDR_BASE (tpnt1->loadaddr), tpnt1->libname);  #ifdef __LDSO_LDD_SUPPORT__  				if (trace_loaded_objects &&  				    tpnt1->usage_count == 1) {  					_dl_dprintf(1, "\t%s => %s (%x)\n",  						    lpntstr, tpnt1->libname, -						    (unsigned)tpnt1->loadaddr); +						    (unsigned) DL_LOADADDR_BASE (tpnt1->loadaddr));  				}  #endif  			} @@ -715,10 +722,10 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  	 */  	if (tpnt) {  		ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val; -		ElfW(Phdr) *myppnt = (ElfW(Phdr) *) (load_addr + epnt->e_phoff); +		ElfW(Phdr) *myppnt = (ElfW(Phdr) *) DL_RELOC_ADDR (epnt->e_phoff, load_addr);  		int j; -		tpnt = _dl_add_elf_hash_table(tpnt->libname, (char *)load_addr, +		tpnt = _dl_add_elf_hash_table(tpnt->libname, load_addr,  					      tpnt->dynamic_info,  					      (unsigned long)tpnt->dynamic_addr,  					      0); @@ -765,7 +772,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  	if (trace_loaded_objects) {  		_dl_dprintf(1, "\t%s => %s (%x)\n",  			    rpnt->dyn->libname + _dl_strlen(_dl_ldsopath) + 1, -			    rpnt->dyn->libname, rpnt->dyn->loadaddr); +			    rpnt->dyn->libname, (unsigned) DL_LOADADDR_BASE (rpnt->dyn->loadaddr));  		_dl_exit(0);  	}  #endif @@ -817,8 +824,10 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  		for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {  			for (myppnt = tpnt->ppnt, j = 0; j < tpnt->n_phent; j++, myppnt++) {  				if (myppnt->p_type == PT_LOAD && !(myppnt->p_flags & PF_W) && tpnt->dynamic_info[DT_TEXTREL]) { -					_dl_mprotect((void *) (tpnt->loadaddr + (myppnt->p_vaddr & PAGE_ALIGN)), -							(myppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) myppnt->p_filesz, LXFLAGS(myppnt->p_flags)); +					void *base = DL_RELOC_ADDR (myppnt->p_vaddr & PAGE_ALIGN, tpnt->loadaddr); +					_dl_mprotect(base, +						     (myppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) myppnt->p_filesz, +						     LXFLAGS(myppnt->p_flags));  				}  			}  		} @@ -846,7 +855,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,  		if (tpnt->dynamic_info[DT_INIT]) {  			void (*dl_elf_func) (void); -			dl_elf_func = (void (*)(void)) (intptr_t) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]); +			dl_elf_func = (void (*)(void)) DL_RELOC_ADDR (tpnt->dynamic_info[DT_INIT], tpnt->loadaddr);  			_dl_if_debug_dprint("calling INIT: %s\n\n", tpnt->libname); diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c index 322230860..b533a2da1 100644 --- a/ldso/libdl/libdl.c +++ b/ldso/libdl/libdl.c @@ -175,8 +175,7 @@ void *dlopen(const char *libname, int flag)  		tfrom = NULL;  		for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) {  			tpnt = dpnt->dyn; -			if (tpnt->loadaddr < from -					&& (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr)) +			if (DL_ADDR_IN_LOADADDR (from, tpnt, tfrom))  				tfrom = tpnt;  		}  	} @@ -378,7 +377,7 @@ void *dlopen(const char *libname, int flag)  		if (tpnt->dynamic_info[DT_INIT]) {  			void (*dl_elf_func) (void); -			dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]); +			dl_elf_func = (void (*)(void)) DL_RELOC_ADDR (tpnt->dynamic_info[DT_INIT], tpnt->loadaddr);  			if (dl_elf_func && *dl_elf_func != NULL) {  				_dl_if_debug_print("running ctors for library %s at '%p'\n",  						tpnt->libname, dl_elf_func); @@ -436,8 +435,7 @@ void *dlsym(void *vhandle, const char *name)  		tfrom = NULL;  		for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) {  			tpnt = rpnt->dyn; -			if (tpnt->loadaddr < from -					&& (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr)) { +			if (DL_ADDR_IN_LOADADDR (from, tpnt, tfrom)) {  				tfrom = tpnt;  				handle = rpnt->next;  			} @@ -512,7 +510,7 @@ static int do_dlclose(void *vhandle, int need_fini)  #endif  				if (tpnt->dynamic_info[DT_FINI]) { -					dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]); +				    dl_elf_fini = (int (*)(void)) DL_RELOC_ADDR (tpnt->dynamic_info[DT_FINI], tpnt->loadaddr);  					_dl_if_debug_print("running dtors for library %s at '%p'\n",  							tpnt->libname, dl_elf_fini);  					(*dl_elf_fini) (); @@ -622,7 +620,7 @@ int dlinfo(void)  	/* First start with a complete list of all of the loaded files. */  	for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {  		fprintf(stderr, "\t%p %p %p %s %d %s\n", -		        tpnt->loadaddr, tpnt, tpnt->symbol_scope, +		        DL_LOADADDR_BASE (tpnt->loadaddr), tpnt, tpnt->symbol_scope,  		        type[tpnt->libtype],  		        tpnt->usage_count, tpnt->libname);  	} @@ -662,12 +660,10 @@ int dladdr(const void *__address, Dl_info * __info)  		tpnt = rpnt;  #if 0  		fprintf(stderr, "Module \"%s\" at %p\n", -				tpnt->libname, tpnt->loadaddr); +			tpnt->libname, DL_LOADADDR_BASE (tpnt->loadaddr));  #endif -		if (tpnt->loadaddr < (ElfW(Addr)) __address -				&& (pelf == NULL || pelf->loadaddr < tpnt->loadaddr)) { +		if (DL_ADDR_IN_LOADADDR ((ElfW(Addr)) __address,  tpnt, pelf))  			pelf = tpnt; -		}  	}  	if (!pelf) { @@ -693,7 +689,7 @@ int dladdr(const void *__address, Dl_info * __info)  			for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) {  				ElfW(Addr) symbol_addr; -				symbol_addr = pelf->loadaddr + symtab[si].st_value; +				symbol_addr = (ElfW(Addr)) DL_RELOC_ADDR (symtab[si].st_value, pelf->loadaddr);  				if (symbol_addr <= (ElfW(Addr))__address && (!sf || sa < symbol_addr)) {  					sa = symbol_addr;  					sn = si; @@ -708,7 +704,7 @@ int dladdr(const void *__address, Dl_info * __info)  		if (sf) {  			__info->dli_fname = pelf->libname; -			__info->dli_fbase = (void *)pelf->loadaddr; +			__info->dli_fbase = DL_LOADADDR_BASE (pelf->loadaddr);  			__info->dli_sname = strtab + symtab[sn].st_name;  			__info->dli_saddr = (void *)sa;  		} | 
