diff options
Diffstat (limited to 'src/ldso/dynlink.c')
-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 |