diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ldso/dynlink.c | 51 | 
1 files changed, 23 insertions, 28 deletions
diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index de0f2ac8..2f151c22 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -56,6 +56,7 @@ struct dso {  	Phdr *phdr;  	int phnum; +	size_t phentsize;  	int refcnt;  	Sym *syms;  	uint32_t *hashtab; @@ -298,9 +299,12 @@ static void reclaim(struct dso *dso, size_t start, size_t end)  	free(a);  } -static void reclaim_gaps(struct dso *dso, Phdr *ph, size_t phent, size_t phcnt) +static void reclaim_gaps(struct dso *dso)  { -	for (; phcnt--; ph=(void *)((char *)ph+phent)) { +	Phdr *ph; +	size_t phcnt; + +	for (phcnt = dso->phnum, ph = dso->phdr; phcnt--; ph=(void *)((char *)ph+dso->phentsize)) {  		if (ph->p_type!=PT_LOAD) continue;  		if ((ph->p_flags&(PF_R|PF_W))!=(PF_R|PF_W)) continue;  		reclaim(dso, ph->p_vaddr & -PAGE_SIZE, ph->p_vaddr); @@ -400,6 +404,7 @@ static void *map_library(int fd, struct dso *dso)  			dso->phdr = (void *)(base + ph->p_vaddr  				+ (eh->e_phoff-ph->p_offset));  			dso->phnum = eh->e_phnum; +			dso->phentsize = eh->e_phentsize;  		}  		/* Reuse the existing mapping for the lowest-address LOAD */  		if ((ph->p_vaddr & -PAGE_SIZE) == addr_min) continue; @@ -430,7 +435,7 @@ static void *map_library(int fd, struct dso *dso)  	dso->base = base;  	dso->dynv = (void *)(base+dyn);  	if (dso->tls_size) dso->tls_image = (void *)(base+tls_image); -	if (!runtime) reclaim_gaps(dso, ph0, eh->e_phentsize, eh->e_phnum); +	if (!runtime) reclaim_gaps(dso);  	free(allocated_buf);  	return map;  noexec: @@ -787,19 +792,14 @@ static void reloc_all(struct dso *p)  	}  } -static size_t find_dyn(Phdr *ph, size_t cnt, size_t stride) -{ -	for (; cnt--; ph = (void *)((char *)ph + stride)) -		if (ph->p_type == PT_DYNAMIC) -			return ph->p_vaddr; -	return 0; -} - -static void find_map_range(Phdr *ph, size_t cnt, size_t stride, struct dso *p) +static void kernel_mapped_dso(struct dso *p)  { -	size_t min_addr = -1, max_addr = 0; -	for (; cnt--; ph = (void *)((char *)ph + stride)) { -		if (ph->p_type == PT_GNU_RELRO) { +	size_t min_addr = -1, max_addr = 0, cnt; +	Phdr *ph = p->phdr; +	for (cnt = p->phnum; cnt--; ph = (void *)((char *)ph + p->phentsize)) { +		if (ph->p_type == PT_DYNAMIC) { +			p->dynv = (void *)(p->base + ph->p_vaddr); +		} else if (ph->p_type == PT_GNU_RELRO) {  			p->relro_start = ph->p_vaddr & -PAGE_SIZE;  			p->relro_end = (ph->p_vaddr + ph->p_memsz) & -PAGE_SIZE;  		} @@ -813,6 +813,7 @@ static void find_map_range(Phdr *ph, size_t cnt, size_t stride, struct dso *p)  	max_addr = (max_addr + PAGE_SIZE-1) & -PAGE_SIZE;  	p->map = p->base + min_addr;  	p->map_len = max_addr - min_addr; +	p->kernel_mapped = 1;  }  static void do_fini() @@ -1023,13 +1024,11 @@ void *__dynlink(int argc, char **argv)  	lib->base = (void *)aux[AT_BASE];  	lib->name = lib->shortname = "libc.so";  	lib->global = 1; -	lib->kernel_mapped = 1;  	ehdr = (void *)lib->base;  	lib->phnum = ehdr->e_phnum;  	lib->phdr = (void *)(aux[AT_BASE]+ehdr->e_phoff); -	find_map_range(lib->phdr, ehdr->e_phnum, ehdr->e_phentsize, lib); -	lib->dynv = (void *)(lib->base + find_dyn(lib->phdr, -		ehdr->e_phnum, ehdr->e_phentsize)); +	lib->phentsize = ehdr->e_phentsize; +	kernel_mapped_dso(lib);  	decode_dyn(lib);  	if (aux[AT_PHDR]) { @@ -1038,6 +1037,7 @@ void *__dynlink(int argc, char **argv)  		/* Find load address of the main program, via AT_PHDR vs PT_PHDR. */  		app->phdr = phdr = (void *)aux[AT_PHDR];  		app->phnum = aux[AT_PHNUM]; +		app->phentsize = aux[AT_PHENT];  		for (i=aux[AT_PHNUM]; i; i--, phdr=(void *)((char *)phdr + aux[AT_PHENT])) {  			if (phdr->p_type == PT_PHDR)  				app->base = (void *)(aux[AT_PHDR] - phdr->p_vaddr); @@ -1057,11 +1057,7 @@ void *__dynlink(int argc, char **argv)  			app->name = (char *)aux[AT_EXECFN];  		else  			app->name = argv[0]; -		app->kernel_mapped = 1; -		app->dynv = (void *)(app->base + find_dyn( -			(void *)aux[AT_PHDR], aux[AT_PHNUM], aux[AT_PHENT])); -		find_map_range((void *)aux[AT_PHDR], -			aux[AT_PHNUM], aux[AT_PHENT], app); +		kernel_mapped_dso(app);  	} else {  		int fd;  		char *ldname = argv[0]; @@ -1127,6 +1123,7 @@ void *__dynlink(int argc, char **argv)  		ehdr = (void *)vdso_base;  		vdso->phdr = phdr = (void *)(vdso_base + ehdr->e_phoff);  		vdso->phnum = ehdr->e_phnum; +		vdso->phentsize = ehdr->e_phentsize;  		for (i=ehdr->e_phnum; i; i--, phdr=(void *)((char *)phdr + ehdr->e_phentsize)) {  			if (phdr->p_type == PT_DYNAMIC)  				vdso->dynv = (void *)(vdso_base + phdr->p_offset); @@ -1154,10 +1151,8 @@ void *__dynlink(int argc, char **argv)  	/* PAST THIS POINT, ALL LIBC INTERFACES ARE FULLY USABLE. */  	/* Donate unused parts of app and library mapping to malloc */ -	reclaim_gaps(app, (void *)aux[AT_PHDR], aux[AT_PHENT], aux[AT_PHNUM]); -	ehdr = (void *)lib->base; -	reclaim_gaps(lib, (void *)(lib->base+ehdr->e_phoff), -		ehdr->e_phentsize, ehdr->e_phnum); +	reclaim_gaps(app); +	reclaim_gaps(lib);  	/* Load preload/needed libraries, add their symbols to the global  	 * namespace, and perform all remaining relocations. The main  | 
