Add support to the static linker for the tokens accepted by the dynamic linker when resolving search paths.
PR ld/20535 * emultempl/elf32.em (_search_needed): Add support for pseudo environment variables supported by ld.so. Namely $ORIGIN, $LIB and $PLATFORM. * configure.ac: Add getauxval to list AC_CHECK_FUNCS list. * config.in: Regenerate. * configure: Regenerate.
This commit is contained in:
parent
93562a343c
commit
199fa1b708
10
ld/ChangeLog
10
ld/ChangeLog
|
@ -1,3 +1,13 @@
|
|||
2016-10-11 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR ld/20535
|
||||
* emultempl/elf32.em (_search_needed): Add support for pseudo
|
||||
environment variables supported by ld.so. Namely $ORIGIN, $LIB
|
||||
and $PLATFORM.
|
||||
* configure.ac: Add getauxval to list AC_CHECK_FUNCS list.
|
||||
* config.in: Regenerate.
|
||||
* configure: Regenerate.
|
||||
|
||||
2016-10-11 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* ldlang.c (lang_do_assignments_1): Descend into output section
|
||||
|
|
|
@ -62,6 +62,9 @@
|
|||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#undef HAVE_FCNTL_H
|
||||
|
||||
/* Define to 1 if you have the `getauxval' function. */
|
||||
#undef HAVE_GETAUXVAL
|
||||
|
||||
/* Define to 1 if you have the `getpagesize' function. */
|
||||
#undef HAVE_GETPAGESIZE
|
||||
|
||||
|
|
|
@ -16488,7 +16488,7 @@ _ACEOF
|
|||
fi
|
||||
done
|
||||
|
||||
for ac_func in open lseek close
|
||||
for ac_func in getauxval open lseek close
|
||||
do :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
|
|
|
@ -216,7 +216,7 @@ AC_CHECK_HEADERS(string.h strings.h stdlib.h unistd.h elf-hints.h limits.h local
|
|||
AC_CHECK_HEADERS(fcntl.h sys/file.h sys/time.h sys/stat.h)
|
||||
ACX_HEADER_STRING
|
||||
AC_CHECK_FUNCS(glob mkstemp realpath sbrk setlocale waitpid)
|
||||
AC_CHECK_FUNCS(open lseek close)
|
||||
AC_CHECK_FUNCS(getauxval open lseek close)
|
||||
AC_HEADER_DIRENT
|
||||
|
||||
dnl AC_CHECK_HEADERS(sys/mman.h)
|
||||
|
|
|
@ -472,6 +472,15 @@ fragment <<EOF
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
EOF
|
||||
if [ "x${NATIVE}" = xyes ] ; then
|
||||
fragment <<EOF
|
||||
#ifdef HAVE_GETAUXVAL
|
||||
#include <sys/auxv.h>
|
||||
#endif
|
||||
EOF
|
||||
fi
|
||||
fragment <<EOF
|
||||
|
||||
/* Search for a needed file in a path. */
|
||||
|
||||
|
@ -496,6 +505,7 @@ gld${EMULATION_NAME}_search_needed (const char *path,
|
|||
len = strlen (name);
|
||||
while (1)
|
||||
{
|
||||
char * var;
|
||||
char *filename, *sset;
|
||||
|
||||
s = strchr (path, config.rpath_separator);
|
||||
|
@ -524,6 +534,147 @@ gld${EMULATION_NAME}_search_needed (const char *path,
|
|||
}
|
||||
strcpy (sset, name);
|
||||
|
||||
/* PR 20535: Support the same pseudo-environment variables that
|
||||
are supported by ld.so. Namely, $ORIGIN, $LIB and $PLATFORM.
|
||||
Since there can be more than one occurrence of these tokens in
|
||||
the path we loop until no more are found. */
|
||||
while ((var = strchr (filename, '$')) != NULL)
|
||||
{
|
||||
/* The ld.so manual page does not say, but I am going to assume that
|
||||
these tokens are terminated by a directory seperator character
|
||||
(/) or the end of the string. There is also an implication that
|
||||
$ORIGIN should only be used at the start of a path, but that is
|
||||
not enforced here.
|
||||
|
||||
FIXME: The ld.so manual page also states that it allows ${ORIGIN}
|
||||
${LIB} and ${PLATFORM}. We should support these variants too.
|
||||
|
||||
FIXME: The code could be a lot cleverer about allocating space
|
||||
for the processed string. */
|
||||
char * end = strchr (var, '/');
|
||||
char * replacement = NULL;
|
||||
char * freeme = NULL;
|
||||
unsigned flen = strlen (filename);
|
||||
|
||||
if (end != NULL)
|
||||
/* Temporarily terminate the filename at the end of the token. */
|
||||
* end = 0;
|
||||
|
||||
switch (var[1])
|
||||
{
|
||||
case 'O':
|
||||
if (strcmp (var + 2, "RIGIN") == 0)
|
||||
{
|
||||
/* ORIGIN - replace with the full path to the directory
|
||||
containing the program or shared object. */
|
||||
if (needed.by == NULL)
|
||||
break;
|
||||
replacement = bfd_get_filename (needed.by);
|
||||
if (replacement)
|
||||
{
|
||||
char * slash;
|
||||
|
||||
if (replacement[0] == '/')
|
||||
freeme = xstrdup (replacement);
|
||||
else
|
||||
{
|
||||
char * current_dir = getpwd ();
|
||||
|
||||
freeme = xmalloc (strlen (replacement) + strlen (current_dir));
|
||||
sprintf (freeme, "%s/%s", current_dir, replacement);
|
||||
}
|
||||
|
||||
replacement = freeme;
|
||||
if ((slash = strrchr (replacement, '/')) != NULL)
|
||||
* slash = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
if (strcmp (var + 2, "IB") == 0)
|
||||
{
|
||||
/* LIB - replace with "lib" in 32-bit environments
|
||||
and "lib64" in 64-bit environments. */
|
||||
|
||||
/* Note - we could replace this switch statement by
|
||||
conditional fragments of shell script, but that is messy.
|
||||
Any compiler worth its salt is going to optimize away
|
||||
all but one of these case statements anyway. */
|
||||
switch ($ELFSIZE)
|
||||
{
|
||||
case 32: replacement = "lib"; break;
|
||||
case 64: replacement = "lib64"; break;
|
||||
default:
|
||||
/* $ELFSIZE is not 32 or 64 ... */
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
if (strcmp (var + 2, "LATFORM") == 0)
|
||||
{
|
||||
/* PLATFORM - replace with a string corresponding
|
||||
to the processor type of the host system.
|
||||
|
||||
FIXME: Supporting this token might be a bad idea,
|
||||
especially for non-native linkers. It has the potential
|
||||
to find incorrect results. Maybe issuing a warning
|
||||
message would be safer. Current policy: wait and see if
|
||||
somebody complains. */
|
||||
replacement = "$OUTPUT_ARCH";
|
||||
EOF
|
||||
# We use getauxval() if it is available, but only for natives.
|
||||
if [ "x${NATIVE}" = xyes ] ; then
|
||||
fragment <<EOF
|
||||
#ifdef HAVE_GETAUXVAL
|
||||
replacement = (char *) getauxval (AT_PLATFORM);
|
||||
#endif
|
||||
EOF
|
||||
fi
|
||||
fragment <<EOF
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (replacement)
|
||||
{
|
||||
char * filename2 = xmalloc (flen + strlen (replacement));
|
||||
|
||||
if (end)
|
||||
sprintf (filename2, "%.*s%s/%s",
|
||||
(int)(var - filename), filename,
|
||||
replacement, end + 1);
|
||||
else
|
||||
sprintf (filename2, "%.*s%s",
|
||||
(int)(var - filename), filename,
|
||||
replacement);
|
||||
|
||||
free (filename);
|
||||
filename = filename2;
|
||||
/* There is no need to restore the path separator (when
|
||||
end != NULL) as we have replaced the entire string. */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (verbose)
|
||||
/* We only issue an "unrecognised" message in verbose mode
|
||||
as the $<foo> token might be a legitimate component of
|
||||
a path name in the target's file system. */
|
||||
info_msg (_("unrecognised token '%s' in search path\n"), var);
|
||||
|
||||
if (end)
|
||||
/* Restore the path separator. */
|
||||
* end = '/';
|
||||
}
|
||||
|
||||
free (freeme);
|
||||
}
|
||||
|
||||
needed.name = filename;
|
||||
if (gld${EMULATION_NAME}_try_needed (&needed, force))
|
||||
return TRUE;
|
||||
|
|
Loading…
Reference in New Issue