Enable parsing and mapping of hardware dependent libraries in ld.so.conf

To be documented in the man page.
This commit is contained in:
christos 1999-12-13 09:09:34 +00:00
parent d6f355c744
commit ea816c78b2
4 changed files with 290 additions and 27 deletions

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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));