Enable parsing and mapping of hardware dependent libraries in ld.so.conf
To be documented in the man page.
This commit is contained in:
parent
d6f355c744
commit
ea816c78b2
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue