summaryrefslogtreecommitdiff
path: root/src/ldso
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2014-03-25 20:59:50 +0200
committerRich Felker <dalias@aerifal.cx>2014-03-25 16:03:53 -0400
commit8769196ffb20569fb97fce9716b3a21fada3f02a (patch)
tree7b784c39092788a639f3d2d2e0536c2b8dd9df2f /src/ldso
parente13a2b8953efabd38edfb7637fda08638454c001 (diff)
downloadmusl-8769196ffb20569fb97fce9716b3a21fada3f02a.tar.gz
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.
Diffstat (limited to 'src/ldso')
-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