mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
Update.
* 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:
27
ChangeLog
27
ChangeLog
@ -1,5 +1,32 @@
|
|||||||
1999-05-05 Ulrich Drepper <drepper@cygnus.com>
|
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
|
* stdio-common/_itoa.c (_itoa): Fix special 32bit platform case
|
||||||
with specific bases and only few bits set in second word.
|
with specific bases and only few bits set in second word.
|
||||||
|
|
||||||
|
@ -72,4 +72,5 @@ libdb1 {
|
|||||||
ld.so {
|
ld.so {
|
||||||
GLIBC_2.0
|
GLIBC_2.0
|
||||||
GLIBC_2.1 GLIBC_2.0
|
GLIBC_2.1 GLIBC_2.0
|
||||||
|
GLIBC_2.1.1 GLIBC_2.1
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ subdir := elf
|
|||||||
|
|
||||||
headers = elf.h bits/elfclass.h bits/dlfcn.h link.h dlfcn.h
|
headers = elf.h bits/elfclass.h bits/dlfcn.h link.h dlfcn.h
|
||||||
routines = $(dl-routines) dl-open dl-close dl-symbol dl-support \
|
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
|
# The core dynamic linking functions are in libc for the static and
|
||||||
# profiled libraries.
|
# profiled libraries.
|
||||||
@ -78,7 +78,7 @@ install-rootsbin += ldconfig
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq (yes,$(build-shared))
|
ifeq (yes,$(build-shared))
|
||||||
tests = loadtest restest1 preloadtest loadfail multiload
|
tests = loadtest restest1 preloadtest loadfail multiload origtest
|
||||||
endif
|
endif
|
||||||
modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||||
testobj1_1 failobj
|
testobj1_1 failobj
|
||||||
@ -253,6 +253,9 @@ LDFLAGS-multiload = -rdynamic
|
|||||||
CFLAGS-multiload.c = -DOBJDIR=\"$(elf-objpfx)\"
|
CFLAGS-multiload.c = -DOBJDIR=\"$(elf-objpfx)\"
|
||||||
|
|
||||||
$(objpfx)multiload.out: $(objpfx)testobj1.so
|
$(objpfx)multiload.out: $(objpfx)testobj1.so
|
||||||
|
|
||||||
|
$(objpfx)origtest: $(libdl)
|
||||||
|
$(objpfx)origtest.out: $(objpfx)testobj1.so
|
||||||
|
|
||||||
# muwahaha
|
# muwahaha
|
||||||
|
|
||||||
|
@ -37,6 +37,13 @@ ld.so {
|
|||||||
# functions used in other libraries
|
# functions used in other libraries
|
||||||
_dl_mcount; _dl_unload_cache;
|
_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 {
|
libdl {
|
||||||
|
@ -17,13 +17,15 @@
|
|||||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
Boston, MA 02111-1307, USA. */
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#include <elf/ldsodefs.h>
|
#include <elf/ldsodefs.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <dl-dst.h>
|
||||||
|
|
||||||
/* Whether an shared object references one or more auxiliary objects
|
/* Whether an shared object references one or more auxiliary objects
|
||||||
is signaled by the AUXTAG entry in l_info. */
|
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. */
|
reset if in _dl_close if the last global object is removed. */
|
||||||
size_t _dl_global_scope_alloc;
|
size_t _dl_global_scope_alloc;
|
||||||
|
|
||||||
|
extern size_t _dl_platformlen;
|
||||||
|
|
||||||
/* When loading auxiliary objects we must ignore errors. It's ok if
|
/* When loading auxiliary objects we must ignore errors. It's ok if
|
||||||
an object is missing. */
|
an object is missing. */
|
||||||
@ -48,7 +51,7 @@ struct openaux_args
|
|||||||
struct link_map *map;
|
struct link_map *map;
|
||||||
int trace_mode;
|
int trace_mode;
|
||||||
const char *strtab;
|
const char *strtab;
|
||||||
const ElfW(Dyn) *d;
|
const char *name;
|
||||||
|
|
||||||
/* The return value of openaux. */
|
/* The return value of openaux. */
|
||||||
struct link_map *aux;
|
struct link_map *aux;
|
||||||
@ -59,7 +62,7 @@ openaux (void *a)
|
|||||||
{
|
{
|
||||||
struct openaux_args *args = (struct openaux_args *) 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
|
(args->map->l_type == lt_executable
|
||||||
? lt_library : args->map->l_type),
|
? lt_library : args->map->l_type),
|
||||||
args->trace_mode);
|
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
|
unsigned int
|
||||||
internal_function
|
internal_function
|
||||||
_dl_map_object_deps (struct link_map *map,
|
_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)
|
if (__builtin_expect (d->d_tag, DT_NEEDED) == DT_NEEDED)
|
||||||
{
|
{
|
||||||
/* Map in the needed object. */
|
/* Map in the needed object. */
|
||||||
struct link_map *dep
|
struct link_map *dep;
|
||||||
= _dl_map_object (l, strtab + d->d_un.d_val, 0,
|
/* Allocate new entry. */
|
||||||
|
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 == lt_executable ? lt_library :
|
||||||
l->l_type, trace_mode);
|
l->l_type, trace_mode);
|
||||||
/* Allocate new entry. */
|
|
||||||
struct list *newp = alloca (sizeof (struct list));
|
|
||||||
|
|
||||||
/* Add it in any case to the duplicate list. */
|
/* Add it in any case to the duplicate list. */
|
||||||
|
newp = alloca (sizeof (struct list));
|
||||||
newp->map = dep;
|
newp->map = dep;
|
||||||
newp->dup = NULL;
|
newp->dup = NULL;
|
||||||
dtail->dup = newp;
|
dtail->dup = newp;
|
||||||
@ -202,17 +249,22 @@ _dl_map_object_deps (struct link_map *map,
|
|||||||
{
|
{
|
||||||
char *errstring;
|
char *errstring;
|
||||||
struct list *newp;
|
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)
|
if (d->d_tag == DT_AUXILIARY)
|
||||||
{
|
{
|
||||||
/* Store the tag in the argument structure. */
|
/* Store the tag in the argument structure. */
|
||||||
args.d = d;
|
args.name = name;
|
||||||
|
|
||||||
/* Say that we are about to load an auxiliary library. */
|
/* Say that we are about to load an auxiliary library. */
|
||||||
if (_dl_debug_libs)
|
if (_dl_debug_libs)
|
||||||
_dl_debug_message (1, "load auxiliary object=",
|
_dl_debug_message (1, "load auxiliary object=",
|
||||||
strtab + d->d_un.d_val,
|
name, " requested by file=",
|
||||||
" requested by file=",
|
|
||||||
l->l_name[0]
|
l->l_name[0]
|
||||||
? l->l_name : _dl_argv[0],
|
? l->l_name : _dl_argv[0],
|
||||||
"\n", NULL);
|
"\n", NULL);
|
||||||
@ -233,15 +285,14 @@ _dl_map_object_deps (struct link_map *map,
|
|||||||
{
|
{
|
||||||
/* Say that we are about to load an auxiliary library. */
|
/* Say that we are about to load an auxiliary library. */
|
||||||
if (_dl_debug_libs)
|
if (_dl_debug_libs)
|
||||||
_dl_debug_message (1, "load filtered object=",
|
_dl_debug_message (1, "load filtered object=", name,
|
||||||
strtab + d->d_un.d_val,
|
|
||||||
" requested by file=",
|
" requested by file=",
|
||||||
l->l_name[0]
|
l->l_name[0]
|
||||||
? l->l_name : _dl_argv[0],
|
? l->l_name : _dl_argv[0],
|
||||||
"\n", NULL);
|
"\n", NULL);
|
||||||
|
|
||||||
/* For filter objects the dependency must be available. */
|
/* 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
|
(l->l_type == lt_executable
|
||||||
? lt_library : l->l_type),
|
? lt_library : l->l_type),
|
||||||
trace_mode);
|
trace_mode);
|
||||||
|
72
elf/dl-dst.h
Normal file
72
elf/dl-dst.h
Normal 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);
|
207
elf/dl-load.c
207
elf/dl-load.c
@ -31,8 +31,7 @@
|
|||||||
#include "dynamic-link.h"
|
#include "dynamic-link.h"
|
||||||
#include <stdio-common/_itoa.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. */
|
/* On some systems, no flag bits are given to specify file mapping. */
|
||||||
#ifndef MAP_FILE
|
#ifndef MAP_FILE
|
||||||
@ -146,6 +145,104 @@ local_strdup (const char *s)
|
|||||||
return (char *) memcpy (new, s, len);
|
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
|
/* Return copy of argument with all recognized dynamic string tokens
|
||||||
($ORIGIN and $PLATFORM for now) replaced. On some platforms it
|
($ORIGIN and $PLATFORM for now) replaced. On some platforms it
|
||||||
might not be possible to determine the path from which the object
|
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
|
resulting string is and then we copy it over. Since this is now
|
||||||
frequently executed operation we are looking here not for performance
|
frequently executed operation we are looking here not for performance
|
||||||
but rather for code size. */
|
but rather for code size. */
|
||||||
const char *sf;
|
size_t cnt;
|
||||||
size_t cnt = 0;
|
|
||||||
size_t origin_len;
|
|
||||||
size_t total;
|
size_t total;
|
||||||
char *result, *last_elem, *wp;
|
char *result;
|
||||||
|
|
||||||
sf = strchr (s, '$');
|
/* Determine the nubmer of DST elements. */
|
||||||
while (sf != NULL)
|
cnt = DL_DST_COUNT (s, 1);
|
||||||
{
|
|
||||||
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, '$');
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we do not have to replace anything simply copy the string. */
|
/* If we do not have to replace anything simply copy the string. */
|
||||||
if (cnt == 0)
|
if (cnt == 0)
|
||||||
return local_strdup (s);
|
return local_strdup (s);
|
||||||
|
|
||||||
/* Now we make a guess how many extra characters on top of the length
|
/* Determine the length of the substituted string. */
|
||||||
of S we need to represent the result. We know that we have CNT
|
total = DL_DST_REQUIRED (l, s, strlen (s), 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
|
/* Allocate the necessary memory. */
|
||||||
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);
|
|
||||||
result = (char *) malloc (total + 1);
|
result = (char *) malloc (total + 1);
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Now fill the result path. While copying over the string we keep
|
return DL_DST_SUBSTITUTE (l, s, result, 1);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Add `name' to the list of names for a particular shared object.
|
/* Add `name' to the list of names for a particular shared object.
|
||||||
`name' is expected to have been allocated with malloc and will
|
`name' is expected to have been allocated with malloc and will
|
||||||
be freed if the shared object already has this name.
|
be freed if the shared object already has this name.
|
||||||
|
@ -17,14 +17,18 @@
|
|||||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
Boston, MA 02111-1307, USA. */
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/mman.h> /* Check whether MAP_COPY is defined. */
|
#include <sys/mman.h> /* Check whether MAP_COPY is defined. */
|
||||||
|
#include <sys/param.h>
|
||||||
#include <bits/libc-lock.h>
|
#include <bits/libc-lock.h>
|
||||||
#include <elf/ldsodefs.h>
|
#include <elf/ldsodefs.h>
|
||||||
|
|
||||||
|
#include <dl-dst.h>
|
||||||
|
|
||||||
|
|
||||||
extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
|
extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
|
||||||
void (*dl_main) (const ElfW(Phdr) *phdr,
|
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. */
|
At this time it is not anymore a problem to modify the tables. */
|
||||||
__libc_lock_define_initialized_recursive (, _dl_load_lock)
|
__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
|
/* We must be carefull not to leave us in an inconsistent state. Thus we
|
||||||
catch any error and re-raise it after cleaning up. */
|
catch any error and re-raise it after cleaning up. */
|
||||||
@ -65,6 +70,7 @@ struct dl_open_args
|
|||||||
{
|
{
|
||||||
const char *file;
|
const char *file;
|
||||||
int mode;
|
int mode;
|
||||||
|
const void *caller;
|
||||||
struct link_map *map;
|
struct link_map *map;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -78,6 +84,50 @@ dl_open_worker (void *a)
|
|||||||
ElfW(Addr) init;
|
ElfW(Addr) init;
|
||||||
struct r_debug *r;
|
struct r_debug *r;
|
||||||
unsigned int global_add;
|
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. */
|
/* Load the named object. */
|
||||||
args->map = new = _dl_map_object (NULL, file, 0, lt_loaded, 0);
|
args->map = new = _dl_map_object (NULL, file, 0, lt_loaded, 0);
|
||||||
@ -157,7 +207,7 @@ dl_open_worker (void *a)
|
|||||||
|
|
||||||
struct link_map *
|
struct link_map *
|
||||||
internal_function
|
internal_function
|
||||||
_dl_open (const char *file, int mode)
|
_dl_open (const char *file, int mode, const void *caller)
|
||||||
{
|
{
|
||||||
struct dl_open_args args;
|
struct dl_open_args args;
|
||||||
char *errstring;
|
char *errstring;
|
||||||
@ -172,6 +222,7 @@ _dl_open (const char *file, int mode)
|
|||||||
|
|
||||||
args.file = file;
|
args.file = file;
|
||||||
args.mode = mode;
|
args.mode = mode;
|
||||||
|
args.caller = caller;
|
||||||
args.map = NULL;
|
args.map = NULL;
|
||||||
errcode = _dl_catch_error (&errstring, dl_open_worker, &args);
|
errcode = _dl_catch_error (&errstring, dl_open_worker, &args);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Load a shared object at run time.
|
/* 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.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -28,6 +28,8 @@ struct dlopen_args
|
|||||||
int mode;
|
int mode;
|
||||||
/* The return value of dlopen_doit. */
|
/* The return value of dlopen_doit. */
|
||||||
struct link_map *new;
|
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;
|
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;
|
struct dlopen_args args;
|
||||||
args.file = file;
|
args.file = file;
|
||||||
args.mode = mode;
|
args.mode = mode;
|
||||||
|
args.caller = __builtin_return_address (0);
|
||||||
|
|
||||||
return _dlerror_run (dlopen_doit, &args) ? NULL : args.new;
|
return _dlerror_run (dlopen_doit, &args) ? NULL : args.new;
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,8 @@ struct dlopen_args
|
|||||||
int mode;
|
int mode;
|
||||||
/* The return value of dlopen_doit. */
|
/* The return value of dlopen_doit. */
|
||||||
struct link_map *new;
|
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;
|
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;
|
struct dlopen_args args;
|
||||||
args.file = file;
|
args.file = file;
|
||||||
|
args.caller = __builtin_return_address (0);
|
||||||
|
|
||||||
if ((mode & RTLD_BINDING_MASK) == 0)
|
if ((mode & RTLD_BINDING_MASK) == 0)
|
||||||
/* By default assume RTLD_LAZY. */
|
/* By default assume RTLD_LAZY. */
|
||||||
|
@ -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
|
/* 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
|
hasn't already been run. MODE is as for `dlopen' (see <dlfcn.h>). If
|
||||||
the object is already opened, returns its existing map. */
|
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;
|
internal_function;
|
||||||
|
|
||||||
/* Close an object previously opened by _dl_open. */
|
/* Close an object previously opened by _dl_open. */
|
||||||
|
38
elf/origtest.c
Normal file
38
elf/origtest.c
Normal 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;
|
||||||
|
}
|
@ -64,7 +64,7 @@ do_open (void *a)
|
|||||||
{
|
{
|
||||||
struct gconv_loaded_object *args = (struct gconv_loaded_object *) a;
|
struct gconv_loaded_object *args = (struct gconv_loaded_object *) a;
|
||||||
/* Open and relocate the shared object. */
|
/* Open and relocate the shared object. */
|
||||||
args->handle = _dl_open (args->name, RTLD_LAZY);
|
args->handle = _dl_open (args->name, RTLD_LAZY, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -285,7 +285,7 @@ do_open (void *a)
|
|||||||
{
|
{
|
||||||
struct do_open_args *args = (struct do_open_args *) a;
|
struct do_open_args *args = (struct do_open_args *) a;
|
||||||
/* Open and relocate the shared object. */
|
/* 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
|
static void
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Find path of executable.
|
/* 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.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
|
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
|
||||||
|
|
||||||
@ -18,12 +18,19 @@
|
|||||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
Boston, MA 02111-1307, USA. */
|
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
|
/* Generally it is not possible to implement this. We have to fall
|
||||||
back on a solution where the user provides the information. */
|
back on a solution where the user provides the information. */
|
||||||
extern const char *_dl_origin_path;
|
extern const char *_dl_origin_path;
|
||||||
|
|
||||||
static inline const char *
|
const char *
|
||||||
get_origin (void)
|
_dl_get_origin (void)
|
||||||
{
|
{
|
||||||
char *result = (char *) -1;
|
char *result = (char *) -1;
|
||||||
/* We use the environment variable LD_ORIGIN_PATH. If it is set make
|
/* We use the environment variable LD_ORIGIN_PATH. If it is set make
|
@ -1,5 +1,5 @@
|
|||||||
/* Find path of executable.
|
/* 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.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
|
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
|
||||||
|
|
||||||
@ -18,13 +18,21 @@
|
|||||||
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
Boston, MA 02111-1307, USA. */
|
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
|
/* 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
|
the path of the application from the /proc/self/exe symlink. Try this
|
||||||
first and fall back on the generic method if necessary. */
|
first and fall back on the generic method if necessary. */
|
||||||
extern const char *_dl_origin_path;
|
extern const char *_dl_origin_path;
|
||||||
|
|
||||||
static inline const char *
|
const char *
|
||||||
get_origin (void)
|
_dl_get_origin (void)
|
||||||
{
|
{
|
||||||
char linkval[PATH_MAX];
|
char linkval[PATH_MAX];
|
||||||
char *result;
|
char *result;
|
Reference in New Issue
Block a user