collect2.c (main): Call find_file_set_debug.
authorMeador Inge <meadori@codesourcery.com>
Tue, 27 Nov 2012 16:55:47 +0000 (16:55 +0000)
committerMeador Inge <meadori@gcc.gnu.org>
Tue, 27 Nov 2012 16:55:47 +0000 (16:55 +0000)
2012-11-27  Meador Inge  <meadori@codesourcery.com>

* collect2.c (main): Call find_file_set_debug.
(find_a_find, add_prefix, prefix_from_env, prefix_from_string):
Factor out into ...
* file-find.c (New file): ... here and ...
* file-find.h (New file): ... here.
* gcc-ar.c (standard_exec_prefix): New variable.
(standard_libexec_prefix): Ditto.
(tooldir_base_prefix) Ditto.
(self_exec_prefix): Ditto.
(self_libexec_prefix): Ditto.
(self_tooldir_prefix): Ditto.
(target_version): Ditto.
(path): Ditto.
(target_path): Ditto.
(setup_prefixes): New function.
(main): Rework how wrapped programs are found.
* Makefile.in (OBJS-libcommon-target): Add file-find.o.
(AR_OBJS): New variable.
(gcc-ar$(exeext)): Add dependency on $(AR_OBJS).
(gcc-nm$(exeext)): Ditto.
(gcc-ranlib(exeext)): Ditto.
(COLLECT2_OBJS): Add file-find.o.
(collect2.o): Add file-find.h prerequisite.
(file-find.o): New rule.

From-SVN: r193859

gcc/ChangeLog
gcc/Makefile.in
gcc/collect2.c
gcc/file-find.c [new file with mode: 0644]
gcc/file-find.h [new file with mode: 0644]
gcc/gcc-ar.c

index 7ae020a9dba8a648eb35134b98976b4fc30cf879..e41e34d323029d3eb72439276d5be65ad640eb46 100644 (file)
@@ -1,3 +1,30 @@
+2012-11-27  Meador Inge  <meadori@codesourcery.com>
+
+       * collect2.c (main): Call find_file_set_debug.
+       (find_a_find, add_prefix, prefix_from_env, prefix_from_string):
+       Factor out into ...
+       * file-find.c (New file): ... here and ...
+       * file-find.h (New file): ... here.
+       * gcc-ar.c (standard_exec_prefix): New variable.
+       (standard_libexec_prefix): Ditto.
+       (tooldir_base_prefix) Ditto.
+       (self_exec_prefix): Ditto.
+       (self_libexec_prefix): Ditto.
+       (self_tooldir_prefix): Ditto.
+       (target_version): Ditto.
+       (path): Ditto.
+       (target_path): Ditto.
+       (setup_prefixes): New function.
+       (main): Rework how wrapped programs are found.
+       * Makefile.in (OBJS-libcommon-target): Add file-find.o.
+       (AR_OBJS): New variable.
+       (gcc-ar$(exeext)): Add dependency on $(AR_OBJS).
+       (gcc-nm$(exeext)): Ditto.
+       (gcc-ranlib(exeext)): Ditto.
+       (COLLECT2_OBJS): Add file-find.o.
+       (collect2.o): Add file-find.h prerequisite.
+       (file-find.o): New rule.
+
 2010-11-27  Dehao Chen  <dehao@google.com>
 
        * ipa-prop.c (ipa_modify_call_arguments): Set loc correctly.
index 44f1e0858661f8b5c1ae7d702fec466ab1346902..8f8316fb6e7bd878352ea386716a26ee7992a77c 100644 (file)
@@ -1471,7 +1471,7 @@ OBJS-libcommon = diagnostic.o pretty-print.o intl.o input.o version.o
 # compiler and containing target-dependent code.
 OBJS-libcommon-target = $(common_out_object_file) prefix.o params.o \
        opts.o opts-common.o options.o vec.o hooks.o common/common-targhooks.o \
-       hash-table.o
+       hash-table.o file-find.o
 
 # This lists all host objects for the front ends.
 ALL_HOST_FRONTEND_OBJS = $(foreach v,$(CONFIG_LANGUAGES),$($(v)_OBJS))
@@ -1852,19 +1852,20 @@ graph.o: graph.c $(SYSTEM_H) coretypes.h $(TM_H) toplev.h $(DIAGNOSTIC_CORE_H) $
 sbitmap.o: sbitmap.c sbitmap.h $(CONFIG_H) $(SYSTEM_H) coretypes.h
 sparseset.o: sparseset.c $(SYSTEM_H) sparseset.h $(CONFIG_H)
 
+AR_OBJS = file-find.o
 AR_LIBS = @COLLECT2_LIBS@
 
-gcc-ar$(exeext): gcc-ar.o $(LIBDEPS)
+gcc-ar$(exeext): gcc-ar.o $(AR_OBJS) $(LIBDEPS)
        +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) gcc-ar.o -o $@ \
-               $(LIBS) $(AR_LIBS)
+               $(AR_OBJS) $(LIBS) $(AR_LIBS)
 
-gcc-nm$(exeext): gcc-nm.o $(LIBDEPS)
+gcc-nm$(exeext): gcc-nm.o $(AR_OBJS) $(LIBDEPS)
        +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) gcc-nm.o -o $@ \
-               $(LIBS) $(AR_LIBS)
+               $(AR_OBJS) $(LIBS) $(AR_LIBS)
 
-gcc-ranlib$(exeext): gcc-ranlib.o $(LIBDEPS)
+gcc-ranlib$(exeext): gcc-ranlib.o $(AR_OBJS) $(LIBDEPS)
        +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) gcc-ranlib.o -o $@ \
-               $(LIBS) $(AR_LIBS)
+               $(AR_OBJS) $(LIBS) $(AR_LIBS)
 
 CFLAGS-gcc-ar.o += $(DRIVER_DEFINES) \
        -DTARGET_MACHINE=\"$(target_noncanonical)\" \
@@ -1892,7 +1893,7 @@ gcc-ranlib.c: gcc-ar.c
 gcc-nm.c: gcc-ar.c
        cp $^ $@
 
-COLLECT2_OBJS = collect2.o collect2-aix.o tlink.o vec.o ggc-none.o
+COLLECT2_OBJS = collect2.o collect2-aix.o tlink.o vec.o ggc-none.o file-find.o
 COLLECT2_LIBS = @COLLECT2_LIBS@
 collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
 # Don't try modifying collect2 (aka ld) in place--it might be linking this.
@@ -1904,7 +1905,7 @@ CFLAGS-collect2.o += -DTARGET_MACHINE=\"$(target_noncanonical)\" \
        @TARGET_SYSTEM_ROOT_DEFINE@
 collect2.o : collect2.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) intl.h \
        $(OBSTACK_H) $(DEMANGLE_H) collect2.h collect2-aix.h version.h \
-       $(DIAGNOSTIC_H)
+       $(DIAGNOSTIC_H) file-find.h
 
 collect2-aix.o : collect2-aix.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
     collect2-aix.h
@@ -3425,6 +3426,7 @@ hw-doloop.o : hw-doloop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h $(TM_H)
    $(RTL_H) $(FLAGS_H) $(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) $(TM_P_H) \
    $(DF_H) $(CFGLOOP_H) $(RECOG_H) $(TARGET_H) \
    $(REGS_H) hw-doloop.h
+file-find.o: file-find.c $(CONFIG_H) $(SYSTEM_H) file-find.h
 $(out_object_file): $(out_file) $(CONFIG_H) coretypes.h $(TM_H) $(TREE_H) \
    $(RTL_H) $(REGS_H) hard-reg-set.h insn-config.h conditions.h \
    output.h $(INSN_ATTR_H) $(SYSTEM_H) toplev.h $(DIAGNOSTIC_CORE_H) \
index fc69e2f71bf224f6a5395a0171723349bc787424..49c40301d6ca605cd290bb47d1ac029303ea70ef 100644 (file)
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "filenames.h"
+#include "file-find.h"
 
 /* TARGET_64BIT may be defined to use driver specific functionality. */
 #undef TARGET_64BIT
@@ -243,22 +244,6 @@ static const char *target_system_root = "";
    would leave untouched.  */
 bool may_unlink_output_file = false;
 
-/* Structure to hold all the directories in which to search for files to
-   execute.  */
-
-struct prefix_list
-{
-  const char *prefix;         /* String to prepend to the path.  */
-  struct prefix_list *next;   /* Next in linked list.  */
-};
-
-struct path_prefix
-{
-  struct prefix_list *plist;  /* List of prefixes to try */
-  int max_len;                /* Max length of a prefix in PLIST */
-  const char *name;           /* Name of this list (used in config stuff) */
-};
-
 #ifdef COLLECT_EXPORT_LIST
 /* Lists to keep libraries to be scanned for global constructors/destructors.  */
 static struct head libs;                    /* list of libraries */
@@ -302,10 +287,6 @@ typedef enum {
 static symkind is_ctor_dtor (const char *);
 
 static void handler (int);
-static char *find_a_file (struct path_prefix *, const char *);
-static void add_prefix (struct path_prefix *, const char *);
-static void prefix_from_env (const char *, struct path_prefix *);
-static void prefix_from_string (const char *, struct path_prefix *);
 static void do_wait (const char *, struct pex_obj *);
 static void fork_execute (const char *, char **);
 static void maybe_unlink (const char *);
@@ -653,168 +634,6 @@ static const char *const target_machine = TARGET_MACHINE;
 
    Return 0 if not found, otherwise return its name, allocated with malloc.  */
 
-static char *
-find_a_file (struct path_prefix *pprefix, const char *name)
-{
-  char *temp;
-  struct prefix_list *pl;
-  int len = pprefix->max_len + strlen (name) + 1;
-
-  if (debug)
-    fprintf (stderr, "Looking for '%s'\n", name);
-
-#ifdef HOST_EXECUTABLE_SUFFIX
-  len += strlen (HOST_EXECUTABLE_SUFFIX);
-#endif
-
-  temp = XNEWVEC (char, len);
-
-  /* Determine the filename to execute (special case for absolute paths).  */
-
-  if (IS_ABSOLUTE_PATH (name))
-    {
-      if (access (name, X_OK) == 0)
-       {
-         strcpy (temp, name);
-
-         if (debug)
-           fprintf (stderr, "  - found: absolute path\n");
-
-         return temp;
-       }
-
-#ifdef HOST_EXECUTABLE_SUFFIX
-       /* Some systems have a suffix for executable files.
-          So try appending that.  */
-      strcpy (temp, name);
-       strcat (temp, HOST_EXECUTABLE_SUFFIX);
-
-       if (access (temp, X_OK) == 0)
-         return temp;
-#endif
-
-      if (debug)
-       fprintf (stderr, "  - failed to locate using absolute path\n");
-    }
-  else
-    for (pl = pprefix->plist; pl; pl = pl->next)
-      {
-       struct stat st;
-
-       strcpy (temp, pl->prefix);
-       strcat (temp, name);
-
-       if (stat (temp, &st) >= 0
-           && ! S_ISDIR (st.st_mode)
-           && access (temp, X_OK) == 0)
-         return temp;
-
-#ifdef HOST_EXECUTABLE_SUFFIX
-       /* Some systems have a suffix for executable files.
-          So try appending that.  */
-       strcat (temp, HOST_EXECUTABLE_SUFFIX);
-
-       if (stat (temp, &st) >= 0
-           && ! S_ISDIR (st.st_mode)
-           && access (temp, X_OK) == 0)
-         return temp;
-#endif
-      }
-
-  if (debug && pprefix->plist == NULL)
-    fprintf (stderr, "  - failed: no entries in prefix list\n");
-
-  free (temp);
-  return 0;
-}
-
-/* Add an entry for PREFIX to prefix list PPREFIX.  */
-
-static void
-add_prefix (struct path_prefix *pprefix, const char *prefix)
-{
-  struct prefix_list *pl, **prev;
-  int len;
-
-  if (pprefix->plist)
-    {
-      for (pl = pprefix->plist; pl->next; pl = pl->next)
-       ;
-      prev = &pl->next;
-    }
-  else
-    prev = &pprefix->plist;
-
-  /* Keep track of the longest prefix.  */
-
-  len = strlen (prefix);
-  if (len > pprefix->max_len)
-    pprefix->max_len = len;
-
-  pl = XNEW (struct prefix_list);
-  pl->prefix = xstrdup (prefix);
-
-  if (*prev)
-    pl->next = *prev;
-  else
-    pl->next = (struct prefix_list *) 0;
-  *prev = pl;
-}
-\f
-/* Take the value of the environment variable ENV, break it into a path, and
-   add of the entries to PPREFIX.  */
-
-static void
-prefix_from_env (const char *env, struct path_prefix *pprefix)
-{
-  const char *p;
-  p = getenv (env);
-
-  if (p)
-    prefix_from_string (p, pprefix);
-}
-
-static void
-prefix_from_string (const char *p, struct path_prefix *pprefix)
-{
-  const char *startp, *endp;
-  char *nstore = XNEWVEC (char, strlen (p) + 3);
-
-  if (debug)
-    fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR);
-
-  startp = endp = p;
-  while (1)
-    {
-      if (*endp == PATH_SEPARATOR || *endp == 0)
-       {
-         strncpy (nstore, startp, endp-startp);
-         if (endp == startp)
-           {
-             strcpy (nstore, "./");
-           }
-         else if (! IS_DIR_SEPARATOR (endp[-1]))
-           {
-             nstore[endp-startp] = DIR_SEPARATOR;
-             nstore[endp-startp+1] = 0;
-           }
-         else
-           nstore[endp-startp] = 0;
-
-         if (debug)
-           fprintf (stderr, "  - add prefix: %s\n", nstore);
-
-         add_prefix (pprefix, nstore);
-         if (*endp == 0)
-           break;
-         endp = startp = endp + 1;
-       }
-      else
-       endp++;
-    }
-  free (nstore);
-}
-
 #ifdef OBJECT_FORMAT_NONE
 
 /* Add an entry for the object file NAME to object file list LIST.
@@ -1198,6 +1017,7 @@ main (int argc, char **argv)
 #endif
       }
     vflag = debug;
+    find_file_set_debug (debug);
     if (no_partition && lto_mode == LTO_MODE_WHOPR)
       lto_mode = LTO_MODE_LTO;
   }
diff --git a/gcc/file-find.c b/gcc/file-find.c
new file mode 100644 (file)
index 0000000..fcc2561
--- /dev/null
@@ -0,0 +1,194 @@
+/* Utility functions for finding files relative to GCC binaries.
+   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011, 2012
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "filenames.h"
+#include "file-find.h"
+
+static bool debug = false;
+
+void
+find_file_set_debug(bool debug_state)
+{
+  debug = debug_state;
+}
+
+char *
+find_a_file (struct path_prefix *pprefix, const char *name)
+{
+  char *temp;
+  struct prefix_list *pl;
+  int len = pprefix->max_len + strlen (name) + 1;
+
+  if (debug)
+    fprintf (stderr, "Looking for '%s'\n", name);
+
+#ifdef HOST_EXECUTABLE_SUFFIX
+  len += strlen (HOST_EXECUTABLE_SUFFIX);
+#endif
+
+  temp = XNEWVEC (char, len);
+
+  /* Determine the filename to execute (special case for absolute paths).  */
+
+  if (IS_ABSOLUTE_PATH (name))
+    {
+      if (access (name, X_OK) == 0)
+       {
+         strcpy (temp, name);
+
+         if (debug)
+           fprintf (stderr, "  - found: absolute path\n");
+
+         return temp;
+       }
+
+#ifdef HOST_EXECUTABLE_SUFFIX
+       /* Some systems have a suffix for executable files.
+          So try appending that.  */
+      strcpy (temp, name);
+       strcat (temp, HOST_EXECUTABLE_SUFFIX);
+
+       if (access (temp, X_OK) == 0)
+         return temp;
+#endif
+
+      if (debug)
+       fprintf (stderr, "  - failed to locate using absolute path\n");
+    }
+  else
+    for (pl = pprefix->plist; pl; pl = pl->next)
+      {
+       struct stat st;
+
+       strcpy (temp, pl->prefix);
+       strcat (temp, name);
+
+       if (stat (temp, &st) >= 0
+           && ! S_ISDIR (st.st_mode)
+           && access (temp, X_OK) == 0)
+         return temp;
+
+#ifdef HOST_EXECUTABLE_SUFFIX
+       /* Some systems have a suffix for executable files.
+          So try appending that.  */
+       strcat (temp, HOST_EXECUTABLE_SUFFIX);
+
+       if (stat (temp, &st) >= 0
+           && ! S_ISDIR (st.st_mode)
+           && access (temp, X_OK) == 0)
+         return temp;
+#endif
+      }
+
+  if (debug && pprefix->plist == NULL)
+    fprintf (stderr, "  - failed: no entries in prefix list\n");
+
+  free (temp);
+  return 0;
+}
+
+/* Add an entry for PREFIX to prefix list PPREFIX.  */
+
+void
+add_prefix (struct path_prefix *pprefix, const char *prefix)
+{
+  struct prefix_list *pl, **prev;
+  int len;
+
+  if (pprefix->plist)
+    {
+      for (pl = pprefix->plist; pl->next; pl = pl->next)
+       ;
+      prev = &pl->next;
+    }
+  else
+    prev = &pprefix->plist;
+
+  /* Keep track of the longest prefix.  */
+
+  len = strlen (prefix);
+  if (len > pprefix->max_len)
+    pprefix->max_len = len;
+
+  pl = XNEW (struct prefix_list);
+  pl->prefix = xstrdup (prefix);
+
+  if (*prev)
+    pl->next = *prev;
+  else
+    pl->next = (struct prefix_list *) 0;
+  *prev = pl;
+}
+
+/* Take the value of the environment variable ENV, break it into a path, and
+   add of the entries to PPREFIX.  */
+
+void
+prefix_from_env (const char *env, struct path_prefix *pprefix)
+{
+  const char *p;
+  p = getenv (env);
+
+  if (p)
+    prefix_from_string (p, pprefix);
+}
+
+void
+prefix_from_string (const char *p, struct path_prefix *pprefix)
+{
+  const char *startp, *endp;
+  char *nstore = XNEWVEC (char, strlen (p) + 3);
+
+  if (debug)
+    fprintf (stderr, "Convert string '%s' into prefixes, separator = '%c'\n", p, PATH_SEPARATOR);
+
+  startp = endp = p;
+  while (1)
+    {
+      if (*endp == PATH_SEPARATOR || *endp == 0)
+       {
+         strncpy (nstore, startp, endp-startp);
+         if (endp == startp)
+           {
+             strcpy (nstore, "./");
+           }
+         else if (! IS_DIR_SEPARATOR (endp[-1]))
+           {
+             nstore[endp-startp] = DIR_SEPARATOR;
+             nstore[endp-startp+1] = 0;
+           }
+         else
+           nstore[endp-startp] = 0;
+
+         if (debug)
+           fprintf (stderr, "  - add prefix: %s\n", nstore);
+
+         add_prefix (pprefix, nstore);
+         if (*endp == 0)
+           break;
+         endp = startp = endp + 1;
+       }
+      else
+       endp++;
+    }
+  free (nstore);
+}
diff --git a/gcc/file-find.h b/gcc/file-find.h
new file mode 100644 (file)
index 0000000..4c0182a
--- /dev/null
@@ -0,0 +1,47 @@
+/* Prototypes and data structures used for implementing functions for
+   finding files relative to GCC binaries.
+   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011, 2012
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_FILE_FIND_H
+#define GCC_FILE_FIND_H
+
+/* Structure to hold all the directories in which to search for files to
+   execute.  */
+
+struct prefix_list
+{
+  const char *prefix;         /* String to prepend to the path.  */
+  struct prefix_list *next;   /* Next in linked list.  */
+};
+
+struct path_prefix
+{
+  struct prefix_list *plist;  /* List of prefixes to try */
+  int max_len;                /* Max length of a prefix in PLIST */
+  const char *name;           /* Name of this list (used in config stuff) */
+};
+
+extern void find_file_set_debug (bool);
+extern char *find_a_file (struct path_prefix *, const char *);
+extern void add_prefix (struct path_prefix *, const char *);
+extern void prefix_from_env (const char *, struct path_prefix *);
+extern void prefix_from_string (const char *, struct path_prefix *);
+
+#endif /* GCC_FILE_FIND_H */
index 5f78378dea86ff09f1182b0f188ac9d8dd86b865..c614566bb7ce340448321e11ec63a6866e3d5c3b 100644 (file)
@@ -21,21 +21,110 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "libiberty.h"
+#include "file-find.h"
 
 #ifndef PERSONALITY
 #error "Please set personality"
 #endif
 
+/* The exec prefix as derived at compile-time from --prefix.  */
+
+static const char standard_exec_prefix[] = STANDARD_EXEC_PREFIX;
+
+/* The libexec prefix as derived at compile-time from --prefix.  */
+
 static const char standard_libexec_prefix[] = STANDARD_LIBEXEC_PREFIX;
+
+/* The bindir prefix as derived at compile-time from --prefix.  */
+
 static const char standard_bin_prefix[] = STANDARD_BINDIR_PREFIX;
-static const char *const target_machine = TARGET_MACHINE;
+
+/* A relative path to be used in finding the location of tools
+   relative to this program.  */
+
+static const char *const tooldir_base_prefix = TOOLDIR_BASE_PREFIX;
+
+/* The exec prefix as relocated from the location of this program.  */
+
+static const char *self_exec_prefix;
+
+/* The libexec prefix as relocated from the location of this program.  */
+
+static const char *self_libexec_prefix;
+
+/* The tools prefix as relocated from the location of this program.  */
+
+static const char *self_tooldir_prefix;
+
+/* The name of the machine that is being targeted.  */
+
+static const char *const target_machine = DEFAULT_TARGET_MACHINE;
+
+/* The target version.  */
+
+static const char *const target_version = DEFAULT_TARGET_VERSION;
+
+/* The collection of target specific path prefixes.  */
+
+static struct path_prefix target_path;
+
+/* The collection path prefixes.  */
+
+static struct path_prefix path;
+
+/* The directory separator.  */
 
 static const char dir_separator[] = { DIR_SEPARATOR, 0 };
 
+static void
+setup_prefixes (const char *exec_path)
+{
+  const char *self;
+
+  self = getenv ("GCC_EXEC_PREFIX");
+  if (!self)
+    self = exec_path;
+  else
+    self = concat (self, "gcc-" PERSONALITY, NULL);
+
+  /* Relocate the exec prefix.  */
+  self_exec_prefix = make_relative_prefix (self,
+                                          standard_bin_prefix,
+                                          standard_exec_prefix);
+  if (self_exec_prefix == NULL)
+    self_exec_prefix = standard_exec_prefix;
+
+  /* Relocate libexec prefix.  */
+  self_libexec_prefix = make_relative_prefix (self,
+                                             standard_bin_prefix,
+                                             standard_libexec_prefix);
+  if (self_libexec_prefix == NULL)
+    self_libexec_prefix = standard_libexec_prefix;
+
+
+  /* Build the relative path to the target-specific tool directory.  */
+  self_tooldir_prefix = concat (tooldir_base_prefix, target_machine,
+                               dir_separator, NULL);
+  self_tooldir_prefix = concat (self_exec_prefix, target_machine, 
+                               dir_separator, target_version, dir_separator,
+                               self_tooldir_prefix, NULL);
+
+  /* Add the target-specific tool bin prefix.  */
+  prefix_from_string (concat (self_tooldir_prefix, "bin", NULL), &target_path);
+
+  /* Add the target-specific libexec prefix.  */
+  self_libexec_prefix = concat (self_libexec_prefix, target_machine, 
+                               dir_separator, target_version,
+                               dir_separator, NULL);
+  prefix_from_string (self_libexec_prefix, &target_path);
+
+  /* Add path as a last resort.  */
+  prefix_from_env ("PATH", &path);
+}
+
 int 
 main(int ac, char **av)
 {
-  const char *nprefix;
   const char *exe_name;
   char *plugin;
   int k, status, err;
@@ -44,39 +133,37 @@ main(int ac, char **av)
   bool is_ar = !strcmp (PERSONALITY, "ar");
   int exit_code = FATAL_EXIT_CODE;
 
-  exe_name = PERSONALITY;
-#ifdef CROSS_DIRECTORY_STRUCTURE
-  exe_name = concat (target_machine, "-", exe_name, NULL);
-#endif
+  setup_prefixes (av[0]);
 
-  /* Find plugin */
-  /* XXX implement more magic from gcc.c? */
-  nprefix = getenv ("GCC_EXEC_PREFIX");
-  if (!nprefix)
-    nprefix = av[0];
-  else
-    nprefix = concat (nprefix, "gcc-" PERSONALITY, NULL);
-
-  nprefix = make_relative_prefix (nprefix,
-                                 standard_bin_prefix,
-                                 standard_libexec_prefix);
-  if (nprefix == NULL)
-    nprefix = standard_libexec_prefix;
-
-  plugin = concat (nprefix,
-                  dir_separator,
-                   DEFAULT_TARGET_MACHINE, 
-                  dir_separator,
-                  DEFAULT_TARGET_VERSION,
-                  dir_separator,
-                  LTOPLUGINSONAME,
-                  NULL);
-  if (access (plugin, R_OK))
+  /* Find the GCC LTO plugin */
+  plugin = find_a_file (&target_path, LTOPLUGINSONAME);
+  if (!plugin)
     {
-      fprintf (stderr, "%s: Cannot find plugin %s\n", av[0], plugin);
+      fprintf (stderr, "%s: Cannot find plugin '%s'\n", av[0], LTOPLUGINSONAME);
       exit (1);
     }
 
+  /* Find the wrapped binutils program.  */
+  exe_name = find_a_file (&target_path, PERSONALITY);
+  if (!exe_name)
+    {
+#ifdef CROSS_DIRECTORY_STRUCTURE
+      const char *cross_exe_name;
+
+      cross_exe_name = concat (target_machine, "-", PERSONALITY, NULL);
+      exe_name = find_a_file (&path, cross_exe_name);
+      if (!exe_name)
+       {
+         fprintf (stderr, "%s: Cannot find binary '%s'\n", av[0],
+                  cross_exe_name);
+         exit (1);
+       }
+#else
+      fprintf (stderr, "%s: Cannot find binary '%s'\n", av[0], PERSONALITY);
+      exit (1);
+#endif
+    }
+
   /* Create new command line with plugin */
   nargv = XCNEWVEC (const char *, ac + 4);
   nargv[0] = exe_name;