use load address from elf header if possible
[musl] / src / ldso / dynlink.c
index 305d70e..527b36b 100644 (file)
@@ -189,7 +189,7 @@ static void *map_library(int fd, size_t *lenp, unsigned char **basep, size_t *dy
         * the length of the file. This is okay because we will not
         * use the invalid part; we just need to reserve the right
         * amount of virtual address space to map over later. */
-       map = mmap(0, map_len, prot, MAP_PRIVATE, fd, off_start);
+       map = mmap((void *)addr_min, map_len, prot, MAP_PRIVATE, fd, off_start);
        if (map==MAP_FAILED) return 0;
        base = map - addr_min;
        ph = (void *)((char *)buf + eh->e_phoff);
@@ -462,6 +462,7 @@ void *__dynlink(int argc, char **argv, size_t *got)
        load_deps(head);
 
        make_global(head);
+       reloc_all(head->next);
        reloc_all(head);
 
        if (rtld_used) {
@@ -473,6 +474,7 @@ void *__dynlink(int argc, char **argv, size_t *got)
                *libc->prev->next = *libc;
                libc = libc->prev->next;
                if (libc->next) libc->next->prev = libc;
+               if (tail == &lib) tail = libc;
        } else {
                free_all(head);
                free(sys_path);
@@ -509,30 +511,30 @@ void *dlopen(const char *file, int mode)
        }
 
        p = load_library(file);
-       if (!p) return 0;
+       if (!p) goto end;
 
        /* First load handling */
        if (!p->deps) {
                load_deps(p);
-               for (i=0; p->deps[i]; i++)
+               if (p->deps) for (i=0; p->deps[i]; i++)
                        if (!p->deps[i]->global)
                                p->deps[i]->global = -1;
                if (!p->global) p->global = -1;
                reloc_all(p);
-               for (i=0; p->deps[i]; i++)
+               if (p->deps) for (i=0; p->deps[i]; i++)
                        if (p->deps[i]->global < 0)
                                p->deps[i]->global = 0;
                if (p->global < 0) p->global = 0;
        }
 
        if (mode & RTLD_GLOBAL) {
-               for (i=0; p->deps[i]; i++)
+               if (p->deps) for (i=0; p->deps[i]; i++)
                        p->deps[i]->global = 1;
                p->global = 1;
        }
 
+end:
        pthread_rwlock_unlock(&lock);
-
        return p;
 }
 
@@ -541,7 +543,8 @@ static void *do_dlsym(struct dso *p, const char *s)
        size_t i;
        uint32_t h;
        Sym *sym;
-       if (p == head) return find_sym(head, s, 0);
+       if (p == head || p == RTLD_DEFAULT)
+               return find_sym(head, s, 0);
        h = hash(s);
        sym = lookup(s, h, p->syms, p->hashtab, p->strings);
        if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES))