|
@@ -13,6 +13,7 @@
|
|
|
#include <errno.h>
|
|
|
#include <limits.h>
|
|
|
#include <elf.h>
|
|
|
+#include <link.h>
|
|
|
#include <setjmp.h>
|
|
|
#include <pthread.h>
|
|
|
#include <ctype.h>
|
|
@@ -56,6 +57,8 @@ struct dso {
|
|
|
size_t *dynv;
|
|
|
struct dso *next, *prev;
|
|
|
|
|
|
+ Phdr *phdr;
|
|
|
+ int phnum;
|
|
|
int refcnt;
|
|
|
Sym *syms;
|
|
|
uint32_t *hashtab;
|
|
@@ -91,6 +94,7 @@ void *__install_initial_tls(void *);
|
|
|
|
|
|
static struct dso *head, *tail, *ldso, *fini_head;
|
|
|
static char *env_path, *sys_path, *r_path;
|
|
|
+static unsigned long long gencnt;
|
|
|
static int ssp_used;
|
|
|
static int runtime;
|
|
|
static int ldd_mode;
|
|
@@ -323,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 = 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;
|
|
@@ -825,18 +831,19 @@ 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 = 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];
|
|
|
+ app->phdr = phdr = (void *)aux[AT_PHDR];
|
|
|
+ app->phnum = aux[AT_PHNUM];
|
|
|
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);
|
|
@@ -884,6 +891,8 @@ void *__dynlink(int argc, char **argv)
|
|
|
close(fd);
|
|
|
lib->name = ldname;
|
|
|
app->name = argv[0];
|
|
|
+ app->phnum = ehdr->e_phnum;
|
|
|
+ app->phdr = (void *)(app->base + ehdr->e_phoff);
|
|
|
aux[AT_ENTRY] = ehdr->e_entry;
|
|
|
}
|
|
|
if (app->tls_size) {
|
|
@@ -907,7 +916,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);
|
|
@@ -1068,6 +1078,7 @@ void *dlopen(const char *file, int mode)
|
|
|
orig_tail = tail;
|
|
|
end:
|
|
|
__release_ptc();
|
|
|
+ if (p) gencnt++;
|
|
|
pthread_rwlock_unlock(&lock);
|
|
|
if (p) do_init_fini(orig_tail);
|
|
|
pthread_setcancelstate(cs, 0);
|
|
@@ -1192,6 +1203,32 @@ 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;
|
|
|
+ struct dl_phdr_info info;
|
|
|
+ int ret = 0;
|
|
|
+ for(current = head; current;) {
|
|
|
+ info.dlpi_addr = (uintptr_t)current->base;
|
|
|
+ info.dlpi_name = current->name;
|
|
|
+ info.dlpi_phdr = current->phdr;
|
|
|
+ info.dlpi_phnum = current->phnum;
|
|
|
+ info.dlpi_adds = gencnt;
|
|
|
+ info.dlpi_subs = 0;
|
|
|
+ info.dlpi_tls_modid = current->tls_id;
|
|
|
+ info.dlpi_tls_data = current->tls_image;
|
|
|
+
|
|
|
+ ret = (callback)(&info, sizeof (info), data);
|
|
|
+
|
|
|
+ if (ret != 0) break;
|
|
|
+
|
|
|
+ pthread_rwlock_rdlock(&lock);
|
|
|
+ current = current->next;
|
|
|
+ pthread_rwlock_unlock(&lock);
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
+}
|
|
|
#else
|
|
|
void *dlopen(const char *file, int mode)
|
|
|
{
|