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>
|
2016-10-11 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* ldlang.c (lang_do_assignments_1): Descend into output section
|
* 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. */
|
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||||
#undef HAVE_FCNTL_H
|
#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. */
|
/* Define to 1 if you have the `getpagesize' function. */
|
||||||
#undef HAVE_GETPAGESIZE
|
#undef HAVE_GETPAGESIZE
|
||||||
|
|
||||||
|
|
|
@ -16488,7 +16488,7 @@ _ACEOF
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
for ac_func in open lseek close
|
for ac_func in getauxval open lseek close
|
||||||
do :
|
do :
|
||||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
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)
|
AC_CHECK_HEADERS(fcntl.h sys/file.h sys/time.h sys/stat.h)
|
||||||
ACX_HEADER_STRING
|
ACX_HEADER_STRING
|
||||||
AC_CHECK_FUNCS(glob mkstemp realpath sbrk setlocale waitpid)
|
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
|
AC_HEADER_DIRENT
|
||||||
|
|
||||||
dnl AC_CHECK_HEADERS(sys/mman.h)
|
dnl AC_CHECK_HEADERS(sys/mman.h)
|
||||||
|
|
|
@ -472,6 +472,15 @@ fragment <<EOF
|
||||||
return TRUE;
|
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. */
|
/* Search for a needed file in a path. */
|
||||||
|
|
||||||
|
@ -496,6 +505,7 @@ gld${EMULATION_NAME}_search_needed (const char *path,
|
||||||
len = strlen (name);
|
len = strlen (name);
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
char * var;
|
||||||
char *filename, *sset;
|
char *filename, *sset;
|
||||||
|
|
||||||
s = strchr (path, config.rpath_separator);
|
s = strchr (path, config.rpath_separator);
|
||||||
|
@ -524,6 +534,147 @@ gld${EMULATION_NAME}_search_needed (const char *path,
|
||||||
}
|
}
|
||||||
strcpy (sset, name);
|
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;
|
needed.name = filename;
|
||||||
if (gld${EMULATION_NAME}_try_needed (&needed, force))
|
if (gld${EMULATION_NAME}_try_needed (&needed, force))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
Loading…
Reference in New Issue