aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2016-10-11 12:04:42 +0100
committerNick Clifton <nickc@redhat.com>2016-10-11 12:13:43 +0100
commit199fa1b7089d7f7438b087fa30504ea5a590f561 (patch)
tree7cbfb0745751bb172694d4d402d354d37b697e21 /ld
parent93562a343c26f67d2bd0e93cceb18a0a793087c2 (diff)
downloadgdb-199fa1b7089d7f7438b087fa30504ea5a590f561.zip
gdb-199fa1b7089d7f7438b087fa30504ea5a590f561.tar.gz
gdb-199fa1b7089d7f7438b087fa30504ea5a590f561.tar.bz2
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.
Diffstat (limited to 'ld')
-rw-r--r--ld/ChangeLog10
-rw-r--r--ld/config.in3
-rwxr-xr-xld/configure2
-rw-r--r--ld/configure.ac2
-rw-r--r--ld/emultempl/elf32.em151
5 files changed, 166 insertions, 2 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 1c71de1..4c296bf 100644
--- a/ld/ChangeLog
+++ b/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
diff --git a/ld/config.in b/ld/config.in
index 2c6d698..5c614ed 100644
--- a/ld/config.in
+++ b/ld/config.in
@@ -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
diff --git a/ld/configure b/ld/configure
index 3f82f35..2c55b28 100755
--- a/ld/configure
+++ b/ld/configure
@@ -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"
diff --git a/ld/configure.ac b/ld/configure.ac
index d17281f..4542845 100644
--- a/ld/configure.ac
+++ b/ld/configure.ac
@@ -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)
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em
index 2815a3e..06f02c6 100644
--- a/ld/emultempl/elf32.em
+++ b/ld/emultempl/elf32.em
@@ -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;