diff mbox

gcc-{ar,nm,ranlib}: Find binutils binaries relative to self

Message ID 1349383546-25548-1-git-send-email-meadori@codesourcery.com
State New
Headers show

Commit Message

Meador Inge Oct. 4, 2012, 8:45 p.m. UTC
Hi All,

Currently the gcc-{ar,nm,ranlib} utilities assume that binutils is in
path when invoking the wrapped binutils program.  This goes against the
accepted practice in GCC to find sub-programs relative to where the
GCC binaries are stored and to not make assumptions about the PATH.

This patch changes the gcc-{ar,nm,ranlib} utilities to do the same
by factoring out some utility code for finding files from collect2.c.
These functions are then leveraged to find the binutils programs.
Note that similar code exist in gcc.c.  Perhaps one day everything
can be merged to the file-find files.

Tested for Windows and GNU/Linux hosts and i686-pc-linux-gnu and
arm-none-eabi targets.  OK?

P.S. I am not quite sure what is best for the copyrights and contributed
by comments in the file-find* files I added since that code was just moved.
This patch drops the contributed by and keeps all the copyright dates from
collect2.c.

2012-10-04  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.

Comments

Meador Inge Oct. 10, 2012, 2:44 a.m. UTC | #1
Ping.

On 10/04/2012 03:45 PM, Meador Inge wrote:
> Hi All,
> 
> Currently the gcc-{ar,nm,ranlib} utilities assume that binutils is in
> path when invoking the wrapped binutils program.  This goes against the
> accepted practice in GCC to find sub-programs relative to where the
> GCC binaries are stored and to not make assumptions about the PATH.
> 
> This patch changes the gcc-{ar,nm,ranlib} utilities to do the same
> by factoring out some utility code for finding files from collect2.c.
> These functions are then leveraged to find the binutils programs.
> Note that similar code exist in gcc.c.  Perhaps one day everything
> can be merged to the file-find files.
> 
> Tested for Windows and GNU/Linux hosts and i686-pc-linux-gnu and
> arm-none-eabi targets.  OK?
> 
> P.S. I am not quite sure what is best for the copyrights and contributed
> by comments in the file-find* files I added since that code was just moved.
> This patch drops the contributed by and keeps all the copyright dates from
> collect2.c.
> 
> 2012-10-04  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.
> 
> Index: gcc/gcc-ar.c
> ===================================================================
> --- gcc/gcc-ar.c	(revision 192099)
> +++ gcc/gcc-ar.c	(working copy)
> @@ -21,21 +21,110 @@
>  #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,37 +133,35 @@
>    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);
> +  /* Find the GCC LTO plugin */
> +  plugin = find_a_file (&target_path, LTOPLUGINSONAME);
> +  if (!plugin)
> +    {
> +      fprintf (stderr, "%s: Cannot find plugin '%s'\n", av[0], LTOPLUGINSONAME);
> +      exit (1);
> +    }
>  
> -  nprefix = make_relative_prefix (nprefix,
> -				  standard_bin_prefix,
> -				  standard_libexec_prefix);
> -  if (nprefix == NULL)
> -    nprefix = standard_libexec_prefix;
> +  /* 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;
>  
> -  plugin = concat (nprefix,
> -		   dir_separator,
> -                   DEFAULT_TARGET_MACHINE, 
> -		   dir_separator,
> -		   DEFAULT_TARGET_VERSION,
> -	           dir_separator,
> -		   LTOPLUGINSONAME,
> -		   NULL);
> -  if (access (plugin, R_OK))
> -    {
> -      fprintf (stderr, "%s: Cannot find plugin %s\n", av[0], plugin);
> +      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 */
> Index: gcc/Makefile.in
> ===================================================================
> --- gcc/Makefile.in	(revision 192099)
> +++ gcc/Makefile.in	(working copy)
> @@ -1446,7 +1446,7 @@
>  # 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))
> @@ -1827,19 +1827,20 @@
>  ebitmap.o: ebitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(EBITMAP_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)\" \
> @@ -1867,7 +1868,7 @@
>  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.
> @@ -1879,7 +1880,7 @@
>  	@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
> @@ -3353,6 +3354,7 @@
>     $(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: gcc/file-find.c
> ===================================================================
> --- gcc/file-find.c	(revision 0)
> +++ gcc/file-find.c	(revision 0)
> @@ -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);
> +}
> Index: gcc/file-find.h
> ===================================================================
> --- gcc/file-find.h	(revision 0)
> +++ gcc/file-find.h	(revision 0)
> @@ -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: gcc/collect2.c
> ===================================================================
> --- gcc/collect2.c	(revision 192099)
> +++ gcc/collect2.c	(working copy)
> @@ -31,6 +31,7 @@
>  #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 @@
>     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 @@
>  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 @@
>  
>     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;
> -}
> -
> -/* 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 @@
>  #endif
>        }
>      vflag = debug;
> +    find_file_set_debug (debug);
>      if (no_partition && lto_mode == LTO_MODE_WHOPR)
>        lto_mode = LTO_MODE_LTO;
>    }
Meador Inge Oct. 18, 2012, 3:30 p.m. UTC | #2
Ping ^ 2.

On 10/09/2012 09:44 PM, Meador Inge wrote:
> Ping.
> 
> On 10/04/2012 03:45 PM, Meador Inge wrote:
>> Hi All,
>>
>> Currently the gcc-{ar,nm,ranlib} utilities assume that binutils is in
>> path when invoking the wrapped binutils program.  This goes against the
>> accepted practice in GCC to find sub-programs relative to where the
>> GCC binaries are stored and to not make assumptions about the PATH.
>>
>> This patch changes the gcc-{ar,nm,ranlib} utilities to do the same
>> by factoring out some utility code for finding files from collect2.c.
>> These functions are then leveraged to find the binutils programs.
>> Note that similar code exist in gcc.c.  Perhaps one day everything
>> can be merged to the file-find files.
>>
>> Tested for Windows and GNU/Linux hosts and i686-pc-linux-gnu and
>> arm-none-eabi targets.  OK?
>>
>> P.S. I am not quite sure what is best for the copyrights and contributed
>> by comments in the file-find* files I added since that code was just moved.
>> This patch drops the contributed by and keeps all the copyright dates from
>> collect2.c.
>>
>> 2012-10-04  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.
>>
>> Index: gcc/gcc-ar.c
>> ===================================================================
>> --- gcc/gcc-ar.c	(revision 192099)
>> +++ gcc/gcc-ar.c	(working copy)
>> @@ -21,21 +21,110 @@
>>  #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,37 +133,35 @@
>>    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);
>> +  /* Find the GCC LTO plugin */
>> +  plugin = find_a_file (&target_path, LTOPLUGINSONAME);
>> +  if (!plugin)
>> +    {
>> +      fprintf (stderr, "%s: Cannot find plugin '%s'\n", av[0], LTOPLUGINSONAME);
>> +      exit (1);
>> +    }
>>  
>> -  nprefix = make_relative_prefix (nprefix,
>> -				  standard_bin_prefix,
>> -				  standard_libexec_prefix);
>> -  if (nprefix == NULL)
>> -    nprefix = standard_libexec_prefix;
>> +  /* 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;
>>  
>> -  plugin = concat (nprefix,
>> -		   dir_separator,
>> -                   DEFAULT_TARGET_MACHINE, 
>> -		   dir_separator,
>> -		   DEFAULT_TARGET_VERSION,
>> -	           dir_separator,
>> -		   LTOPLUGINSONAME,
>> -		   NULL);
>> -  if (access (plugin, R_OK))
>> -    {
>> -      fprintf (stderr, "%s: Cannot find plugin %s\n", av[0], plugin);
>> +      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 */
>> Index: gcc/Makefile.in
>> ===================================================================
>> --- gcc/Makefile.in	(revision 192099)
>> +++ gcc/Makefile.in	(working copy)
>> @@ -1446,7 +1446,7 @@
>>  # 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))
>> @@ -1827,19 +1827,20 @@
>>  ebitmap.o: ebitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(EBITMAP_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)\" \
>> @@ -1867,7 +1868,7 @@
>>  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.
>> @@ -1879,7 +1880,7 @@
>>  	@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
>> @@ -3353,6 +3354,7 @@
>>     $(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: gcc/file-find.c
>> ===================================================================
>> --- gcc/file-find.c	(revision 0)
>> +++ gcc/file-find.c	(revision 0)
>> @@ -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);
>> +}
>> Index: gcc/file-find.h
>> ===================================================================
>> --- gcc/file-find.h	(revision 0)
>> +++ gcc/file-find.h	(revision 0)
>> @@ -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: gcc/collect2.c
>> ===================================================================
>> --- gcc/collect2.c	(revision 192099)
>> +++ gcc/collect2.c	(working copy)
>> @@ -31,6 +31,7 @@
>>  #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 @@
>>     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 @@
>>  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 @@
>>  
>>     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;
>> -}
>> -
>> -/* 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 @@
>>  #endif
>>        }
>>      vflag = debug;
>> +    find_file_set_debug (debug);
>>      if (no_partition && lto_mode == LTO_MODE_WHOPR)
>>        lto_mode = LTO_MODE_LTO;
>>    }
> 
>
Bernhard Reutner-Fischer Oct. 18, 2012, 6:33 p.m. UTC | #3
On 18 October 2012 17:30:20 Meador Inge <meadori@codesourcery.com> wrote:
> Ping ^ 2

Been a while but wasn't --with-build-sysroot for exactly this?
>
> On 10/09/2012 09:44 PM, Meador Inge wrote:
> > Ping.
> >
> > On 102012 03:45 PM, Meador Inge wrote:
> >> Hi All,
> >>
> >> Currently the gcc-{ar,nm,ranlib} utilities assume that binutils is in
> >> path when invoking the wrapped binutils program.  This goes against the
> >> accepted practice in GCC to find sub-programs relative to where the
> >> GCC binaries are stored and to not make assumptions about the PATH.
> >>
> >> This patch changes the gcc-{ar,nm,ranlib} utilities to do the same
> >> by factoring out some utility code for finding files from collect2.c.
> >> These functions are then leveraged to find the binutils programs.
> >> Note that similar code exist in gcc.c.  Perhaps one day everything
> >> can be merged to the file-find files.
> >>
> >> Tested for Windows and GNU/Linux hosts and i686-pc-linux-gnu and
> >> arm-none-eabi targets.


Sent with AquaMail for Android
http://www.aqua-mail.com
Meador Inge Oct. 19, 2012, 9:38 p.m. UTC | #4
On 10/18/2012 01:33 PM, Bernhard Reutner-Fischer wrote:

> On 18 October 2012 17:30:20 Meador Inge <meadori@codesourcery.com> wrote:
>> Ping ^ 2
> 
> Been a while but wasn't --with-build-sysroot for exactly this?

AFAICT, no.  --with-build-sysroot seems to be used for setting a different
sysroot to use for compiling target libraries while GCC is being built [1].
This patch fixes the gcc-{ar,nm,ranlib} programs that are built and deployed
with GCC to not rely on the current PATH when running the binutils programs
they are wrapping.

[1] http://gcc.gnu.org/install/configure.html
Meador Inge Oct. 19, 2012, 9:40 p.m. UTC | #5
CC'ing the LTO maintainers.

On 10/18/2012 10:30 AM, Meador Inge wrote:
> Ping ^ 2.
> 
> On 10/09/2012 09:44 PM, Meador Inge wrote:
>> Ping.
>>
>> On 10/04/2012 03:45 PM, Meador Inge wrote:
>>> Hi All,
>>>
>>> Currently the gcc-{ar,nm,ranlib} utilities assume that binutils is in
>>> path when invoking the wrapped binutils program.  This goes against the
>>> accepted practice in GCC to find sub-programs relative to where the
>>> GCC binaries are stored and to not make assumptions about the PATH.
>>>
>>> This patch changes the gcc-{ar,nm,ranlib} utilities to do the same
>>> by factoring out some utility code for finding files from collect2.c.
>>> These functions are then leveraged to find the binutils programs.
>>> Note that similar code exist in gcc.c.  Perhaps one day everything
>>> can be merged to the file-find files.
>>>
>>> Tested for Windows and GNU/Linux hosts and i686-pc-linux-gnu and
>>> arm-none-eabi targets.  OK?
>>>
>>> P.S. I am not quite sure what is best for the copyrights and contributed
>>> by comments in the file-find* files I added since that code was just moved.
>>> This patch drops the contributed by and keeps all the copyright dates from
>>> collect2.c.
>>>
>>> 2012-10-04  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.
>>>
>>> Index: gcc/gcc-ar.c
>>> ===================================================================
>>> --- gcc/gcc-ar.c	(revision 192099)
>>> +++ gcc/gcc-ar.c	(working copy)
>>> @@ -21,21 +21,110 @@
>>>  #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,37 +133,35 @@
>>>    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);
>>> +  /* Find the GCC LTO plugin */
>>> +  plugin = find_a_file (&target_path, LTOPLUGINSONAME);
>>> +  if (!plugin)
>>> +    {
>>> +      fprintf (stderr, "%s: Cannot find plugin '%s'\n", av[0], LTOPLUGINSONAME);
>>> +      exit (1);
>>> +    }
>>>  
>>> -  nprefix = make_relative_prefix (nprefix,
>>> -				  standard_bin_prefix,
>>> -				  standard_libexec_prefix);
>>> -  if (nprefix == NULL)
>>> -    nprefix = standard_libexec_prefix;
>>> +  /* 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;
>>>  
>>> -  plugin = concat (nprefix,
>>> -		   dir_separator,
>>> -                   DEFAULT_TARGET_MACHINE, 
>>> -		   dir_separator,
>>> -		   DEFAULT_TARGET_VERSION,
>>> -	           dir_separator,
>>> -		   LTOPLUGINSONAME,
>>> -		   NULL);
>>> -  if (access (plugin, R_OK))
>>> -    {
>>> -      fprintf (stderr, "%s: Cannot find plugin %s\n", av[0], plugin);
>>> +      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 */
>>> Index: gcc/Makefile.in
>>> ===================================================================
>>> --- gcc/Makefile.in	(revision 192099)
>>> +++ gcc/Makefile.in	(working copy)
>>> @@ -1446,7 +1446,7 @@
>>>  # 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))
>>> @@ -1827,19 +1827,20 @@
>>>  ebitmap.o: ebitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(EBITMAP_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)\" \
>>> @@ -1867,7 +1868,7 @@
>>>  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.
>>> @@ -1879,7 +1880,7 @@
>>>  	@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
>>> @@ -3353,6 +3354,7 @@
>>>     $(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: gcc/file-find.c
>>> ===================================================================
>>> --- gcc/file-find.c	(revision 0)
>>> +++ gcc/file-find.c	(revision 0)
>>> @@ -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);
>>> +}
>>> Index: gcc/file-find.h
>>> ===================================================================
>>> --- gcc/file-find.h	(revision 0)
>>> +++ gcc/file-find.h	(revision 0)
>>> @@ -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: gcc/collect2.c
>>> ===================================================================
>>> --- gcc/collect2.c	(revision 192099)
>>> +++ gcc/collect2.c	(working copy)
>>> @@ -31,6 +31,7 @@
>>>  #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 @@
>>>     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 @@
>>>  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 @@
>>>  
>>>     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;
>>> -}
>>> -
>>> -/* 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 @@
>>>  #endif
>>>        }
>>>      vflag = debug;
>>> +    find_file_set_debug (debug);
>>>      if (no_partition && lto_mode == LTO_MODE_WHOPR)
>>>        lto_mode = LTO_MODE_LTO;
>>>    }
>>
>>
> 
>
Meador Inge Oct. 29, 2012, 3:46 p.m. UTC | #6
Ping ^ 3.

On 10/18/2012 10:30 AM, Meador Inge wrote:
> Ping ^ 2.
> 
> On 10/09/2012 09:44 PM, Meador Inge wrote:
>> Ping.
>>
>> On 10/04/2012 03:45 PM, Meador Inge wrote:
>>> Hi All,
>>>
>>> Currently the gcc-{ar,nm,ranlib} utilities assume that binutils is in
>>> path when invoking the wrapped binutils program.  This goes against the
>>> accepted practice in GCC to find sub-programs relative to where the
>>> GCC binaries are stored and to not make assumptions about the PATH.
>>>
>>> This patch changes the gcc-{ar,nm,ranlib} utilities to do the same
>>> by factoring out some utility code for finding files from collect2.c.
>>> These functions are then leveraged to find the binutils programs.
>>> Note that similar code exist in gcc.c.  Perhaps one day everything
>>> can be merged to the file-find files.
>>>
>>> Tested for Windows and GNU/Linux hosts and i686-pc-linux-gnu and
>>> arm-none-eabi targets.  OK?
>>>
>>> P.S. I am not quite sure what is best for the copyrights and contributed
>>> by comments in the file-find* files I added since that code was just moved.
>>> This patch drops the contributed by and keeps all the copyright dates from
>>> collect2.c.
>>>
>>> 2012-10-04  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.
>>>
>>> Index: gcc/gcc-ar.c
>>> ===================================================================
>>> --- gcc/gcc-ar.c	(revision 192099)
>>> +++ gcc/gcc-ar.c	(working copy)
>>> @@ -21,21 +21,110 @@
>>>  #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,37 +133,35 @@
>>>    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);
>>> +  /* Find the GCC LTO plugin */
>>> +  plugin = find_a_file (&target_path, LTOPLUGINSONAME);
>>> +  if (!plugin)
>>> +    {
>>> +      fprintf (stderr, "%s: Cannot find plugin '%s'\n", av[0], LTOPLUGINSONAME);
>>> +      exit (1);
>>> +    }
>>>  
>>> -  nprefix = make_relative_prefix (nprefix,
>>> -				  standard_bin_prefix,
>>> -				  standard_libexec_prefix);
>>> -  if (nprefix == NULL)
>>> -    nprefix = standard_libexec_prefix;
>>> +  /* 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;
>>>  
>>> -  plugin = concat (nprefix,
>>> -		   dir_separator,
>>> -                   DEFAULT_TARGET_MACHINE, 
>>> -		   dir_separator,
>>> -		   DEFAULT_TARGET_VERSION,
>>> -	           dir_separator,
>>> -		   LTOPLUGINSONAME,
>>> -		   NULL);
>>> -  if (access (plugin, R_OK))
>>> -    {
>>> -      fprintf (stderr, "%s: Cannot find plugin %s\n", av[0], plugin);
>>> +      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 */
>>> Index: gcc/Makefile.in
>>> ===================================================================
>>> --- gcc/Makefile.in	(revision 192099)
>>> +++ gcc/Makefile.in	(working copy)
>>> @@ -1446,7 +1446,7 @@
>>>  # 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))
>>> @@ -1827,19 +1827,20 @@
>>>  ebitmap.o: ebitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(EBITMAP_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)\" \
>>> @@ -1867,7 +1868,7 @@
>>>  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.
>>> @@ -1879,7 +1880,7 @@
>>>  	@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
>>> @@ -3353,6 +3354,7 @@
>>>     $(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: gcc/file-find.c
>>> ===================================================================
>>> --- gcc/file-find.c	(revision 0)
>>> +++ gcc/file-find.c	(revision 0)
>>> @@ -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);
>>> +}
>>> Index: gcc/file-find.h
>>> ===================================================================
>>> --- gcc/file-find.h	(revision 0)
>>> +++ gcc/file-find.h	(revision 0)
>>> @@ -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: gcc/collect2.c
>>> ===================================================================
>>> --- gcc/collect2.c	(revision 192099)
>>> +++ gcc/collect2.c	(working copy)
>>> @@ -31,6 +31,7 @@
>>>  #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 @@
>>>     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 @@
>>>  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 @@
>>>  
>>>     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;
>>> -}
>>> -
>>> -/* 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 @@
>>>  #endif
>>>        }
>>>      vflag = debug;
>>> +    find_file_set_debug (debug);
>>>      if (no_partition && lto_mode == LTO_MODE_WHOPR)
>>>        lto_mode = LTO_MODE_LTO;
>>>    }
>>
>>
> 
>
Meador Inge Nov. 7, 2012, 9:51 p.m. UTC | #7
Ping ^ 4.

On 10/29/2012 10:46 AM, Meador Inge wrote:
> Ping ^ 3.
> 
> On 10/18/2012 10:30 AM, Meador Inge wrote:
>> Ping ^ 2.
>>
>> On 10/09/2012 09:44 PM, Meador Inge wrote:
>>> Ping.
>>>
>>> On 10/04/2012 03:45 PM, Meador Inge wrote:
>>>> Hi All,
>>>>
>>>> Currently the gcc-{ar,nm,ranlib} utilities assume that binutils is in
>>>> path when invoking the wrapped binutils program.  This goes against the
>>>> accepted practice in GCC to find sub-programs relative to where the
>>>> GCC binaries are stored and to not make assumptions about the PATH.
>>>>
>>>> This patch changes the gcc-{ar,nm,ranlib} utilities to do the same
>>>> by factoring out some utility code for finding files from collect2.c.
>>>> These functions are then leveraged to find the binutils programs.
>>>> Note that similar code exist in gcc.c.  Perhaps one day everything
>>>> can be merged to the file-find files.
>>>>
>>>> Tested for Windows and GNU/Linux hosts and i686-pc-linux-gnu and
>>>> arm-none-eabi targets.  OK?
>>>>
>>>> P.S. I am not quite sure what is best for the copyrights and contributed
>>>> by comments in the file-find* files I added since that code was just moved.
>>>> This patch drops the contributed by and keeps all the copyright dates from
>>>> collect2.c.
>>>>
>>>> 2012-10-04  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.
>>>>
>>>> Index: gcc/gcc-ar.c
>>>> ===================================================================
>>>> --- gcc/gcc-ar.c	(revision 192099)
>>>> +++ gcc/gcc-ar.c	(working copy)
>>>> @@ -21,21 +21,110 @@
>>>>  #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,37 +133,35 @@
>>>>    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);
>>>> +  /* Find the GCC LTO plugin */
>>>> +  plugin = find_a_file (&target_path, LTOPLUGINSONAME);
>>>> +  if (!plugin)
>>>> +    {
>>>> +      fprintf (stderr, "%s: Cannot find plugin '%s'\n", av[0], LTOPLUGINSONAME);
>>>> +      exit (1);
>>>> +    }
>>>>  
>>>> -  nprefix = make_relative_prefix (nprefix,
>>>> -				  standard_bin_prefix,
>>>> -				  standard_libexec_prefix);
>>>> -  if (nprefix == NULL)
>>>> -    nprefix = standard_libexec_prefix;
>>>> +  /* 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;
>>>>  
>>>> -  plugin = concat (nprefix,
>>>> -		   dir_separator,
>>>> -                   DEFAULT_TARGET_MACHINE, 
>>>> -		   dir_separator,
>>>> -		   DEFAULT_TARGET_VERSION,
>>>> -	           dir_separator,
>>>> -		   LTOPLUGINSONAME,
>>>> -		   NULL);
>>>> -  if (access (plugin, R_OK))
>>>> -    {
>>>> -      fprintf (stderr, "%s: Cannot find plugin %s\n", av[0], plugin);
>>>> +      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 */
>>>> Index: gcc/Makefile.in
>>>> ===================================================================
>>>> --- gcc/Makefile.in	(revision 192099)
>>>> +++ gcc/Makefile.in	(working copy)
>>>> @@ -1446,7 +1446,7 @@
>>>>  # 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))
>>>> @@ -1827,19 +1827,20 @@
>>>>  ebitmap.o: ebitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(EBITMAP_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)\" \
>>>> @@ -1867,7 +1868,7 @@
>>>>  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.
>>>> @@ -1879,7 +1880,7 @@
>>>>  	@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
>>>> @@ -3353,6 +3354,7 @@
>>>>     $(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: gcc/file-find.c
>>>> ===================================================================
>>>> --- gcc/file-find.c	(revision 0)
>>>> +++ gcc/file-find.c	(revision 0)
>>>> @@ -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);
>>>> +}
>>>> Index: gcc/file-find.h
>>>> ===================================================================
>>>> --- gcc/file-find.h	(revision 0)
>>>> +++ gcc/file-find.h	(revision 0)
>>>> @@ -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: gcc/collect2.c
>>>> ===================================================================
>>>> --- gcc/collect2.c	(revision 192099)
>>>> +++ gcc/collect2.c	(working copy)
>>>> @@ -31,6 +31,7 @@
>>>>  #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 @@
>>>>     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 @@
>>>>  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 @@
>>>>  
>>>>     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;
>>>> -}
>>>> -
>>>> -/* 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 @@
>>>>  #endif
>>>>        }
>>>>      vflag = debug;
>>>> +    find_file_set_debug (debug);
>>>>      if (no_partition && lto_mode == LTO_MODE_WHOPR)
>>>>        lto_mode = LTO_MODE_LTO;
>>>>    }
>>>
>>>
>>
>>
> 
>
Richard Biener Nov. 26, 2012, 3:05 p.m. UTC | #8
On Wed, Nov 7, 2012 at 10:51 PM, Meador Inge <meadori@codesourcery.com> wrote:
> Ping ^ 4.

Ok.

Thanks,
Richard.

> On 10/29/2012 10:46 AM, Meador Inge wrote:
>> Ping ^ 3.
>>
>> On 10/18/2012 10:30 AM, Meador Inge wrote:
>>> Ping ^ 2.
>>>
>>> On 10/09/2012 09:44 PM, Meador Inge wrote:
>>>> Ping.
>>>>
>>>> On 10/04/2012 03:45 PM, Meador Inge wrote:
>>>>> Hi All,
>>>>>
>>>>> Currently the gcc-{ar,nm,ranlib} utilities assume that binutils is in
>>>>> path when invoking the wrapped binutils program.  This goes against the
>>>>> accepted practice in GCC to find sub-programs relative to where the
>>>>> GCC binaries are stored and to not make assumptions about the PATH.
>>>>>
>>>>> This patch changes the gcc-{ar,nm,ranlib} utilities to do the same
>>>>> by factoring out some utility code for finding files from collect2.c.
>>>>> These functions are then leveraged to find the binutils programs.
>>>>> Note that similar code exist in gcc.c.  Perhaps one day everything
>>>>> can be merged to the file-find files.
>>>>>
>>>>> Tested for Windows and GNU/Linux hosts and i686-pc-linux-gnu and
>>>>> arm-none-eabi targets.  OK?
>>>>>
>>>>> P.S. I am not quite sure what is best for the copyrights and contributed
>>>>> by comments in the file-find* files I added since that code was just moved.
>>>>> This patch drops the contributed by and keeps all the copyright dates from
>>>>> collect2.c.
>>>>>
>>>>> 2012-10-04  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.
>>>>>
>>>>> Index: gcc/gcc-ar.c
>>>>> ===================================================================
>>>>> --- gcc/gcc-ar.c   (revision 192099)
>>>>> +++ gcc/gcc-ar.c   (working copy)
>>>>> @@ -21,21 +21,110 @@
>>>>>  #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,37 +133,35 @@
>>>>>    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);
>>>>> +  /* Find the GCC LTO plugin */
>>>>> +  plugin = find_a_file (&target_path, LTOPLUGINSONAME);
>>>>> +  if (!plugin)
>>>>> +    {
>>>>> +      fprintf (stderr, "%s: Cannot find plugin '%s'\n", av[0], LTOPLUGINSONAME);
>>>>> +      exit (1);
>>>>> +    }
>>>>>
>>>>> -  nprefix = make_relative_prefix (nprefix,
>>>>> -                            standard_bin_prefix,
>>>>> -                            standard_libexec_prefix);
>>>>> -  if (nprefix == NULL)
>>>>> -    nprefix = standard_libexec_prefix;
>>>>> +  /* 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;
>>>>>
>>>>> -  plugin = concat (nprefix,
>>>>> -             dir_separator,
>>>>> -                   DEFAULT_TARGET_MACHINE,
>>>>> -             dir_separator,
>>>>> -             DEFAULT_TARGET_VERSION,
>>>>> -             dir_separator,
>>>>> -             LTOPLUGINSONAME,
>>>>> -             NULL);
>>>>> -  if (access (plugin, R_OK))
>>>>> -    {
>>>>> -      fprintf (stderr, "%s: Cannot find plugin %s\n", av[0], plugin);
>>>>> +      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 */
>>>>> Index: gcc/Makefile.in
>>>>> ===================================================================
>>>>> --- gcc/Makefile.in        (revision 192099)
>>>>> +++ gcc/Makefile.in        (working copy)
>>>>> @@ -1446,7 +1446,7 @@
>>>>>  # 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))
>>>>> @@ -1827,19 +1827,20 @@
>>>>>  ebitmap.o: ebitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(EBITMAP_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)\" \
>>>>> @@ -1867,7 +1868,7 @@
>>>>>  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.
>>>>> @@ -1879,7 +1880,7 @@
>>>>>    @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
>>>>> @@ -3353,6 +3354,7 @@
>>>>>     $(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: gcc/file-find.c
>>>>> ===================================================================
>>>>> --- gcc/file-find.c        (revision 0)
>>>>> +++ gcc/file-find.c        (revision 0)
>>>>> @@ -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);
>>>>> +}
>>>>> Index: gcc/file-find.h
>>>>> ===================================================================
>>>>> --- gcc/file-find.h        (revision 0)
>>>>> +++ gcc/file-find.h        (revision 0)
>>>>> @@ -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: gcc/collect2.c
>>>>> ===================================================================
>>>>> --- gcc/collect2.c (revision 192099)
>>>>> +++ gcc/collect2.c (working copy)
>>>>> @@ -31,6 +31,7 @@
>>>>>  #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 @@
>>>>>     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 @@
>>>>>  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 @@
>>>>>
>>>>>     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;
>>>>> -}
>>>>> -
>>>>> -/* 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 @@
>>>>>  #endif
>>>>>        }
>>>>>      vflag = debug;
>>>>> +    find_file_set_debug (debug);
>>>>>      if (no_partition && lto_mode == LTO_MODE_WHOPR)
>>>>>        lto_mode = LTO_MODE_LTO;
>>>>>    }
>>>>
>>>>
>>>
>>>
>>
>>
>
>
> --
> Meador Inge
> CodeSourcery / Mentor Embedded
> http://www.mentor.com/embedded-software
Meador Inge Nov. 27, 2012, 6:14 p.m. UTC | #9
On 11/26/2012 09:05 AM, Richard Biener wrote:

> On Wed, Nov 7, 2012 at 10:51 PM, Meador Inge <meadori@codesourcery.com> wrote:
>> Ping ^ 4.
> 
> Ok.

Thanks for the review.  Committed to trunk.
Matthias Klose June 19, 2013, 12:03 p.m. UTC | #10
Am 27.11.2012 19:14, schrieb Meador Inge:
> On 11/26/2012 09:05 AM, Richard Biener wrote:
> 
>> On Wed, Nov 7, 2012 at 10:51 PM, Meador Inge <meadori@codesourcery.com> wrote:
>>> Ping ^ 4.
>>
>> Ok.
> 
> Thanks for the review.  Committed to trunk.

This did break gcc-ar and gcc-nm; now a regression on the 4.8 branch.

$ gcc-ar-4.8 -h
gcc-ar-4.8: Cannot find plugin 'liblto_plugin.so'

the plugin is *not* installed with x permission flags (which seems to be the
standard for shared libraries).   You did change the code to use find_a_file
which searches only for files with the x bit set.

Work around is to install the plugin with the x bits set, or use some helper
function which doesn't look for the x bits.  I assume that wasn't catched,
because the plugin then was found in another location?

  Matthias
Jakub Jelinek June 19, 2013, 12:10 p.m. UTC | #11
On Wed, Jun 19, 2013 at 02:03:34PM +0200, Matthias Klose wrote:
> Am 27.11.2012 19:14, schrieb Meador Inge:
> > On 11/26/2012 09:05 AM, Richard Biener wrote:
> > 
> >> On Wed, Nov 7, 2012 at 10:51 PM, Meador Inge <meadori@codesourcery.com> wrote:
> >>> Ping ^ 4.
> >>
> >> Ok.
> > 
> > Thanks for the review.  Committed to trunk.
> 
> This did break gcc-ar and gcc-nm; now a regression on the 4.8 branch.
> 
> $ gcc-ar-4.8 -h
> gcc-ar-4.8: Cannot find plugin 'liblto_plugin.so'
> 
> the plugin is *not* installed with x permission flags (which seems to be the
> standard for shared libraries).   You did change the code to use find_a_file
> which searches only for files with the x bit set.

That actually is the standard for shared libraries, the linker creates
libraries with those permissions and libtool/automake installs them that way
too.  So if you override this, you need to cope with that decision.

	Jakub
Matthias Klose June 19, 2013, 12:17 p.m. UTC | #12
Am 19.06.2013 14:03, schrieb Matthias Klose:
> $ gcc-ar-4.8 -h
> gcc-ar-4.8: Cannot find plugin 'liblto_plugin.so'
> 
> the plugin is *not* installed with x permission flags (which seems to be the
> standard for shared libraries).   You did change the code to use find_a_file
> which searches only for files with the x bit set.
> 
> Work around is to install the plugin with the x bits set, or use some helper
> function which doesn't look for the x bits.  I assume that wasn't catched,
> because the plugin then was found in another location?

openend 57651 for that.

now, working around the permission bit, I get:

$ gcc-ar-4.8
gcc-ar-4.8: Cannot find binary 'ar'

so it only searches ar in the given paths, not on the path of the file system
(/usr/bin in this case)
diff mbox

Patch

Index: gcc/gcc-ar.c
===================================================================
--- gcc/gcc-ar.c	(revision 192099)
+++ gcc/gcc-ar.c	(working copy)
@@ -21,21 +21,110 @@ 
 #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,37 +133,35 @@ 
   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);
+  /* Find the GCC LTO plugin */
+  plugin = find_a_file (&target_path, LTOPLUGINSONAME);
+  if (!plugin)
+    {
+      fprintf (stderr, "%s: Cannot find plugin '%s'\n", av[0], LTOPLUGINSONAME);
+      exit (1);
+    }
 
-  nprefix = make_relative_prefix (nprefix,
-				  standard_bin_prefix,
-				  standard_libexec_prefix);
-  if (nprefix == NULL)
-    nprefix = standard_libexec_prefix;
+  /* 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;
 
-  plugin = concat (nprefix,
-		   dir_separator,
-                   DEFAULT_TARGET_MACHINE, 
-		   dir_separator,
-		   DEFAULT_TARGET_VERSION,
-	           dir_separator,
-		   LTOPLUGINSONAME,
-		   NULL);
-  if (access (plugin, R_OK))
-    {
-      fprintf (stderr, "%s: Cannot find plugin %s\n", av[0], plugin);
+      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 */
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 192099)
+++ gcc/Makefile.in	(working copy)
@@ -1446,7 +1446,7 @@ 
 # 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))
@@ -1827,19 +1827,20 @@ 
 ebitmap.o: ebitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(EBITMAP_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)\" \
@@ -1867,7 +1868,7 @@ 
 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.
@@ -1879,7 +1880,7 @@ 
 	@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
@@ -3353,6 +3354,7 @@ 
    $(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: gcc/file-find.c
===================================================================
--- gcc/file-find.c	(revision 0)
+++ gcc/file-find.c	(revision 0)
@@ -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);
+}
Index: gcc/file-find.h
===================================================================
--- gcc/file-find.h	(revision 0)
+++ gcc/file-find.h	(revision 0)
@@ -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: gcc/collect2.c
===================================================================
--- gcc/collect2.c	(revision 192099)
+++ gcc/collect2.c	(working copy)
@@ -31,6 +31,7 @@ 
 #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 @@ 
    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 @@ 
 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 @@ 
 
    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;
-}
-
-/* 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 @@ 
 #endif
       }
     vflag = debug;
+    find_file_set_debug (debug);
     if (no_partition && lto_mode == LTO_MODE_WHOPR)
       lto_mode = LTO_MODE_LTO;
   }