summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libexec/ld.so/loader.c61
1 files changed, 42 insertions, 19 deletions
diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c
index 50d49a8df05..cd2b180dafa 100644
--- a/libexec/ld.so/loader.c
+++ b/libexec/ld.so/loader.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: loader.c,v 1.113 2008/05/05 02:29:02 kurt Exp $ */
+/* $OpenBSD: loader.c,v 1.114 2008/06/12 19:50:04 kurt Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -353,7 +353,7 @@ _dl_load_dep_libs(elf_object_t *object, int flags, int booting)
* to do is to dig out all information we need to accomplish our task.
*/
unsigned long
-_dl_boot(const char **argv, char **envp, const long loff, long *dl_data)
+_dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data)
{
struct elf_object *exe_obj; /* Pointer to executable object */
struct elf_object *dyn_obj; /* Pointer to executable object */
@@ -363,10 +363,12 @@ _dl_boot(const char **argv, char **envp, const long loff, long *dl_data)
Elf_Dyn *dynp;
Elf_Phdr *phdp;
Elf_Ehdr *ehdr;
- char *us = "";
+ char *us = NULL;
unsigned int loop;
int failed;
struct dep_node *n;
+ Elf_Addr minva, maxva, exe_loff;
+ int align;
_dl_setup_env(envp);
@@ -376,6 +378,11 @@ _dl_boot(const char **argv, char **envp, const long loff, long *dl_data)
else
_dl_pagesz = 4096;
+ align = _dl_pagesz - 1;
+
+#define ROUND_PG(x) (((x) + align) & ~(align))
+#define TRUNC_PG(x) ((x) & ~(align))
+
/*
* now that GOT and PLT has been relocated, and we know
* page size, protect it from modification
@@ -411,40 +418,56 @@ _dl_boot(const char **argv, char **envp, const long loff, long *dl_data)
exe_obj = NULL;
_dl_loading_object = NULL;
+
+ minva = ELFDEFNNAME(NO_ADDR);
+ maxva = exe_loff = 0;
+
/*
* Examine the user application and set up object information.
*/
phdp = (Elf_Phdr *)dl_data[AUX_phdr];
for (loop = 0; loop < dl_data[AUX_phnum]; loop++) {
- if (phdp->p_type == PT_DYNAMIC) {
+ switch (phdp->p_type) {
+ case PT_PHDR:
+ exe_loff = (Elf_Addr)dl_data[AUX_phdr] - phdp->p_vaddr;
+ us += exe_loff;
+ DL_DEB(("exe load offset: 0x%lx\n", exe_loff));
+ break;
+ case PT_DYNAMIC:
+ minva = TRUNC_PG(minva);
+ maxva = ROUND_PG(maxva);
exe_obj = _dl_finalize_object(argv[0] ? argv[0] : "",
(Elf_Dyn *)phdp->p_vaddr, (Elf_Phdr *)dl_data[AUX_phdr],
- dl_data[AUX_phnum], OBJTYPE_EXE, 0, 0);
+ dl_data[AUX_phnum], OBJTYPE_EXE, minva + exe_loff, exe_loff);
_dl_add_object(exe_obj);
- } else if (phdp->p_type == PT_INTERP) {
- us = _dl_strdup((char *)phdp->p_vaddr);
- } else if (phdp->p_type == PT_LOAD) {
- int align = _dl_pagesz - 1;
- int size = (phdp->p_vaddr & align) + phdp->p_filesz;
-
-#define TRUNC_PG(x) ((x) & ~(align))
+ break;
+ case PT_INTERP:
+ us += phdp->p_vaddr;
+ break;
+ case PT_LOAD:
+ if (phdp->p_vaddr < minva)
+ minva = phdp->p_vaddr;
+ if (phdp->p_vaddr > maxva)
+ maxva = phdp->p_vaddr + phdp->p_memsz;
next_load = _dl_malloc(sizeof(struct load_list));
next_load->next = load_list;
load_list = next_load;
- next_load->start = (char *)TRUNC_PG(phdp->p_vaddr);
- next_load->size = size;
+ next_load->start = (char *)TRUNC_PG(phdp->p_vaddr) + exe_loff;
+ next_load->size = (phdp->p_vaddr & align) + phdp->p_filesz;
next_load->prot = PFLAGS(phdp->p_flags);
if (phdp->p_flags & 0x08000000) {
-// dump_prelink(phdp->p_vaddr, phdp->p_memsz);
+// dump_prelink(phdp->p_vaddr + exe_loff, phdp->p_memsz);
prebind_load_exe(phdp, exe_obj);
}
+ break;
}
phdp++;
}
exe_obj->load_list = load_list;
exe_obj->obj_flags |= RTLD_GLOBAL;
+ exe_obj->load_size = maxva - minva;
n = _dl_malloc(sizeof *n);
if (n == NULL)
@@ -467,7 +490,7 @@ _dl_boot(const char **argv, char **envp, const long loff, long *dl_data)
ehdr = (Elf_Ehdr *)dl_data[AUX_base];
dyn_obj = _dl_finalize_object(us, dynp,
(Elf_Phdr *)((char *)dl_data[AUX_base] + ehdr->e_phoff),
- ehdr->e_phnum, OBJTYPE_LDR, dl_data[AUX_base], loff);
+ ehdr->e_phnum, OBJTYPE_LDR, dl_data[AUX_base], dyn_loff);
_dl_add_object(dyn_obj);
dyn_obj->refcount++;
@@ -526,7 +549,7 @@ _dl_boot(const char **argv, char **envp, const long loff, long *dl_data)
debug_map->r_map = (struct link_map *)_dl_objects;
debug_map->r_brk = (Elf_Addr)_dl_debug_state;
debug_map->r_state = RT_CONSISTENT;
- debug_map->r_ldbase = loff;
+ debug_map->r_ldbase = dyn_loff;
_dl_debug_map = debug_map;
*map_link = _dl_debug_map;
}
@@ -604,7 +627,7 @@ _dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynamicp)
/*
* Zero out dl_data.
*/
- for (n = 0; n < AUX_entry; n++)
+ for (n = 0; n <= AUX_entry; n++)
dl_data[n] = 0;
/*
@@ -617,7 +640,7 @@ _dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynamicp)
continue;
dl_data[auxstack->au_id] = auxstack->au_v;
}
- loff = dl_data[AUX_base]; /* XXX assumes linked at 0x0 */
+ loff = dl_data[AUX_base]; /* XXX assumes ld.so is linked at 0x0 */
/*
* We need to do 'selfreloc' in case the code weren't