diff --git a/src/ldso/dynlink.c b/src/ldso/dynlink.c index c3cb611..503ed0e 100644 --- a/src/ldso/dynlink.c +++ b/src/ldso/dynlink.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,8 @@ struct dso { size_t *dynv; struct dso *next, *prev; + Phdr *phdr; + uint16_t phnum; int refcnt; Sym *syms; uint32_t *hashtab; @@ -324,6 +327,8 @@ static void *map_library(int fd, struct dso *dso) eh->e_phoff = sizeof *eh; } ph = (void *)((char *)buf + eh->e_phoff); + dso->phdr = ph; + dso->phnum = (uint16_t)eh->e_phnum; for (i=eh->e_phnum; i; i--, ph=(void *)((char *)ph+eh->e_phentsize)) { if (ph->p_type == PT_DYNAMIC) dyn = ph->p_vaddr; @@ -815,19 +820,20 @@ void *__dynlink(int argc, char **argv) lib->name = lib->shortname = "libc.so"; lib->global = 1; ehdr = (void *)lib->base; - find_map_range((void *)(aux[AT_BASE]+ehdr->e_phoff), - ehdr->e_phnum, ehdr->e_phentsize, lib); - lib->dynv = (void *)(lib->base + find_dyn( - (void *)(aux[AT_BASE]+ehdr->e_phoff), - ehdr->e_phnum, ehdr->e_phentsize)); + lib->phnum = (uint16_t)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)); decode_dyn(lib); if (aux[AT_PHDR]) { size_t interp_off = 0; size_t tls_image = 0; /* Find load address of the main program, via AT_PHDR vs PT_PHDR. */ - phdr = (void *)aux[AT_PHDR]; - for (i=aux[AT_PHNUM]; i; i--, phdr=(void *)((char *)phdr + aux[AT_PHENT])) { + app->phdr = phdr = (void *)aux[AT_PHDR]; + app->phnum = aux[AT_PHNUM]; + for (i=app->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); else if (phdr->p_type == PT_INTERP) @@ -890,7 +896,8 @@ void *__dynlink(int argc, char **argv) /* Attach to vdso, if provided by the kernel */ if (search_vec(auxv, &vdso_base, AT_SYSINFO_EHDR)) { ehdr = (void *)vdso_base; - phdr = (void *)(vdso_base + ehdr->e_phoff); + vdso->phdr = phdr = (void *)(vdso_base + ehdr->e_phoff); + vdso->phnum = ehdr->e_phnum; 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); @@ -1166,6 +1173,30 @@ void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra) pthread_rwlock_unlock(&lock); return res; } + +int dl_iterate_phdr(int(*callback)(struct dl_phdr_info *info, size_t size, void *data), void *data) +{ + struct dso *current, *saved_tail; + struct dl_phdr_info info; + int ret = 0; + + pthread_rwlock_rdlock(&lock); + saved_tail = tail; + pthread_rwlock_unlock(&lock); + + for(current = head; ; current = current->next) { + info.dlpi_addr = (uintptr_t)current->base; + info.dlpi_name = current->name; + info.dlpi_phdr = current->phdr; + info.dlpi_phnum = current->phnum; + + ret = (callback)(&info, sizeof (info), data); + if (ret != 0) break; + + if (current == saved_tail) break; + } + return ret; +} #else void *dlopen(const char *file, int mode) {