summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ldso/dynlink.c51
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