PR 6753

Alan Modra amodra@bigpond.net.au
Sat Aug 9 10:10:00 GMT 2008


This patch is a result of my analysis of PR6753, a complaint that the
library search order is different when specifying a script with -T as
compared to using the same script as the default.  It turns out that
the claim is true for directories specified in a script SEARCH_DIR,
but not, I think, for -L directories, unless of course the user places
the -T option in the middle of -L options.  The problem is caused by
set_scripts_dir, a function that finds the location of ldscripts/ and
adds that directory to the linker search path, before parsing the
default script.  Typically, ldscripts/ is found in
$prefix/$target_alias/lib/, but can live in other places.  For
instance it is possible to put ldscripts in /usr/lib.  Call the
location of ldscripts/, $scriptdir.  If the user specifies a script
using -T (after any -L dirs!), the search order is:
 -L directories, script SEARCH_DIRs, $scriptdir
If you allow the linker to find the script, the search order is:
 -L directories, $scriptdir, script SEARCH_DIRs.
set_scripts_dir gets called even when the linker scripts are built-in
and there's no need to go looking in the file system.

I think that messing with the library search directories like this is
rather nasty, so let's not do that any more.  I've also fixed another
bug.  "ld -nostdlib" used to throw away the ldscripts/ directory,
potentially resulting in the linker not being able to find its linker
scripts.

	* ldmain.c (check_for_scripts_dir, set_scripts_dir): Delete.
	(main): Don't set_scripts_dir here.
	* ldfile.c (check_for_scripts_dir, find_scripts_dir): New functions,
	largely based on ldmain.c versions.
	(ldfile_find_command_file): Set up search in script dir here without
	affecting library search.
	* Makefile.am (ldmain.o): No need to define SCRIPTDIR.
	(ldfile.o): New rule.
	* Makefile.in: Regenerate.

Index: ld/Makefile.am
===================================================================
RCS file: /cvs/src/src/ld/Makefile.am,v
retrieving revision 1.251
diff -u -p -r1.251 Makefile.am
--- ld/Makefile.am	4 Aug 2008 06:55:32 -0000	1.251
+++ ld/Makefile.am	9 Aug 2008 04:58:52 -0000
@@ -464,11 +464,15 @@ po/POTFILES.in: @MAINT@ Makefile
 
 ldmain.o: ldmain.c config.status
 	$(COMPILE) -c -DDEFAULT_EMULATION='"$(EMUL)"' \
-	  -DSCRIPTDIR='"$(scriptdir)"' -DBINDIR='"$(bindir)"' \
-	  -DTOOLBINDIR='"$(tooldir)/bin"' \
+	  -DBINDIR='"$(bindir)"' -DTOOLBINDIR='"$(tooldir)/bin"' \
 	  -DTARGET='"@target@"' @TARGET_SYSTEM_ROOT_DEFINE@ \
 	  $(srcdir)/ldmain.c
 
+ldfile.o: ldfile.c config.status
+	$(COMPILE) -c -DSCRIPTDIR='"$(scriptdir)"' \
+	  -DBINDIR='"$(bindir)"' -DTOOLBINDIR='"$(tooldir)/bin"' \
+	  $(srcdir)/ldfile.c
+
 eelf32_spu.o: eelf32_spu.c
 	$(COMPILE) -c -DEMBEDSPU="\"`echo embedspu | sed '$(transform)'`\"" \
 	  eelf32_spu.c
Index: ld/ldfile.c
===================================================================
RCS file: /cvs/src/src/ld/ldfile.c,v
retrieving revision 1.46
diff -u -p -r1.46 ldfile.c
--- ld/ldfile.c	8 Aug 2008 08:06:16 -0000	1.46
+++ ld/ldfile.c	9 Aug 2008 09:45:13 -0000
@@ -456,30 +456,134 @@ try_open (const char *name, const char *
   return result;
 }
 
-/* Try to open NAME; if that fails, look for it in any directories
-   specified with -L, without and with EXTEND appended.  */
+/* Return TRUE iff directory DIR contains an "ldscripts" subdirectory.  */
+
+static bfd_boolean
+check_for_scripts_dir (char *dir)
+{
+  char *buf;
+  struct stat s;
+  bfd_boolean res;
+
+  buf = concat (dir, "/ldscripts", (const char *) NULL);
+  res = stat (buf, &s) == 0 && S_ISDIR (s.st_mode);
+  free (buf);
+  return res;
+}
+
+/* Return the default directory for finding script files.
+   We look for the "ldscripts" directory in:
+
+   SCRIPTDIR (passed from Makefile)
+	     (adjusted according to the current location of the binary)
+   SCRIPTDIR (passed from Makefile)
+   the dir where this program is (for using it from the build tree)
+   the dir where this program is/../lib
+	     (for installing the tool suite elsewhere).  */
+
+static char *
+find_scripts_dir (void)
+{
+  char *end, *dir;
+  size_t dirlen;
+
+  dir = make_relative_prefix (program_name, BINDIR, SCRIPTDIR);
+  if (dir)
+    {
+      if (check_for_scripts_dir (dir))
+	return dir;
+      free (dir);
+    }
+
+  dir = make_relative_prefix (program_name, TOOLBINDIR, SCRIPTDIR);
+  if (dir)
+    {
+      if (check_for_scripts_dir (dir))
+	return dir;
+      free (dir);
+    }
+
+  if (check_for_scripts_dir (SCRIPTDIR))
+    /* We've been installed normally.  */
+    return SCRIPTDIR;
+
+  /* Look for "ldscripts" in the dir where our binary is.  */
+  end = strrchr (program_name, '/');
+#ifdef HAVE_DOS_BASED_FILE_SYSTEM
+  {
+    /* We could have \foo\bar, or /foo\bar.  */
+    char *bslash = strrchr (program_name, '\\');
+
+    if (end == NULL || (bslash != NULL && bslash > end))
+      end = bslash;
+  }
+#endif
+
+  if (end == NULL)
+    /* Don't look for ldscripts in the current directory.  There is
+       too much potential for confusion.  */
+    return NULL;
+
+  dirlen = end - program_name;
+  /* Make a copy of program_name in dir.
+     Leave room for later "/../lib".  */
+  dir = xmalloc (dirlen + sizeof ("/../lib"));
+  strncpy (dir, program_name, dirlen);
+  dir[dirlen] = '\0';
+
+  if (check_for_scripts_dir (dir))
+    return dir;
+
+  /* Look for "ldscripts" in <the dir where our binary is>/../lib.  */
+  strcpy (dir + dirlen, "/../lib");
+  if (check_for_scripts_dir (dir))
+    return dir;
+  free (dir);
+  return NULL;
+}
+
+/* Try to open NAME; if that fails, look for it in the default script
+   directory, then in any directories specified with -L, without and
+   with EXTEND appended.  */
 
 static FILE *
 ldfile_find_command_file (const char *name, const char *extend)
 {
   search_dirs_type *search;
   FILE *result;
+  char *buffer;
+  static search_dirs_type *script_search;
 
   /* First try raw name.  */
   result = try_open (name, "");
-  if (result == NULL)
+  if (result != NULL)
+    return result;
+
+  if (!script_search)
     {
-      /* Try now prefixes.  */
-      for (search = search_head; search != NULL; search = search->next)
+      char *script_dir = find_scripts_dir ();
+      if (script_dir)
 	{
-	  char *buffer;
-
-	  buffer = concat (search->name, slash, name, (const char *) NULL);
-	  result = try_open (buffer, extend);
-	  free (buffer);
-	  if (result)
-	    break;
+	  search_dirs_type **save_tail_ptr = search_tail_ptr;
+	  search_tail_ptr = &script_search;
+	  ldfile_add_library_path (script_dir, TRUE);
+	  search_tail_ptr = save_tail_ptr;
 	}
+      if (!script_search)
+	script_search = search_head;
+      else
+	script_search->next = search_head;
+    }
+
+  /* Try now prefixes.  */
+  for (search = script_search; search != NULL; search = search->next)
+    {
+
+      buffer = concat (search->name, slash, name, (const char *) NULL);
+      result = try_open (buffer, extend);
+      free (buffer);
+      if (result)
+	break;
     }
 
   return result;
Index: ld/ldmain.c
===================================================================
RCS file: /cvs/src/src/ld/ldmain.c,v
retrieving revision 1.131
diff -u -p -r1.131 ldmain.c
--- ld/ldmain.c	12 Jul 2008 08:54:13 -0000	1.131
+++ ld/ldmain.c	9 Aug 2008 04:59:02 -0000
@@ -114,8 +114,6 @@ static const char *get_sysroot
   (int, char **);
 static char *get_emulation
   (int, char **);
-static void set_scripts_dir
-  (void);
 static bfd_boolean add_archive_element
   (struct bfd_link_info *, bfd *, const char *);
 static bfd_boolean multiple_definition
@@ -358,10 +356,6 @@ main (int argc, char **argv)
 	link_info.discard = discard_all;
     }
 
-  /* This essentially adds another -L directory so this must be done after
-     the -L's in argv have been processed.  */
-  set_scripts_dir ();
-
   /* If we have not already opened and parsed a linker script,
      try the default script from command line first.  */
   if (saved_script_handle == NULL
@@ -671,106 +665,6 @@ get_emulation (int argc, char **argv)
   return emulation;
 }
 
-/* If directory DIR contains an "ldscripts" subdirectory,
-   add DIR to the library search path and return TRUE,
-   else return FALSE.  */
-
-static bfd_boolean
-check_for_scripts_dir (char *dir)
-{
-  size_t dirlen;
-  char *buf;
-  struct stat s;
-  bfd_boolean res;
-
-  dirlen = strlen (dir);
-  /* sizeof counts the terminating NUL.  */
-  buf = xmalloc (dirlen + sizeof ("/ldscripts"));
-  sprintf (buf, "%s/ldscripts", dir);
-
-  res = stat (buf, &s) == 0 && S_ISDIR (s.st_mode);
-  free (buf);
-  if (res)
-    ldfile_add_library_path (dir, FALSE);
-  return res;
-}
-
-/* Set the default directory for finding script files.
-   Libraries will be searched for here too, but that's ok.
-   We look for the "ldscripts" directory in:
-
-   SCRIPTDIR (passed from Makefile)
-	     (adjusted according to the current location of the binary)
-   SCRIPTDIR (passed from Makefile)
-   the dir where this program is (for using it from the build tree)
-   the dir where this program is/../lib
-	     (for installing the tool suite elsewhere).  */
-
-static void
-set_scripts_dir (void)
-{
-  char *end, *dir;
-  size_t dirlen;
-  bfd_boolean found;
-
-  dir = make_relative_prefix (program_name, BINDIR, SCRIPTDIR);
-  if (dir)
-    {
-      found = check_for_scripts_dir (dir);
-      free (dir);
-      if (found)
-	return;
-    }
-
-  dir = make_relative_prefix (program_name, TOOLBINDIR, SCRIPTDIR);
-  if (dir)
-    {
-      found = check_for_scripts_dir (dir);
-      free (dir);
-      if (found)
-	return;
-    }
-
-  if (check_for_scripts_dir (SCRIPTDIR))
-    /* We've been installed normally.  */
-    return;
-
-  /* Look for "ldscripts" in the dir where our binary is.  */
-  end = strrchr (program_name, '/');
-#ifdef HAVE_DOS_BASED_FILE_SYSTEM
-  {
-    /* We could have \foo\bar, or /foo\bar.  */
-    char *bslash = strrchr (program_name, '\\');
-
-    if (end == NULL || (bslash != NULL && bslash > end))
-      end = bslash;
-  }
-#endif
-
-  if (end == NULL)
-    /* Don't look for ldscripts in the current directory.  There is
-       too much potential for confusion.  */
-    return;
-
-  dirlen = end - program_name;
-  /* Make a copy of program_name in dir.
-     Leave room for later "/../lib".  */
-  dir = xmalloc (dirlen + 8);
-  strncpy (dir, program_name, dirlen);
-  dir[dirlen] = '\0';
-
-  if (check_for_scripts_dir (dir))
-    {
-      free (dir);
-      return;
-    }
-
-  /* Look for "ldscripts" in <the dir where our binary is>/../lib.  */
-  strcpy (dir + dirlen, "/../lib");
-  check_for_scripts_dir (dir);
-  free (dir);
-}
-
 void
 add_ysym (const char *name)
 {

-- 
Alan Modra
Australia Development Lab, IBM



More information about the Binutils mailing list