summaryrefslogtreecommitdiff
path: root/libexec
diff options
context:
space:
mode:
authorchristos <christos@NetBSD.org>1999-12-13 09:09:34 +0000
committerchristos <christos@NetBSD.org>1999-12-13 09:09:34 +0000
commitea816c78b2115aa79e9442b3c3d8cd78fb6f454d (patch)
tree69a581cfbd54f0dff3b107b2af72f0f5c606a697 /libexec
parentd6f355c744d925ceb5b59548f173a1b1128ca9e9 (diff)
Enable parsing and mapping of hardware dependent libraries in ld.so.conf
To be documented in the man page.
Diffstat (limited to 'libexec')
-rw-r--r--libexec/ld.elf_so/load.c109
-rw-r--r--libexec/ld.elf_so/paths.c171
-rw-r--r--libexec/ld.elf_so/rtld.c15
-rw-r--r--libexec/ld.elf_so/rtld.h22
4 files changed, 290 insertions, 27 deletions
diff --git a/libexec/ld.elf_so/load.c b/libexec/ld.elf_so/load.c
index 6269088b887..bdca3e63db6 100644
--- a/libexec/ld.elf_so/load.c
+++ b/libexec/ld.elf_so/load.c
@@ -1,4 +1,4 @@
-/* $NetBSD: load.c,v 1.5 1999/11/07 00:21:12 mycroft Exp $ */
+/* $NetBSD: load.c,v 1.6 1999/12/13 09:09:34 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -46,12 +46,16 @@
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
+#include <sys/param.h>
#include <sys/mman.h>
+#include <sys/sysctl.h>
#include <dirent.h>
#include "debug.h"
#include "rtld.h"
+static Obj_Entry *_rtld_load_by_name __P((const char *, Obj_Entry *, bool));
+
/*
* Load a shared object into memory, if it is not already loaded. The
* argument must be a string allocated on the heap. This function assumes
@@ -128,14 +132,103 @@ _rtld_load_object(filepath, dodebug)
return obj;
}
+static Obj_Entry *
+_rtld_load_by_name(name, obj, dodebug)
+ const char *name;
+ Obj_Entry *obj;
+ bool dodebug;
+{
+ Library_Xform *x = _rtld_xforms;
+ Obj_Entry *o = NULL;
+ size_t i, j;
+ int ctlname[2];
+ char *libpath;
+ union {
+ int i;
+ char s[16];
+ } val;
+
+ ctlname[0] = CTL_MACHDEP;
+ if (dodebug)
+ dbg(("load by name %s %p", name, x));
+ for (; x; x = x->next) {
+ if (strcmp(x->name, name) != 0)
+ continue;
+
+ ctlname[1] = x->ctl;
+
+ i = sizeof(val);
+
+ if (sysctl(ctlname, 2, &val, &i, NULL, 0) == -1) {
+ warn("sysctl");
+ break;
+ }
+
+ switch (x->ctltype) {
+ case CTLTYPE_INT:
+ xsnprintf(val.s, sizeof(val.s), "%d", val.i);
+ break;
+ case CTLTYPE_STRING:
+ break;
+ default:
+ warnx("unsupport sysctl type %d", x->ctltype);
+ break;
+ }
+
+ if (dodebug)
+ dbg(("sysctl returns %s", val.s));
+
+ for (i = 0; i < RTLD_MAX_ENTRY && x->entry[i].value != NULL;
+ i++) {
+ if (dodebug)
+ dbg(("entry %d", i));
+ if (strcmp(x->entry[i].value, val.s) == 0)
+ break;
+ }
+
+ if (i == RTLD_MAX_ENTRY) {
+ warnx("sysctl value %s not found for lib%s",
+ val.s, name);
+ break;
+ }
+ /* XXX: This can mess up debuggers, cause we lie about
+ * what we loaded in the needed objects */
+ for (j = 0; j < RTLD_MAX_LIBRARY &&
+ x->entry[i].library[j] != NULL; j++) {
+ libpath = _rtld_find_library(
+ x->entry[i].library[j], obj);
+ if (libpath == NULL) {
+ warnx("could not load lib%s for lib%s",
+ x->entry[i].library[j], name);
+ continue;
+ }
+ o = _rtld_load_object(libpath, true);
+ if (o == NULL)
+ continue;
+ }
+
+ }
+
+ if (o != NULL)
+ return o;
+
+ libpath = _rtld_find_library(name, obj);
+ if (libpath == NULL)
+ return NULL;
+ return _rtld_load_object(libpath, true);
+
+}
+
+
/*
* Given a shared object, traverse its list of needed objects, and load
* each of them. Returns 0 on success. Generates an error message and
* returns -1 on failure.
*/
int
-_rtld_load_needed_objects(first)
+_rtld_load_needed_objects(first, dodebug)
Obj_Entry *first;
+ bool dodebug;
{
Obj_Entry *obj;
int status = 0;
@@ -146,15 +239,9 @@ _rtld_load_needed_objects(first)
for (needed = obj->needed; needed != NULL;
needed = needed->next) {
const char *name = obj->strtab + needed->name;
- char *libpath = _rtld_find_library(name, obj);
-
- if (libpath == NULL) {
- status = -1;
- } else {
- needed->obj = _rtld_load_object(libpath, true);
- if (needed->obj == NULL)
- status = -1; /* FIXME - cleanup */
- }
+ needed->obj = _rtld_load_by_name(name, obj, dodebug);
+ if (needed->obj == NULL)
+ status = -1; /* FIXME - cleanup */
#ifdef RTLD_LOADER
if (status == -1)
return status;
diff --git a/libexec/ld.elf_so/paths.c b/libexec/ld.elf_so/paths.c
index e27024f28de..6e40b908309 100644
--- a/libexec/ld.elf_so/paths.c
+++ b/libexec/ld.elf_so/paths.c
@@ -1,4 +1,4 @@
-/* $NetBSD: paths.c,v 1.6 1999/08/20 21:10:27 christos Exp $ */
+/* $NetBSD: paths.c,v 1.7 1999/12/13 09:09:34 christos Exp $ */
/*
* Copyright 1996 Matt Thomas <matt@3am-software.com>
@@ -37,9 +37,18 @@
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
-#include <dirent.h>
+#include <sys/gmon.h>
+#include <sys/sysctl.h>
+#include <sys/socket.h>
+#include <sys/mount.h>
+#include <sys/mbuf.h>
+#include <sys/resource.h>
+#include <vm/vm_param.h>
+#include <machine/cpu.h>
#include "debug.h"
#include "rtld.h"
@@ -47,6 +56,7 @@
static Search_Path *_rtld_find_path __P((Search_Path *, const char *, size_t));
static Search_Path **_rtld_append_path __P((Search_Path **, Search_Path **,
const char *, const char *, bool));
+static void _rtld_process_mapping __P((Library_Xform **, char *, bool));
static Search_Path *
_rtld_find_path(path, pathstr, pathlen)
@@ -127,9 +137,136 @@ _rtld_add_paths(path_p, pathstr, dodebug)
}
}
+
+static struct {
+ const char *name;
+ int type;
+} ctl_machdep[] = CTL_MACHDEP_NAMES;
+
+#define CTL_MACHDEP_SIZE (sizeof(ctl_machdep) / sizeof(ctl_machdep[0]))
+
+/*
+ * Process library mappings of the form:
+ * <library_name> <machdep_variable> <value,...:library_name,...> ...
+ */
+static void
+_rtld_process_mapping(lib_p, bp, dodebug)
+ Library_Xform **lib_p;
+ char *bp;
+ bool dodebug;
+{
+ static const char WS[] = " \t\n";
+ Library_Xform *hwptr = NULL;
+ char *ptr, *key, *lib, *l;
+ int i, j;
+
+ if (dodebug)
+ dbg((" processing mapping \"%s\"", bp));
+
+ if ((ptr = strsep(&bp, WS)) == NULL)
+ return;
+
+ if (dodebug)
+ dbg((" library \"%s\"", ptr));
+
+ hwptr = xmalloc(sizeof(*hwptr));
+ memset(hwptr, 0, sizeof(*hwptr));
+ hwptr->name = xstrdup(ptr);
+
+ if ((ptr = strsep(&bp, WS)) == NULL) {
+ warnx("missing sysctl variable name");
+ goto cleanup;
+ }
+
+ if (dodebug)
+ dbg((" sysctl \"%s\"", ptr));
+
+ for (i = 1; i < CTL_MACHDEP_SIZE; i++)
+ if (strcmp(ctl_machdep[i].name, ptr) == 0)
+ break;
+
+ if (i == CTL_MACHDEP_SIZE) {
+ warnx("unknown sysctl variable name `%s'", ptr);
+ goto cleanup;
+ }
+
+ hwptr->ctl = i;
+ hwptr->ctltype = ctl_machdep[i].type;
+ if (dodebug)
+ dbg((" sysctl \"%d\"", i));
+
+ for (i = 0; (ptr = strsep(&bp, WS)) != NULL; i++) {
+ if (i == RTLD_MAX_ENTRY) {
+no_more:
+ warnx("maximum library entries exceeded `%s'",
+ hwptr->name);
+ goto cleanup;
+ }
+ if ((key = strsep(&ptr, ":")) == NULL) {
+ warnx("missing sysctl variable value for `%s'",
+ hwptr->name);
+ goto cleanup;
+ }
+ if ((lib = strsep(&ptr, ":")) == NULL) {
+ warnx("missing sysctl library list for `%s'",
+ hwptr->name);
+ goto cleanup;
+ }
+ for (j = 0; (l = strsep(&lib, ",")) != NULL; j++) {
+ if (j == RTLD_MAX_LIBRARY) {
+ warnx("maximum library entries exceeded `%s'",
+ hwptr->name);
+ goto cleanup;
+ }
+ if (dodebug)
+ dbg((" library \"%s\"", l));
+ hwptr->entry[i].library[j] = xstrdup(l);
+ }
+ if (j == 0) {
+ warnx("No library map entries for `%s/%s'",
+ hwptr->name, ptr);
+ goto cleanup;
+ }
+ j = i;
+ for (; (l = strsep(&key, ",")) != NULL; i++) {
+ if (dodebug)
+ dbg((" key \"%s\"", l));
+ if (i == RTLD_MAX_ENTRY)
+ goto no_more;
+ if (i != j)
+ (void)memcpy(hwptr->entry[i].library,
+ hwptr->entry[j].library,
+ sizeof(hwptr->entry[j].library));
+ hwptr->entry[i].value = xstrdup(l);
+ }
+
+ if (j != i)
+ i--;
+ }
+
+ if (i == 0) {
+ warnx("No library entries for `%s'", hwptr->name);
+ goto cleanup;
+ }
+
+
+ hwptr->next = NULL;
+ if (*lib_p != NULL)
+ (*lib_p)->next = hwptr;
+ *lib_p = hwptr;
+
+ return;
+
+cleanup:
+ if (hwptr->name)
+ free(hwptr->name);
+ free(hwptr);
+}
+
void
-_rtld_process_hints(path_p, fname, dodebug)
+_rtld_process_hints(path_p, lib_p, fname, dodebug)
Search_Path **path_p;
+ Library_Xform **lib_p;
const char *fname;
bool dodebug;
{
@@ -138,6 +275,7 @@ _rtld_process_hints(path_p, fname, dodebug)
struct stat st;
size_t sz;
Search_Path **head_p = path_p;
+ int doing_path = 0;
if ((fd = open(fname, O_RDONLY)) == -1) {
/* Don't complain */
@@ -169,6 +307,11 @@ _rtld_process_hints(path_p, fname, dodebug)
b = p;
switch (*p) {
+ case '/':
+ if (b == p)
+ doing_path = 1;
+ break;
+
case ' ': case '\t':
if (b == p)
b++;
@@ -176,8 +319,11 @@ _rtld_process_hints(path_p, fname, dodebug)
case '\n':
*p = '\0';
- path_p = _rtld_append_path(head_p, path_p, b, p,
- dodebug);
+ if (doing_path)
+ path_p = _rtld_append_path(head_p, path_p, b, p,
+ dodebug);
+ else
+ _rtld_process_mapping(lib_p, b, dodebug);
b = NULL;
break;
@@ -188,19 +334,28 @@ _rtld_process_hints(path_p, fname, dodebug)
*sp == '\t'; --sp)
continue;
*++sp = '\0';
- path_p = _rtld_append_path(head_p, path_p, b,
- sp, dodebug);
+ if (doing_path)
+ path_p = _rtld_append_path(head_p,
+ path_p, b, sp, dodebug);
+ else
+ _rtld_process_mapping(lib_p, b,
+ dodebug);
*sp = ' ';
}
b = NULL;
break;
default:
+ if (b == p)
+ doing_path = 0;
break;
}
}
- path_p = _rtld_append_path(head_p, path_p, b, ebuf, dodebug);
+ if (doing_path)
+ path_p = _rtld_append_path(head_p, path_p, b, ebuf, dodebug);
+ else
+ _rtld_process_mapping(lib_p, b, dodebug);
(void)munmap(buf, sz);
}
diff --git a/libexec/ld.elf_so/rtld.c b/libexec/ld.elf_so/rtld.c
index 6fa55fc6f00..333b1aa88e2 100644
--- a/libexec/ld.elf_so/rtld.c
+++ b/libexec/ld.elf_so/rtld.c
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld.c,v 1.27 1999/11/10 18:48:19 thorpej Exp $ */
+/* $NetBSD: rtld.c,v 1.28 1999/12/13 09:09:34 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -101,6 +101,9 @@ Objlist _rtld_list_main = /* Objects loaded at program startup */
Search_Path *_rtld_default_paths;
Search_Path *_rtld_paths;
+
+Library_Xform *_rtld_xforms;
+
/*
* Global declarations normally provided by crt0.
*/
@@ -370,7 +373,7 @@ _rtld(sp)
#endif
_rtld_add_paths(&_rtld_paths, getenv("LD_LIBRARY_PATH"), true);
}
- _rtld_process_hints(&_rtld_paths, _PATH_LD_HINTS, true);
+ _rtld_process_hints(&_rtld_paths, &_rtld_xforms, _PATH_LD_HINTS, true);
dbg(("%s is initialized, base address = %p", __progname,
(void *) pAUX_base->a_v));
@@ -440,7 +443,7 @@ _rtld(sp)
_rtld_die();
dbg(("loading needed objects"));
- if (_rtld_load_needed_objects(_rtld_objmain) == -1)
+ if (_rtld_load_needed_objects(_rtld_objmain, true) == -1)
_rtld_die();
for (obj = _rtld_objlist; obj != NULL; obj = obj->next)
@@ -668,8 +671,10 @@ _rtld_dlopen(name, mode)
if (*old_obj_tail != NULL) { /* We loaded something new. */
assert(*old_obj_tail == obj);
- if (_rtld_load_needed_objects(obj) == -1 || (_rtld_init_dag(obj),
- _rtld_relocate_objects(obj, ((mode & 3) == RTLD_NOW), true)) == -1) {
+ if (_rtld_load_needed_objects(obj, true) == -1 ||
+ (_rtld_init_dag(obj),
+ _rtld_relocate_objects(obj,
+ ((mode & 3) == RTLD_NOW), true)) == -1) {
_rtld_unload_object(obj, false);
obj->dl_refcount--;
obj = NULL;
diff --git a/libexec/ld.elf_so/rtld.h b/libexec/ld.elf_so/rtld.h
index a53e682b543..6a520bce5ba 100644
--- a/libexec/ld.elf_so/rtld.h
+++ b/libexec/ld.elf_so/rtld.h
@@ -1,4 +1,4 @@
-/* $NetBSD: rtld.h,v 1.20 1999/12/05 18:36:25 fredb Exp $ */
+/* $NetBSD: rtld.h,v 1.21 1999/12/13 09:09:35 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -110,6 +110,20 @@ typedef struct _rtld_search_path_t {
size_t sp_pathlen;
} Search_Path;
+
+#define RTLD_MAX_ENTRY 10
+#define RTLD_MAX_LIBRARY 4
+typedef struct _rtld_library_xform_t {
+ struct _rtld_library_xform_t *next;
+ char *name;
+ int ctl;
+ int ctltype;
+ struct {
+ char *value;
+ char *library[RTLD_MAX_LIBRARY];
+ } entry[RTLD_MAX_ENTRY];
+} Library_Xform;
+
/*
* Shared object descriptor.
*
@@ -207,6 +221,7 @@ extern Obj_Entry **_rtld_objtail;
extern Obj_Entry *_rtld_objmain;
extern Obj_Entry _rtld_objself;
extern Search_Path *_rtld_paths;
+extern Library_Xform *_rtld_xforms;
extern bool _rtld_trust;
extern const char *_rtld_error_message;
extern unsigned long _rtld_curmark;
@@ -235,12 +250,13 @@ Obj_Entry *_rtld_digest_phdr __P((const Elf_Phdr *, int, caddr_t));
/* load.c */
Obj_Entry *_rtld_load_object __P((char *, bool));
-int _rtld_load_needed_objects __P((Obj_Entry *));
+int _rtld_load_needed_objects __P((Obj_Entry *, bool));
int _rtld_preload __P((const char *, bool));
/* path.c */
void _rtld_add_paths __P((Search_Path **, const char *, bool));
-void _rtld_process_hints __P((Search_Path **, const char *, bool));
+void _rtld_process_hints __P((Search_Path **, Library_Xform **, const char *,
+ bool));
/* reloc.c */
int _rtld_do_copy_relocations __P((const Obj_Entry *, bool));