Permalink
Browse files

Support Solaris-like $ORIGIN etc. expansions in paths.

  • Loading branch information...
christos christos
christos authored and christos committed May 18, 2007
1 parent 318ecbe commit 37c782c48280f61ef3be93ad04956648d6cda166
@@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.78 2007/04/08 09:35:48 scw Exp $
# $NetBSD: Makefile,v 1.79 2007/05/18 21:44:08 christos Exp $
.include <bsd.own.mk> # for OBJECT_FMT definition
.include <bsd.shlib.mk> # for SHLINKINSTALLDIR definition
@@ -34,7 +34,7 @@ LDFLAGS+= -Wl,-static
CLIBOBJ!= cd ${NETBSDSRCDIR}/lib/libc && ${PRINTOBJDIR}
SRCS+= rtld.c reloc.c symbol.c malloc.c xmalloc.c xprintf.c debug.c \
map_object.c load.c search.c headers.c paths.c
map_object.c load.c search.c headers.c paths.c expand.c
BINDIR= ${SHLINKINSTALLDIR}
@@ -0,0 +1,179 @@
/* $NetBSD: expand.c,v 1.1 2007/05/18 21:44:08 christos Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: expand.c,v 1.1 2007/05/18 21:44:08 christos Exp $");
#endif /* not lint */
#include <ctype.h>
#include <string.h>
#include <sys/sysctl.h>
#ifdef DEBUG_EXPAND
#include <stdio.h>
#include <err.h>
#define xwarn warn
size_t _rtld_expand_path(char *, size_t, const char *, const char *,
const char *);
#else
#include <sys/stat.h>
#include "rtld.h"
#endif
static const struct {
const char *name;
size_t namelen;
} bltn[] = {
#define ADD(a) { #a, sizeof(#a) - 1 },
ADD(HWCAP) /* SSE, MMX, etc */
ADD(ISALIST) /* uname -p */
ADD(ORIGIN) /* dirname argv[0] */
ADD(OSNAME) /* uname -s */
ADD(OSREL) /* uname -r */
ADD(PLATFORM) /* uname -m */
};
static int mib[3][2] = {
{ CTL_KERN, KERN_OSTYPE },
{ CTL_KERN, KERN_OSRELEASE },
{ CTL_HW, HW_MACHINE_ARCH },
};
static size_t
expand(char *buf, const char *av, int what, size_t bl)
{
const char *p, *ep;
char *bp = buf;
size_t len;
char name[32];
switch (what) {
case 0: /* HWCAP XXX: Not yet */
case 1: /* ISALIST XXX: Not yet */
return 0;
case 2: /* ORIGIN */
ep = strrchr(p = av, '/');
if (ep == NULL) {
p = ".";
ep = p + 1;
}
break;
case 3: /* OSNAME */
case 4: /* OSREL */
case 5: /* PLATFORM */
len = sizeof(name);
if (sysctl(mib[what - 3], 2, name, &len, NULL, 0) == -1) {
xwarn("sysctl");
return 0;
}
ep = (p = name) + len - 1;
break;
default:
return 0;
}
while (p != ep && bl)
*bp++ = *p++, bl--;
return bp - buf;
}
size_t
_rtld_expand_path(char *buf, size_t bufsize, const char *av, const char *bp,
const char *ep)
{
size_t i, ds = bufsize;
char *dp = buf;
const char *p;
int br;
for (p = bp; p < ep;) {
if (*p == '$') {
br = *++p == '{';
if (br)
p++;
for (i = 0; i < sizeof(bltn) / sizeof(bltn[0]); i++) {
size_t s = bltn[i].namelen;
const char *es = p + s;
if ((br && *es != '}') ||
(!br && (es != ep &&
isalpha((unsigned char)*es))))
continue;
if (strncmp(bltn[i].name, p, s) == 0) {
size_t ls = expand(dp, av, i, ds);
if (ls >= ds)
return bufsize;
ds -= ls;
dp += ls;
p = es + br;
goto done;
}
}
p -= br + 1;
}
*dp++ = *p++;
ds--;
done:;
}
*dp = '\0';
return dp - buf;
}
#ifdef DEBUG_EXPAND
int
main(int argc, char *argv[])
{
char buf[1024];
size_t i;
for (i = 1; i < argc; i++) {
char *p = argv[i], *ep = argv[i] + strlen(p);
size_t n = _rtld_expand_path(buf, sizeof(buf), argv[0], p, ep);
printf("%s\n", buf);
}
return 0;
}
#endif
@@ -1,4 +1,4 @@
/* $NetBSD: headers.c,v 1.20 2005/01/09 12:43:23 simonb Exp $ */
/* $NetBSD: headers.c,v 1.21 2007/05/18 21:44:08 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: headers.c,v 1.20 2005/01/09 12:43:23 simonb Exp $");
__RCSID("$NetBSD: headers.c,v 1.21 2007/05/18 21:44:08 christos Exp $");
#endif /* not lint */
#include <err.h>
@@ -63,7 +63,7 @@ __RCSID("$NetBSD: headers.c,v 1.20 2005/01/09 12:43:23 simonb Exp $");
* information in its Obj_Entry structure.
*/
void
_rtld_digest_dynamic(Obj_Entry *obj)
_rtld_digest_dynamic(const char *argv0, Obj_Entry *obj)
{
Elf_Dyn *dynp;
Needed_Entry **needed_tail = &obj->needed;
@@ -269,7 +269,7 @@ _rtld_digest_dynamic(Obj_Entry *obj)
#endif
if (dyn_rpath != NULL) {
_rtld_add_paths(&obj->rpaths, obj->strtab +
_rtld_add_paths(argv0, &obj->rpaths, obj->strtab +
dyn_rpath->d_un.d_val);
}
}
@@ -1,4 +1,4 @@
.\" $NetBSD: ld.elf_so.1,v 1.8 2003/02/25 10:34:49 wiz Exp $
.\" $NetBSD: ld.elf_so.1,v 1.9 2007/05/18 21:44:08 christos Exp $
.\"
.\" Copyright (c) 2001 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -34,7 +34,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd October 23, 2001
.Dd May 18, 2007
.Dt LD.ELF_SO 1
.Os
.Sh NAME
@@ -104,6 +104,37 @@ The list of default paths which is set to
.Pa /usr/lib .
.El
.Pp
.Nm
will expand the following variables if present in the paths:
.Bl -tag -width $PLATFORM
.It $HWCAP
Processor hardware capabilities, for example FPU, MMX, SSE.
Currently unimplemented.
.It $ISALIST
List of instructions sets this processor can execute.
Currently unimplemented.
.It $ORIGIN
The directory of the main object.
.It $OSNAME
The value of the
.Dv kern.ostype
.Xr sysctl 3 .
.It $OSREL
The value of the
.Dv kern.osrelease
.Xr sysctl 3 .
.It $PLATFORM
The value of the
.Dv hw.machine_arch
.Xr sysctl 3 .
.El
.Pp
Both
.Dv ${VARIABLE}
and
.Dv $VARIABLE
are recognized.
.Pp
The filename string can be considered free form, however, it will almost
always take the form lib\*[Lt]name\*[Gt].so.\*[Lt]number\*[Gt],
where name specifies the
@@ -190,7 +221,12 @@ library location hints supplied by the system administrator.
.Xr dlfcn 3 ,
.Xr elf 5
.Sh HISTORY
.Pp
The ELF shared library model employed first appeared in Sys V R4.
.Pp
The path expansion variables first appeared in Solaris 10, and
in
.Nx 5 .
.Sh SECURITY CONSIDERATIONS
The environment variables
.Ev LD_LIBRARY_PATH
@@ -1,4 +1,4 @@
/* $NetBSD: load.c,v 1.31 2006/03/21 17:48:10 christos Exp $ */
/* $NetBSD: load.c,v 1.32 2007/05/18 21:44:08 christos Exp $ */
/*
* Copyright 1996 John D. Polstra.
@@ -40,7 +40,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: load.c,v 1.31 2006/03/21 17:48:10 christos Exp $");
__RCSID("$NetBSD: load.c,v 1.32 2007/05/18 21:44:08 christos Exp $");
#endif /* not lint */
#include <err.h>
@@ -137,11 +137,20 @@ _rtld_load_object(const char *filepath, int mode)
}
if (obj == NULL) { /* First use of this object, so we must map it in */
char *p, pathname[MAXPATHLEN];
const char *q;
obj = _rtld_map_object(filepath, fd, &sb);
(void)close(fd);
if (obj == NULL)
return NULL;
_rtld_digest_dynamic(obj);
(void)strlcpy(pathname, filepath, sizeof(pathname));
if ((p = strrchr(q = pathname, '/')) != NULL)
*p = '\0';
else
q = ".";
_rtld_digest_dynamic(q, obj);
*_rtld_objtail = obj;
_rtld_objtail = &obj->next;
Oops, something went wrong.

0 comments on commit 37c782c

Please sign in to comment.