* Versions.def (ld.so): Add GLIBC_2.1.1.
	* elf/Makefile (routines): Add dl-origin.
	(tests): Add origtest.  Add dependencies for the program.
	* elf/Versions (ld.so) [GLIBC_2.1.1]: Add _dl_origin_path,
	_dl_platformlen, _dl_dst_count and _dl_dst_substitute.
	* elf/dl-deps.c (expand_dst): New macro.  Expand DSTs in filename.
	(_dl_map_object_deps): Use expand_dst to expand DSTs in DT_NEEDED,
	DT_AUXILIARY, and DT_FILTER filenames.
	* elf/dl-load.c (expand_dynamic_string_token): Explode into
	two functions and three macros.
	(_dl_dst_count, _dl_dst_substitute): New functions.
	* elf/dl-dst.h: New file.
	* elf/dl-open.c (_dl_open): Take extra parameter with address of
	caller.  Pass address in args structure.
	(dl_open_worker): Recognize and expand DSTs in filename.
	* elf/ldsodefs.h (_dl_open): Adapt prototype.
	* elf/dlopen.c (dlopen_doit): Pass caller address to _dl_open.
	(__dlopen_check): Pass caller address to dlopen_doit in args.
	* elf/dlopendoit.c: Likewise.
	* iconv/gconv_dl.c: Adapt call of _dl_open.
	* nss/nsswitch.c: Likewise.
	* elf/origtest.c: New file.
	* sysdeps/generic/dl-origin.h: Moved to...
	* sysdeps/generic/dl-origin.c: ...here.
	* sysdeps/unix/sysv/linux/dl-origin.h: Moved to...
	* sysdeps/unix/sysv/linux/dl-origin.c: ...here.
This commit is contained in:
Ulrich Drepper 1999-05-05 23:29:18 +00:00
parent 4f8dbcb126
commit dc5efe83c0
16 changed files with 409 additions and 128 deletions

View file

@ -1,5 +1,32 @@
1999-05-05 Ulrich Drepper <drepper@cygnus.com>
* Versions.def (ld.so): Add GLIBC_2.1.1.
* elf/Makefile (routines): Add dl-origin.
(tests): Add origtest. Add dependencies for the program.
* elf/Versions (ld.so) [GLIBC_2.1.1]: Add _dl_origin_path,
_dl_platformlen, _dl_dst_count and _dl_dst_substitute.
* elf/dl-deps.c (expand_dst): New macro. Expand DSTs in filename.
(_dl_map_object_deps): Use expand_dst to expand DSTs in DT_NEEDED,
DT_AUXILIARY, and DT_FILTER filenames.
* elf/dl-load.c (expand_dynamic_string_token): Explode into
two functions and three macros.
(_dl_dst_count, _dl_dst_substitute): New functions.
* elf/dl-dst.h: New file.
* elf/dl-open.c (_dl_open): Take extra parameter with address of
caller. Pass address in args structure.
(dl_open_worker): Recognize and expand DSTs in filename.
* elf/ldsodefs.h (_dl_open): Adapt prototype.
* elf/dlopen.c (dlopen_doit): Pass caller address to _dl_open.
(__dlopen_check): Pass caller address to dlopen_doit in args.
* elf/dlopendoit.c: Likewise.
* iconv/gconv_dl.c: Adapt call of _dl_open.
* nss/nsswitch.c: Likewise.
* elf/origtest.c: New file.
* sysdeps/generic/dl-origin.h: Moved to...
* sysdeps/generic/dl-origin.c: ...here.
* sysdeps/unix/sysv/linux/dl-origin.h: Moved to...
* sysdeps/unix/sysv/linux/dl-origin.c: ...here.
* stdio-common/_itoa.c (_itoa): Fix special 32bit platform case
with specific bases and only few bits set in second word.

View file

@ -72,4 +72,5 @@ libdb1 {
ld.so {
GLIBC_2.0
GLIBC_2.1 GLIBC_2.0
GLIBC_2.1.1 GLIBC_2.1
}

View file

@ -22,7 +22,7 @@ subdir := elf
headers = elf.h bits/elfclass.h bits/dlfcn.h link.h dlfcn.h
routines = $(dl-routines) dl-open dl-close dl-symbol dl-support \
dl-addr enbl-secure dl-profstub
dl-addr enbl-secure dl-profstub dl-origin
# The core dynamic linking functions are in libc for the static and
# profiled libraries.
@ -78,7 +78,7 @@ install-rootsbin += ldconfig
endif
ifeq (yes,$(build-shared))
tests = loadtest restest1 preloadtest loadfail multiload
tests = loadtest restest1 preloadtest loadfail multiload origtest
endif
modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
testobj1_1 failobj
@ -253,6 +253,9 @@ LDFLAGS-multiload = -rdynamic
CFLAGS-multiload.c = -DOBJDIR=\"$(elf-objpfx)\"
$(objpfx)multiload.out: $(objpfx)testobj1.so
$(objpfx)origtest: $(libdl)
$(objpfx)origtest.out: $(objpfx)testobj1.so
# muwahaha

View file

@ -37,6 +37,13 @@ ld.so {
# functions used in other libraries
_dl_mcount; _dl_unload_cache;
}
GLIBC_2.1.1 {
# global variables
_dl_origin_path; _dl_platformlen;
# functions used in other libraries
_dl_dst_count; _dl_dst_substitute;
}
}
libdl {

View file

@ -17,13 +17,15 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <assert.h>
#include <dlfcn.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include <elf/ldsodefs.h>
#include <assert.h>
#include <dl-dst.h>
/* Whether an shared object references one or more auxiliary objects
is signaled by the AUXTAG entry in l_info. */
@ -39,6 +41,7 @@
reset if in _dl_close if the last global object is removed. */
size_t _dl_global_scope_alloc;
extern size_t _dl_platformlen;
/* When loading auxiliary objects we must ignore errors. It's ok if
an object is missing. */
@ -48,7 +51,7 @@ struct openaux_args
struct link_map *map;
int trace_mode;
const char *strtab;
const ElfW(Dyn) *d;
const char *name;
/* The return value of openaux. */
struct link_map *aux;
@ -59,7 +62,7 @@ openaux (void *a)
{
struct openaux_args *args = (struct openaux_args *) a;
args->aux = _dl_map_object (args->map, args->strtab + args->d->d_un.d_val, 0,
args->aux = _dl_map_object (args->map, args->name, 0,
(args->map->l_type == lt_executable
? lt_library : args->map->l_type),
args->trace_mode);
@ -84,6 +87,43 @@ struct list
};
/* Macro to expand DST. It is an macro since we use `alloca'. */
#define expand_dst(l, str, fatal) \
({ \
const char *__str = (str); \
const char *__result = __str; \
size_t __cnt = DL_DST_COUNT(__str, 0); \
\
if (__cnt != 0) \
{ \
char *__newp = (char *) alloca (DL_DST_REQUIRED (l, __str, \
strlen (__str), \
__cnt)); \
\
__result = DL_DST_SUBSTITUTE (l, __str, __newp, 0); \
\
if (*__result == '\0') \
{ \
/* The replacement for the DST is not known. We can't \
processed. */ \
if (fatal) \
_dl_signal_error (0, __str, \
"empty dynamics string token substitution"); \
else \
{ \
/* This is for DT_AUXILIARY. */ \
if (_dl_debug_libs) \
_dl_debug_message (1, "cannot load auxiliary `", __str, \
"' because of empty dynamic string" \
" token substitution\n", NULL); \
continue; \
} \
} \
} \
\
__result; })
unsigned int
internal_function
_dl_map_object_deps (struct link_map *map,
@ -166,14 +206,21 @@ _dl_map_object_deps (struct link_map *map,
if (__builtin_expect (d->d_tag, DT_NEEDED) == DT_NEEDED)
{
/* Map in the needed object. */
struct link_map *dep
= _dl_map_object (l, strtab + d->d_un.d_val, 0,
l->l_type == lt_executable ? lt_library :
l->l_type, trace_mode);
struct link_map *dep;
/* Allocate new entry. */
struct list *newp = alloca (sizeof (struct list));
struct list *newp;
/* Object name. */
const char *name;
/* Recognize DSTs. */
name = expand_dst (l, strtab + d->d_un.d_val, 0);
dep = _dl_map_object (l, name, 0,
l->l_type == lt_executable ? lt_library :
l->l_type, trace_mode);
/* Add it in any case to the duplicate list. */
newp = alloca (sizeof (struct list));
newp->map = dep;
newp->dup = NULL;
dtail->dup = newp;
@ -202,17 +249,22 @@ _dl_map_object_deps (struct link_map *map,
{
char *errstring;
struct list *newp;
/* Object name. */
const char *name;
/* Recognize DSTs. */
name = expand_dst (l, strtab + d->d_un.d_val,
d->d_tag == DT_AUXILIARY);
if (d->d_tag == DT_AUXILIARY)
{
/* Store the tag in the argument structure. */
args.d = d;
args.name = name;
/* Say that we are about to load an auxiliary library. */
if (_dl_debug_libs)
_dl_debug_message (1, "load auxiliary object=",
strtab + d->d_un.d_val,
" requested by file=",
name, " requested by file=",
l->l_name[0]
? l->l_name : _dl_argv[0],
"\n", NULL);
@ -233,15 +285,14 @@ _dl_map_object_deps (struct link_map *map,
{
/* Say that we are about to load an auxiliary library. */
if (_dl_debug_libs)
_dl_debug_message (1, "load filtered object=",
strtab + d->d_un.d_val,
_dl_debug_message (1, "load filtered object=", name,
" requested by file=",
l->l_name[0]
? l->l_name : _dl_argv[0],
"\n", NULL);
/* For filter objects the dependency must be available. */
args.aux = _dl_map_object (l, strtab + d->d_un.d_val, 0,
args.aux = _dl_map_object (l, name, 0,
(l->l_type == lt_executable
? lt_library : l->l_type),
trace_mode);

72
elf/dl-dst.h Normal file
View file

@ -0,0 +1,72 @@
/* Handling of dynamic sring tokens.
Copyright (C) 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Determine the number of DST elements in the name. Only if IS_PATH is
nonzero paths are recognized (i.e., multiple, ':' separated filenames). */
#define DL_DST_COUNT(name, is_path) \
({ \
size_t __cnt = 0; \
const char *__sf = strchr (name, '$'); \
\
if (__sf != NULL) \
__cnt = _dl_dst_count (__sf, is_path); \
\
__cnt; })
/* Prototype for used function. */
extern size_t _dl_dst_count (const char *name, int is_path);
/* Guess from the number of DSTs the length of the restul string. */
#define DL_DST_REQUIRED(l, name, len, cnt) \
({ \
size_t origin_len; \
size_t __len = (len); \
\
/* Now we make a guess how many extra characters on top of the length \
of S we need to represent the result. We know that we have CNT \
replacements. Each at most can use \
MAX (strlen (ORIGIN), strlen (_dl_platform)) \
minus 7 (which is the length of "$ORIGIN"). \
\
First get the origin string if it is not available yet. This can \
only happen for the map of the executable. */ \
if ((l)->l_origin == NULL) \
{ \
assert ((l)->l_name[0] == '\0'); \
(l)->l_origin = _dl_get_origin (); \
origin_len = ((l)->l_origin && (l)->l_origin != (char *) -1 \
? strlen ((l)->l_origin) : 0); \
} \
else \
origin_len = (l)->l_origin == (char *) -1 ? 0 : strlen ((l)->l_origin); \
\
__len + cnt * (MAX (origin_len, _dl_platformlen) - 7); })
/* Find origin of the executable. */
extern const char *_dl_get_origin (void);
/* Perform the DST substitution. */
#define DL_DST_SUBSTITUTE(l, name, res, is_path) \
_dl_dst_substitute (l, name, res, is_path)
/* Prototype for used function. */
extern char *_dl_dst_substitute (struct link_map *l, const char *name,
char *result, int is_path);

View file

@ -31,8 +31,7 @@
#include "dynamic-link.h"
#include <stdio-common/_itoa.h>
#include <dl-origin.h>
#include <dl-dst.h>
/* On some systems, no flag bits are given to specify file mapping. */
#ifndef MAP_FILE
@ -146,6 +145,104 @@ local_strdup (const char *s)
return (char *) memcpy (new, s, len);
}
size_t
_dl_dst_count (const char *name, int is_path)
{
size_t cnt = 0;
do
{
size_t len = 1;
/* $ORIGIN is not expanded for SUID/GUID programs. */
if ((((!__libc_enable_secure
&& strncmp (&name[1], "ORIGIN", 6) == 0 && (len = 7) != 0)
|| (strncmp (&name[1], "PLATFORM", 8) == 0 && (len = 9) != 0))
&& (name[len] == '\0' || name[len] == '/'
|| (is_path && name[len] == ':')))
|| (name[1] == '{'
&& ((!__libc_enable_secure
&& strncmp (&name[2], "ORIGIN}", 7) == 0 && (len = 9) != 0)
|| (strncmp (&name[2], "PLATFORM}", 9) == 0
&& (len = 11) != 0))))
++cnt;
name = strchr (name + len, '$');
}
while (name != NULL);
return cnt;
}
char *
_dl_dst_substitute (struct link_map *l, const char *name, char *result,
int is_path)
{
char *last_elem, *wp;
/* Now fill the result path. While copying over the string we keep
track of the start of the last path element. When we come accross
a DST we copy over the value or (if the value is not available)
leave the entire path element out. */
last_elem = wp = result;
do
{
if (*name == '$')
{
const char *repl;
size_t len;
if ((((strncmp (&name[1], "ORIGIN", 6) == 0 && (len = 7) != 0)
|| (strncmp (&name[1], "PLATFORM", 8) == 0 && (len = 9) != 0))
&& (name[len] == '\0' || name[len] == '/'
|| (is_path && name[len] == ':')))
|| (name[1] == '{'
&& ((strncmp (&name[2], "ORIGIN}", 7) == 0 && (len = 9) != 0)
|| (strncmp (&name[2], "PLATFORM}", 9) == 0
&& (len = 11) != 0))))
{
repl = ((len == 7 || name[2] == 'O')
? (__libc_enable_secure ? NULL : l->l_origin)
: _dl_platform);
if (repl != NULL && repl != (const char *) -1)
{
wp = __stpcpy (wp, repl);
name += len;
}
else
{
/* We cannot use this path element, the value of the
replacement is unknown. */
wp = last_elem;
name += len;
while (*name != '\0' && (!is_path || *name != ':'))
++name;
}
}
else
/* No DST we recognize. */
*wp++ = *name++;
}
else if (is_path && *name == ':')
{
*wp++ = *name++;
last_elem = wp;
}
else
*wp++ = *name++;
}
while (*name != '\0');
*wp = '\0';
return result;
}
/* Return copy of argument with all recognized dynamic string tokens
($ORIGIN and $PLATFORM for now) replaced. On some platforms it
might not be possible to determine the path from which the object
@ -158,117 +255,29 @@ expand_dynamic_string_token (struct link_map *l, const char *s)
resulting string is and then we copy it over. Since this is now
frequently executed operation we are looking here not for performance
but rather for code size. */
const char *sf;
size_t cnt = 0;
size_t origin_len;
size_t cnt;
size_t total;
char *result, *last_elem, *wp;
char *result;
sf = strchr (s, '$');
while (sf != NULL)
{
size_t len = 1;
/* $ORIGIN is not expanded for SUID/GUID programs. */
if ((((!__libc_enable_secure
&& strncmp (&sf[1], "ORIGIN", 6) == 0 && (len = 7) != 0)
|| (strncmp (&sf[1], "PLATFORM", 8) == 0 && (len = 9) != 0))
&& (s[len] == '\0' || s[len] == '/' || s[len] == ':'))
|| (s[1] == '{'
&& ((!__libc_enable_secure
&& strncmp (&sf[2], "ORIGIN}", 7) == 0 && (len = 9) != 0)
|| (strncmp (&sf[2], "PLATFORM}", 9) == 0
&& (len = 11) != 0))))
++cnt;
sf = strchr (sf + len, '$');
}
/* Determine the nubmer of DST elements. */
cnt = DL_DST_COUNT (s, 1);
/* If we do not have to replace anything simply copy the string. */
if (cnt == 0)
return local_strdup (s);
/* Now we make a guess how many extra characters on top of the length
of S we need to represent the result. We know that we have CNT
replacements. Each at most can use
MAX (strlen (ORIGIN), strlen (_dl_platform))
minus 7 (which is the length of "$ORIGIN").
/* Determine the length of the substituted string. */
total = DL_DST_REQUIRED (l, s, strlen (s), cnt);
First get the origin string if it is not available yet. This can
only happen for the map of the executable. */
if (l->l_origin == NULL)
{
assert (l->l_name[0] == '\0');
l->l_origin = get_origin ();
origin_len = (l->l_origin && l->l_origin != (char *) -1
? strlen (l->l_origin) : 0);
}
else
origin_len = l->l_origin == (char *) -1 ? 0 : strlen (l->l_origin);
total = strlen (s) + cnt * (MAX (origin_len, _dl_platformlen) - 7);
/* Allocate the necessary memory. */
result = (char *) malloc (total + 1);
if (result == NULL)
return NULL;
/* Now fill the result path. While copying over the string we keep
track of the start of the last path element. When we come accross
a DST we copy over the value or (if the value is not available)
leave the entire path element out. */
last_elem = wp = result;
do
{
if (*s == '$')
{
const char *repl;
size_t len;
if ((((strncmp (&s[1], "ORIGIN", 6) == 0 && (len = 7) != 0)
|| (strncmp (&s[1], "PLATFORM", 8) == 0 && (len = 9) != 0))
&& (s[len] == '\0' || s[len] == '/' || s[len] == ':'))
|| (s[1] == '{'
&& ((strncmp (&s[2], "ORIGIN}", 7) == 0 && (len = 9) != 0)
|| (strncmp (&s[2], "PLATFORM}", 9) == 0
&& (len = 11) != 0))))
{
repl = ((len == 7 || s[2] == 'O')
? (__libc_enable_secure ? NULL : l->l_origin)
: _dl_platform);
if (repl != NULL && repl != (const char *) -1)
{
wp = __stpcpy (wp, repl);
s += len;
}
else
{
/* We cannot use this path element, the value of the
replacement is unknown. */
wp = last_elem;
s += len;
while (*s != '\0' && *s != ':')
++s;
}
}
else
/* No DST we recognize. */
*wp++ = *s++;
}
else if (*s == ':')
{
*wp++ = *s++;
last_elem = wp;
}
else
*wp++ = *s++;
}
while (*s != '\0');
*wp = '\0';
return result;
return DL_DST_SUBSTITUTE (l, s, result, 1);
}
/* Add `name' to the list of names for a particular shared object.
`name' is expected to have been allocated with malloc and will
be freed if the shared object already has this name.

View file

@ -17,14 +17,18 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <assert.h>
#include <dlfcn.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h> /* Check whether MAP_COPY is defined. */
#include <sys/param.h>
#include <bits/libc-lock.h>
#include <elf/ldsodefs.h>
#include <dl-dst.h>
extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
void (*dl_main) (const ElfW(Phdr) *phdr,
@ -57,6 +61,7 @@ static void show_scope (struct link_map *new);
At this time it is not anymore a problem to modify the tables. */
__libc_lock_define_initialized_recursive (, _dl_load_lock)
extern size_t _dl_platformlen;
/* We must be carefull not to leave us in an inconsistent state. Thus we
catch any error and re-raise it after cleaning up. */
@ -65,6 +70,7 @@ struct dl_open_args
{
const char *file;
int mode;
const void *caller;
struct link_map *map;
};
@ -78,6 +84,50 @@ dl_open_worker (void *a)
ElfW(Addr) init;
struct r_debug *r;
unsigned int global_add;
const char *dst;
/* Maybe we have to expand a DST. */
dst = strchr (file, '$');
if (dst != NULL)
{
const void *caller = args->caller;
size_t len = strlen (file);
size_t required;
struct link_map *call_map;
char *new_file;
/* We have to find out from which object the caller is calling.
Find the highest-addressed object that ADDRESS is not below. */
call_map = NULL;
for (l = _dl_loaded; l; l = l->l_next)
if (l->l_addr != 0 /* Make sure we do not currently set this map up
in this moment. */
&& caller >= (const void *) l->l_addr
&& (call_map == NULL || call_map->l_addr < l->l_addr))
call_map = l;
if (call_map == NULL)
/* In this case we assume this is the main application. */
call_map = _dl_loaded;
/* Determine how much space we need. We have to allocate the
memory locally. */
required = DL_DST_REQUIRED (call_map, file, len, _dl_dst_count (dst, 0));
/* Get space for the new file name. */
new_file = (char *) alloca (required + 1);
/* Generate the new file name. */
DL_DST_SUBSTITUTE (call_map, file, new_file, 0);
/* If the substitution failed don't try to load. */
if (*new_file == '\0')
_dl_signal_error (0, "dlopen",
"empty dynamics string token substitution");
/* Now we have a new file name. */
file = new_file;
}
/* Load the named object. */
args->map = new = _dl_map_object (NULL, file, 0, lt_loaded, 0);
@ -157,7 +207,7 @@ dl_open_worker (void *a)
struct link_map *
internal_function
_dl_open (const char *file, int mode)
_dl_open (const char *file, int mode, const void *caller)
{
struct dl_open_args args;
char *errstring;
@ -172,6 +222,7 @@ _dl_open (const char *file, int mode)
args.file = file;
args.mode = mode;
args.caller = caller;
args.map = NULL;
errcode = _dl_catch_error (&errstring, dl_open_worker, &args);

View file

@ -1,5 +1,5 @@
/* Load a shared object at run time.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -28,6 +28,8 @@ struct dlopen_args
int mode;
/* The return value of dlopen_doit. */
struct link_map *new;
/* Address of the caller. */
const void *caller;
};
@ -36,7 +38,7 @@ dlopen_doit (void *a)
{
struct dlopen_args *args = (struct dlopen_args *) a;
args->new = _dl_open (args->file ?: "", args->mode);
args->new = _dl_open (args->file ?: "", args->mode, args->caller);
}
@ -46,6 +48,7 @@ __dlopen_check (const char *file, int mode)
struct dlopen_args args;
args.file = file;
args.mode = mode;
args.caller = __builtin_return_address (0);
return _dlerror_run (dlopen_doit, &args) ? NULL : args.new;
}

View file

@ -32,6 +32,8 @@ struct dlopen_args
int mode;
/* The return value of dlopen_doit. */
struct link_map *new;
/* Address of the caller. */
const void *caller;
};
@ -40,7 +42,7 @@ dlopen_doit (void *a)
{
struct dlopen_args *args = (struct dlopen_args *) a;
args->new = _dl_open (args->file ?: "", args->mode);
args->new = _dl_open (args->file ?: "", args->mode, args->caller);
}
@ -49,6 +51,7 @@ __dlopen_nocheck (const char *file, int mode)
{
struct dlopen_args args;
args.file = file;
args.caller = __builtin_return_address (0);
if ((mode & RTLD_BINDING_MASK) == 0)
/* By default assume RTLD_LAZY. */

View file

@ -270,7 +270,8 @@ extern void _dl_setup_hash (struct link_map *map) internal_function;
/* Open the shared object NAME, relocate it, and run its initializer if it
hasn't already been run. MODE is as for `dlopen' (see <dlfcn.h>). If
the object is already opened, returns its existing map. */
extern struct link_map *_dl_open (const char *name, int mode)
extern struct link_map *_dl_open (const char *name, int mode,
const void *caller)
internal_function;
/* Close an object previously opened by _dl_open. */

38
elf/origtest.c Normal file
View file

@ -0,0 +1,38 @@
#include <dlfcn.h>
#include <error.h>
#include <stdio.h>
#include <stdlib.h>
int
main (void)
{
void *h;
int (*fp) (int);
int res;
h = dlopen ("${ORIGIN}/testobj1.so", RTLD_LAZY);
if (h == NULL)
error (EXIT_FAILURE, 0, "while loading `%s': %s", "testobj1.so",
dlerror ());
fp = dlsym (h, "obj1func1");
if (fp == NULL)
error (EXIT_FAILURE, 0, "getting `obj1func1' in `%s': %s",
"testobj1.so", dlerror ());
res = fp (10);
printf ("fp(10) = %d\n", res);
if (dlclose (h) != 0)
error (EXIT_FAILURE, 0, "while close `%s': %s",
"testobj1.so", dlerror ());
return res != 42;
}
int
foo (int a)
{
return a + 10;
}

View file

@ -64,7 +64,7 @@ do_open (void *a)
{
struct gconv_loaded_object *args = (struct gconv_loaded_object *) a;
/* Open and relocate the shared object. */
args->handle = _dl_open (args->name, RTLD_LAZY);
args->handle = _dl_open (args->name, RTLD_LAZY, NULL);
}

View file

@ -285,7 +285,7 @@ do_open (void *a)
{
struct do_open_args *args = (struct do_open_args *) a;
/* Open and relocate the shared object. */
args->ni->library->lib_handle = _dl_open (args->shlib_name, RTLD_LAZY);
args->ni->library->lib_handle = _dl_open (args->shlib_name, RTLD_LAZY, NULL);
}
static void

View file

@ -1,5 +1,5 @@
/* Find path of executable.
Copyright (C) 1998 Free Software Foundation, Inc.
Copyright (C) 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
@ -18,12 +18,19 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include <elf/ldsodefs.h>
#include <dl-dst.h>
/* Generally it is not possible to implement this. We have to fall
back on a solution where the user provides the information. */
extern const char *_dl_origin_path;
static inline const char *
get_origin (void)
const char *
_dl_get_origin (void)
{
char *result = (char *) -1;
/* We use the environment variable LD_ORIGIN_PATH. If it is set make

View file

@ -1,5 +1,5 @@
/* Find path of executable.
Copyright (C) 1998 Free Software Foundation, Inc.
Copyright (C) 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
@ -18,13 +18,21 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/param.h>
#include <elf/ldsodefs.h>
#include <dl-dst.h>
/* On Linux >= 2.1 systems which have the dcache implementation we can get
the path of the application from the /proc/self/exe symlink. Try this
first and fall back on the generic method if necessary. */
extern const char *_dl_origin_path;
static inline const char *
get_origin (void)
const char *
_dl_get_origin (void)
{
char linkval[PATH_MAX];
char *result;