aboutsummaryrefslogtreecommitdiff
path: root/libshouldbeinlibc/wire.c
diff options
context:
space:
mode:
Diffstat (limited to 'libshouldbeinlibc/wire.c')
-rw-r--r--libshouldbeinlibc/wire.c65
1 files changed, 46 insertions, 19 deletions
diff --git a/libshouldbeinlibc/wire.c b/libshouldbeinlibc/wire.c
index 7be04dee..bafc9599 100644
--- a/libshouldbeinlibc/wire.c
+++ b/libshouldbeinlibc/wire.c
@@ -1,5 +1,5 @@
/* Function to wire down text and data (including from shared libraries)
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996,99,2000,01,02 Free Software Foundation, Inc.
Written by Michael I. Bushnell, p/BSG.
This file is part of the GNU Hurd.
@@ -20,14 +20,28 @@
#include <link.h>
+#include <dlfcn.h>
#include <mach.h>
#include <hurd.h>
+#include <error.h>
+
+#pragma weak _DYNAMIC
+#pragma weak dlopen
+#pragma weak dlclose
+#pragma weak dlerror
+#pragma weak dlsym
+#ifndef RTLD_NOLOAD
+#define RTLD_NOLOAD 0
+#endif
/* Find the list of shared objects */
static struct link_map *
loaded (void)
{
- Elf32_Dyn *d;
+ ElfW(Dyn) *d;
+
+ if (&_DYNAMIC == 0) /* statically linked */
+ return 0;
for (d = _DYNAMIC; d->d_tag != DT_NULL; ++d)
if (d->d_tag == DT_DEBUG)
@@ -40,13 +54,27 @@ loaded (void)
}
/* Compute the extent of a particular shared object. */
-static Elf32_Addr
+static ElfW(Addr)
map_extent (struct link_map *map)
{
- /* Find the last load cmd; they are in ascending p_vaddr order. */
- Elf32_Word n = map->l_phnum;
- while (n-- > 0 && map->l_phdr[n].p_type != PT_LOAD);
- return map->l_phdr[n].p_vaddr + map->l_phdr[n].p_filesz;
+ /* In fact, LIB == MAP, but doing it this way makes it entirely kosher. */
+ void *lib = dlopen (map->l_name, RTLD_NOLOAD);
+ if (lib == 0)
+ {
+ error (2, 0, "cannot dlopen %s: %s", map->l_name, dlerror ());
+ /* NOTREACHED */
+ return 0;
+ }
+ else
+ {
+ /* Find the _end symbol's runtime address and subtract the load base. */
+ void *end = dlsym (lib, "_end");
+ if (end == 0)
+ error (2, 0, "cannot wire library %s with no _end symbol: %s",
+ map->l_name, dlerror ());
+ dlclose (lib);
+ return (ElfW(Addr)) end - map->l_addr;
+ }
}
/* Wire down all memory currently allocated at START for LEN bytes;
@@ -70,7 +98,7 @@ wire_segment_internal (vm_address_t start,
do
{
addr = start;
- err = vm_region (mach_task_self (), &addr, &size, &protection,
+ err = vm_region (mach_task_self (), &addr, &size, &protection,
&max_protection, &inheritance, &shared, &object_name,
&offset);
if (err)
@@ -80,25 +108,25 @@ wire_segment_internal (vm_address_t start,
extends beyond the LEN, prune it. */
if (addr + size > start + len)
size = len - (addr - start);
-
+
/* Set protection to allow all access possible */
vm_protect (mach_task_self (), addr, size, 0, max_protection);
-
+
/* Generate write faults */
- for (poke = (char *) addr;
- (vm_address_t) poke < addr + size;
+ for (poke = (char *) addr;
+ (vm_address_t) poke < addr + size;
poke += vm_page_size)
*poke = *poke;
/* Wire pages */
vm_wire (host_priv, mach_task_self (), addr, size, max_protection);
-
+
/* Set protection back to what it was */
vm_protect (mach_task_self (), addr, size, 0, protection);
mach_port_deallocate (mach_task_self (), object_name);
-
+
len -= (addr - start) + size;
start = addr + size;
}
@@ -112,7 +140,7 @@ wire_segment (vm_address_t start,
{
mach_port_t host, device;
error_t error;
-
+
error = get_privileged_ports (&host, &device);
if (!error)
{
@@ -132,17 +160,17 @@ wire_task_self ()
mach_port_t host, device;
error_t error;
extern char _edata, _etext, __data_start;
-
+
error = get_privileged_ports (&host, &device);
if (error)
return;
-
+
map = loaded ();
if (!map)
{
extern void _start ();
vm_address_t text_start = (vm_address_t) &_start;
- wire_segment_internal (text_start,
+ wire_segment_internal (text_start,
(vm_size_t) (&_etext - text_start),
host);
wire_segment_internal ((vm_address_t) &__data_start,
@@ -156,4 +184,3 @@ wire_task_self ()
mach_port_deallocate (mach_task_self (), host);
mach_port_deallocate (mach_task_self (), device);
}
-