mirror of
https://sourceware.org/git/glibc.git
synced 2026-01-06 11:51:29 +03:00
Update.
1998-08-27 19:42 Ulrich Drepper <drepper@cygnus.com> * elf/Makefile (distribute): Add dl-origin.h. * sysdeps/generic/dl-origin.h: New file. * sysdeps/unix/sysv/linux/dl-origin.h: New file. * elf/link.h (struct link_map): Add l_origin field. * elf/dl-load.c (expand_dynamic_string_token): New function. (decompose_path): Remove WHERE argument, take link map pointer instead. Call expand_dynamic_string_token instead of local_strdup to make copy of rpath. (_dl_init_paths): Call decompose_path with correct argument. (_dl_map_object_from_fd): Define static is EXTERNAL_MAP_FROM_FD is not defined. Check EI_OSABI and EI_ABIVERSION fields in header. (_dl_map_object): Call decompose_path with correct argument. Call expand_dynamic_string_token instead of local_strdup to also expand DST. * elf/dl-object.c (_dl_new_object): Determine l_origin for all maps but the main one. * elf/dl-support.c: Define _dl_origin_path. * elf/rtld.c: Likewise. Set _dl_origin_path based on LD_ORIGIN_PATH. * elf/dl-close (_dl_close): Free l_name and l_origin. * sysdeps/i386/useldt.h (THREAD_GETMEM, THREAD_SETMEM): Use P modifier in asm, not c. * sysdeps/mach/hurd/Makefile [subdirs==elf]: Define CFLAGS-dl-load.c to -DEXTERNAL_MAP_FROM_FD to make _dl_map_object_from_fd extern.
This commit is contained in:
153
elf/dl-load.c
153
elf/dl-load.c
@@ -31,6 +31,8 @@
|
||||
#include "dynamic-link.h"
|
||||
#include <stdio-common/_itoa.h>
|
||||
|
||||
#include <dl-origin.h>
|
||||
|
||||
|
||||
/* On some systems, no flag bits are given to specify file mapping. */
|
||||
#ifndef MAP_FILE
|
||||
@@ -124,6 +126,116 @@ local_strdup (const char *s)
|
||||
return (char *) memcpy (new, s, len);
|
||||
}
|
||||
|
||||
/* 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
|
||||
belonging to the map is loaded. In this case the path element
|
||||
containing $ORIGIN is left out. */
|
||||
static char *
|
||||
expand_dynamic_string_token (struct link_map *l, const char *s)
|
||||
{
|
||||
/* We make two runs over the string. First we determine how large the
|
||||
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 *st, *sf;
|
||||
size_t cnt = 0;
|
||||
size_t origin_len;
|
||||
size_t total;
|
||||
char *result, *last_elem, *wp;
|
||||
|
||||
st = s;
|
||||
sf = strchr (s, '$');
|
||||
while (sf != NULL)
|
||||
{
|
||||
size_t len = 1;
|
||||
|
||||
if (((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] == ':'))
|
||||
++cnt;
|
||||
|
||||
st = sf + len;
|
||||
sf = strchr (st, '$');
|
||||
}
|
||||
|
||||
/* 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").
|
||||
|
||||
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 ? 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);
|
||||
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] == ':'))
|
||||
{
|
||||
if ((repl = len == 7 ? l->l_origin : _dl_platform) != 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 SDK 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.
|
||||
`name' is expected to have been allocated with malloc and will
|
||||
be freed if the shared object already has this name.
|
||||
@@ -286,9 +398,10 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep,
|
||||
|
||||
static struct r_search_path_elem **
|
||||
internal_function
|
||||
decompose_rpath (const char *rpath, size_t additional_room, const char *where)
|
||||
decompose_rpath (const char *rpath, size_t additional_room, struct link_map *l)
|
||||
{
|
||||
/* Make a copy we can work with. */
|
||||
const char *where = l->l_name;
|
||||
char *copy;
|
||||
char *cp;
|
||||
struct r_search_path_elem **result;
|
||||
@@ -318,8 +431,13 @@ decompose_rpath (const char *rpath, size_t additional_room, const char *where)
|
||||
}
|
||||
}
|
||||
|
||||
/* Make a writable copy. At the same time expand possible dynamic
|
||||
string tokens. */
|
||||
copy = expand_dynamic_string_token (l, rpath);
|
||||
if (copy == NULL)
|
||||
_dl_signal_error (ENOMEM, NULL, "cannot create RPATH copy");
|
||||
|
||||
/* Count the number of necessary elements in the result array. */
|
||||
copy = local_strdup (rpath);
|
||||
nelems = 0;
|
||||
for (cp = copy; *cp != '\0'; ++cp)
|
||||
if (*cp == ':')
|
||||
@@ -429,7 +547,7 @@ _dl_init_paths (const char *llp)
|
||||
decompose_rpath ((const char *)
|
||||
(l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr
|
||||
+ l->l_info[DT_RPATH]->d_un.d_val),
|
||||
nllp, l->l_name);
|
||||
nllp, l);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -497,6 +615,9 @@ _dl_init_paths (const char *llp)
|
||||
/* Map in the shared object NAME, actually located in REALNAME, and already
|
||||
opened on FD. */
|
||||
|
||||
#ifndef EXTERNAL_MAP_FROM_FD
|
||||
static
|
||||
#endif
|
||||
struct link_map *
|
||||
_dl_map_object_from_fd (char *name, int fd, char *realname,
|
||||
struct link_map *loader, int l_type)
|
||||
@@ -591,6 +712,12 @@ _dl_map_object_from_fd (char *name, int fd, char *realname,
|
||||
LOSE ("ELF file data encoding not " byteorder_name);
|
||||
if (header->e_ident[EI_VERSION] != EV_CURRENT)
|
||||
LOSE ("ELF file version ident not " STRING(EV_CURRENT));
|
||||
/* XXX We should be able so set system specific versions which are
|
||||
allowed here. */
|
||||
if (header->e_ident[EI_OSABI] != ELFOSABI_SYSV)
|
||||
LOSE ("ELF file OS ABI not " STRING(ELFOSABI_SYSV));
|
||||
if (header->e_ident[EI_ABIVERSION] != 0)
|
||||
LOSE ("ELF file ABI version not 0");
|
||||
if (header->e_version != EV_CURRENT)
|
||||
LOSE ("ELF file version not " STRING(EV_CURRENT));
|
||||
if (! elf_machine_matches_host (header->e_machine))
|
||||
@@ -1076,7 +1203,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
|
||||
+ l->l_info[DT_STRTAB]->d_un.d_ptr
|
||||
+ l->l_info[DT_RPATH]->d_un.d_val);
|
||||
l->l_rpath_dirs =
|
||||
decompose_rpath ((const char *) ptrval, 0, l->l_name);
|
||||
decompose_rpath ((const char *) ptrval, 0, l);
|
||||
}
|
||||
|
||||
if (l->l_rpath_dirs != (struct r_search_path_elem **) -1l)
|
||||
@@ -1127,15 +1254,17 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
|
||||
}
|
||||
else
|
||||
{
|
||||
fd = __open (name, O_RDONLY);
|
||||
if (fd != -1)
|
||||
/* The path may contain dynamic string tokens. */
|
||||
realname = (loader
|
||||
? expand_dynamic_string_token (loader, name)
|
||||
: local_strdup (name));
|
||||
if (realname == NULL)
|
||||
fd = -1;
|
||||
else
|
||||
{
|
||||
realname = local_strdup (name);
|
||||
if (realname == NULL)
|
||||
{
|
||||
__close (fd);
|
||||
fd = -1;
|
||||
}
|
||||
fd = __open (realname, O_RDONLY);
|
||||
if (fd == -1)
|
||||
free (realname);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user