- app = (struct dso){
- .base = 0,
- .strings = (void *)(app_dyn[DT_STRTAB]),
- .hashtab = (void *)(app_dyn[DT_HASH]),
- .syms = (void *)(app_dyn[DT_SYMTAB]),
- .dynv = (void *)(phdr->p_vaddr),
- .name = argv[0],
- .global = 1,
- .next = &lib
- };
-
- lib = (struct dso){
- .base = (void *)aux[AT_BASE],
- .strings = (void *)(aux[AT_BASE]+lib_dyn[DT_STRTAB]),
- .hashtab = (void *)(aux[AT_BASE]+lib_dyn[DT_HASH]),
- .syms = (void *)(aux[AT_BASE]+lib_dyn[DT_SYMTAB]),
- .dynv = (void *)(got[0]),
- .name = "libc.so",
- .global = 1,
- .relocated = 1
- };
-
- /* Relocate the dynamic linker/libc */
- do_relocs((void *)aux[AT_BASE], (void *)(aux[AT_BASE]+lib_dyn[DT_REL]),
- lib_dyn[DT_RELSZ], 2, lib.syms, lib.strings, &app);
- do_relocs((void *)aux[AT_BASE], (void *)(aux[AT_BASE]+lib_dyn[DT_RELA]),
- lib_dyn[DT_RELASZ], 3, lib.syms, lib.strings, &app);
-
- /* At this point the standard library is fully functional */
-
- head = tail = &app;
- libc = &lib;
- app.next = 0;
- load_deps(head);
-
- make_global(head);
- reloc_all(head->next);
- reloc_all(head);
-
- if (rtld_used) {
- runtime = 1;
- head->next->prev = malloc(sizeof *head);
- *head->next->prev = *head;
- head = head->next->prev;
- libc->prev->next = malloc(sizeof *libc);
- *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);
+ /* Attach to vdso, if provided by the kernel */
+ if (search_vec(auxv, &vdso_base, AT_SYSINFO_EHDR)) {
+ ehdr = (void *)vdso_base;
+ 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);
+ if (phdr->p_type == PT_LOAD)
+ vdso->base = (void *)(vdso_base - phdr->p_vaddr + phdr->p_offset);
+ }
+ vdso->name = "";
+ vdso->shortname = "linux-gate.so.1";
+ vdso->global = 1;
+ decode_dyn(vdso);
+ vdso->prev = lib;
+ lib->next = vdso;
+ }
+
+ /* Initial dso chain consists only of the app. We temporarily
+ * append the dynamic linker/libc so we can relocate it, then
+ * restore the initial chain in preparation for loading third
+ * party libraries (preload/needed). */
+ head = tail = app;
+ ldso = lib;
+ app->next = lib;
+ reloc_all(lib);
+ app->next = 0;
+
+ /* PAST THIS POINT, ALL LIBC INTERFACES ARE FULLY USABLE. */
+
+ /* Donate unused parts of app and library mapping to malloc */
+ reclaim_gaps(app->base, (void *)aux[AT_PHDR], aux[AT_PHENT], aux[AT_PHNUM]);
+ ehdr = (void *)lib->base;
+ reclaim_gaps(lib->base, (void *)(lib->base+ehdr->e_phoff),
+ ehdr->e_phentsize, ehdr->e_phnum);
+
+ /* Load preload/needed libraries, add their symbols to the global
+ * namespace, and perform all remaining relocations. The main
+ * program must be relocated LAST since it may contain copy
+ * relocations which depend on libraries' relocations. */
+ if (env_preload) load_preload(env_preload);
+ load_deps(app);
+ make_global(app);
+
+ reloc_all(app->next);
+ reloc_all(app);
+
+ update_tls_size();
+ if (tls_cnt) {
+ void *mem = mmap(0, libc.tls_size, PROT_READ|PROT_WRITE,
+ MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+ if (mem==MAP_FAILED ||
+ !__install_initial_tls(__copy_tls(mem))) {
+ dprintf(2, "%s: Error getting %zu bytes thread-local storage: %m\n",
+ argv[0], libc.tls_size);
+ _exit(127);
+ }