瀏覽代碼

clean up internal dynamic linker functions enumerating phdrs

record phentsize in struct dso, so the phdrs can be easily
enumerated via it. simplify all functions enumerating phdrs
to require only struct dso. also merge find_map_range and
find_dso to kernel_mapped_dso function that does both tasks
during single phdr enumeration.
Timo Teräs 11 年之前
父節點
當前提交
8769196ffb
共有 1 個文件被更改,包括 23 次插入28 次删除
  1. 23 28
      src/ldso/dynlink.c

+ 23 - 28
src/ldso/dynlink.c

@@ -56,6 +56,7 @@ struct dso {
 
 
 	Phdr *phdr;
 	Phdr *phdr;
 	int phnum;
 	int phnum;
+	size_t phentsize;
 	int refcnt;
 	int refcnt;
 	Sym *syms;
 	Sym *syms;
 	uint32_t *hashtab;
 	uint32_t *hashtab;
@@ -298,9 +299,12 @@ static void reclaim(struct dso *dso, size_t start, size_t end)
 	free(a);
 	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_type!=PT_LOAD) continue;
 		if ((ph->p_flags&(PF_R|PF_W))!=(PF_R|PF_W)) continue;
 		if ((ph->p_flags&(PF_R|PF_W))!=(PF_R|PF_W)) continue;
 		reclaim(dso, ph->p_vaddr & -PAGE_SIZE, ph->p_vaddr);
 		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
 			dso->phdr = (void *)(base + ph->p_vaddr
 				+ (eh->e_phoff-ph->p_offset));
 				+ (eh->e_phoff-ph->p_offset));
 			dso->phnum = eh->e_phnum;
 			dso->phnum = eh->e_phnum;
+			dso->phentsize = eh->e_phentsize;
 		}
 		}
 		/* Reuse the existing mapping for the lowest-address LOAD */
 		/* Reuse the existing mapping for the lowest-address LOAD */
 		if ((ph->p_vaddr & -PAGE_SIZE) == addr_min) continue;
 		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->base = base;
 	dso->dynv = (void *)(base+dyn);
 	dso->dynv = (void *)(base+dyn);
 	if (dso->tls_size) dso->tls_image = (void *)(base+tls_image);
 	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);
 	free(allocated_buf);
 	return map;
 	return map;
 noexec:
 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_start = ph->p_vaddr & -PAGE_SIZE;
 			p->relro_end = (ph->p_vaddr + ph->p_memsz) & -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;
 	max_addr = (max_addr + PAGE_SIZE-1) & -PAGE_SIZE;
 	p->map = p->base + min_addr;
 	p->map = p->base + min_addr;
 	p->map_len = max_addr - min_addr;
 	p->map_len = max_addr - min_addr;
+	p->kernel_mapped = 1;
 }
 }
 
 
 static void do_fini()
 static void do_fini()
@@ -1023,13 +1024,11 @@ void *__dynlink(int argc, char **argv)
 	lib->base = (void *)aux[AT_BASE];
 	lib->base = (void *)aux[AT_BASE];
 	lib->name = lib->shortname = "libc.so";
 	lib->name = lib->shortname = "libc.so";
 	lib->global = 1;
 	lib->global = 1;
-	lib->kernel_mapped = 1;
 	ehdr = (void *)lib->base;
 	ehdr = (void *)lib->base;
 	lib->phnum = ehdr->e_phnum;
 	lib->phnum = ehdr->e_phnum;
 	lib->phdr = (void *)(aux[AT_BASE]+ehdr->e_phoff);
 	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);
 	decode_dyn(lib);
 
 
 	if (aux[AT_PHDR]) {
 	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. */
 		/* Find load address of the main program, via AT_PHDR vs PT_PHDR. */
 		app->phdr = phdr = (void *)aux[AT_PHDR];
 		app->phdr = phdr = (void *)aux[AT_PHDR];
 		app->phnum = aux[AT_PHNUM];
 		app->phnum = aux[AT_PHNUM];
+		app->phentsize = aux[AT_PHENT];
 		for (i=aux[AT_PHNUM]; i; i--, phdr=(void *)((char *)phdr + aux[AT_PHENT])) {
 		for (i=aux[AT_PHNUM]; i; i--, phdr=(void *)((char *)phdr + aux[AT_PHENT])) {
 			if (phdr->p_type == PT_PHDR)
 			if (phdr->p_type == PT_PHDR)
 				app->base = (void *)(aux[AT_PHDR] - phdr->p_vaddr);
 				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];
 			app->name = (char *)aux[AT_EXECFN];
 		else
 		else
 			app->name = argv[0];
 			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 {
 	} else {
 		int fd;
 		int fd;
 		char *ldname = argv[0];
 		char *ldname = argv[0];
@@ -1127,6 +1123,7 @@ void *__dynlink(int argc, char **argv)
 		ehdr = (void *)vdso_base;
 		ehdr = (void *)vdso_base;
 		vdso->phdr = phdr = (void *)(vdso_base + ehdr->e_phoff);
 		vdso->phdr = phdr = (void *)(vdso_base + ehdr->e_phoff);
 		vdso->phnum = ehdr->e_phnum;
 		vdso->phnum = ehdr->e_phnum;
+		vdso->phentsize = ehdr->e_phentsize;
 		for (i=ehdr->e_phnum; i; i--, phdr=(void *)((char *)phdr + ehdr->e_phentsize)) {
 		for (i=ehdr->e_phnum; i; i--, phdr=(void *)((char *)phdr + ehdr->e_phentsize)) {
 			if (phdr->p_type == PT_DYNAMIC)
 			if (phdr->p_type == PT_DYNAMIC)
 				vdso->dynv = (void *)(vdso_base + phdr->p_offset);
 				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. */
 	/* PAST THIS POINT, ALL LIBC INTERFACES ARE FULLY USABLE. */
 
 
 	/* Donate unused parts of app and library mapping to malloc */
 	/* 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
 	/* Load preload/needed libraries, add their symbols to the global
 	 * namespace, and perform all remaining relocations. The main
 	 * namespace, and perform all remaining relocations. The main