diff options
| author | christos <christos@NetBSD.org> | 1999-12-13 09:09:34 +0000 |
|---|---|---|
| committer | christos <christos@NetBSD.org> | 1999-12-13 09:09:34 +0000 |
| commit | ea816c78b2115aa79e9442b3c3d8cd78fb6f454d (patch) | |
| tree | 69a581cfbd54f0dff3b107b2af72f0f5c606a697 /libexec | |
| parent | d6f355c744d925ceb5b59548f173a1b1128ca9e9 (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.c | 109 | ||||
| -rw-r--r-- | libexec/ld.elf_so/paths.c | 171 | ||||
| -rw-r--r-- | libexec/ld.elf_so/rtld.c | 15 | ||||
| -rw-r--r-- | libexec/ld.elf_so/rtld.h | 22 |
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)); |
