diff mbox

Add gcc-ar/nm/ranlib wrappers for slim LTO v2

Message ID 1319154948-22442-1-git-send-email-andi@firstfloor.org
State New
Headers show

Commit Message

Andi Kleen Oct. 20, 2011, 11:55 p.m. UTC
From: Andi Kleen <ak@linux.intel.com>

Slim LTO requires running ar/nm/ranlib with the LTO plugin. The most
convenient way to get this into existing Makefiles is using small
wrappers that pass the plugin. This matches how other compilers
(LLVM, icc) do this too.

My previous attempt at using shell scripts for this
http://gcc.gnu.org/ml/gcc-patches/2010-10/msg02471.html
was not approved. Here's another attempt using wrappers written
in C.  This adds wrappers add a --plugin argument before calling the
respective binutils utilities.

The logic gcc.c uses to find the files is very complicated. I didn't
try to replicate it 100% and left out some magic. I would be interested
if this simple method works for everyone or if more code needs
to be added. This only needs to support LTO supporting hosts of course.

I didn't add any documentation because the syntax is exactly the same as
the native ar/ranlib/nm.

v2: Address review comments. Makefile follows go now, use own binaries
for each sub program.

Passed bootstrap and test suite on x86_64-linux.

gcc/:
2011-10-19  Andi Kleen  <ak@linux.intel.com>

	* Makefile.in (MOSTLYCLEANFILES): Add gcc-ar/nm/ranlib.
	(native): Add gcc-ar, gcc-nm, gcc-ranlib.
	(AR_LIBS, gcc-ar, gcc-ar.o, gcc-ranlib, gcc-ranlib.o,
         gcc-nm, gcc-nm.o, gcc-ranlib.c, gcc-nm.c): Add.
	(install): Depend on install-gcc-ar.
	(install-gcc-ar): Add.
	(uninstall): Uninstall gcc-ar, gcc-nm, gcc-ranlib.
	* gcc-ar.c: Add new file.
---
 gcc/Makefile.in |   71 +++++++++++++++++++++++++++++++++++++++--
 gcc/gcc-ar.c    |   96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 164 insertions(+), 3 deletions(-)
 create mode 100644 gcc/gcc-ar.c

Comments

Andi Kleen Oct. 25, 2011, 8:23 a.m. UTC | #1
Andi Kleen <andi@firstfloor.org> writes:

> From: Andi Kleen <ak@linux.intel.com>
>
> Slim LTO requires running ar/nm/ranlib with the LTO plugin. The most
> convenient way to get this into existing Makefiles is using small
> wrappers that pass the plugin. This matches how other compilers
> (LLVM, icc) do this too.

Ping. Could someone please review
http://permalink.gmane.org/gmane.comp.gcc.patches/249338

Thanks,

-Andi
Diego Novillo Oct. 25, 2011, 2:46 p.m. UTC | #2
On 11-10-25 01:23 , Andi Kleen wrote:
> Andi Kleen<andi@firstfloor.org>  writes:
>
>> From: Andi Kleen<ak@linux.intel.com>
>>
>> Slim LTO requires running ar/nm/ranlib with the LTO plugin. The most
>> convenient way to get this into existing Makefiles is using small
>> wrappers that pass the plugin. This matches how other compilers
>> (LLVM, icc) do this too.
>
> Ping. Could someone please review
> http://permalink.gmane.org/gmane.comp.gcc.patches/249338

In my review queue.  Will try to get to it shortly.


Diego.
Richard Biener Oct. 28, 2011, 11:18 a.m. UTC | #3
On Fri, Oct 21, 2011 at 1:55 AM, Andi Kleen <andi@firstfloor.org> wrote:
> From: Andi Kleen <ak@linux.intel.com>
>
> Slim LTO requires running ar/nm/ranlib with the LTO plugin. The most
> convenient way to get this into existing Makefiles is using small
> wrappers that pass the plugin. This matches how other compilers
> (LLVM, icc) do this too.
>
> My previous attempt at using shell scripts for this
> http://gcc.gnu.org/ml/gcc-patches/2010-10/msg02471.html
> was not approved. Here's another attempt using wrappers written
> in C.  This adds wrappers add a --plugin argument before calling the
> respective binutils utilities.
>
> The logic gcc.c uses to find the files is very complicated. I didn't
> try to replicate it 100% and left out some magic. I would be interested
> if this simple method works for everyone or if more code needs
> to be added. This only needs to support LTO supporting hosts of course.
>
> I didn't add any documentation because the syntax is exactly the same as
> the native ar/ranlib/nm.
>
> v2: Address review comments. Makefile follows go now, use own binaries
> for each sub program.
>
> Passed bootstrap and test suite on x86_64-linux.

Ok.

We can improve/fix things if there is a need to as followup.

Thanks,
Richard.

> gcc/:
> 2011-10-19  Andi Kleen  <ak@linux.intel.com>
>
>        * Makefile.in (MOSTLYCLEANFILES): Add gcc-ar/nm/ranlib.
>        (native): Add gcc-ar, gcc-nm, gcc-ranlib.
>        (AR_LIBS, gcc-ar, gcc-ar.o, gcc-ranlib, gcc-ranlib.o,
>         gcc-nm, gcc-nm.o, gcc-ranlib.c, gcc-nm.c): Add.
>        (install): Depend on install-gcc-ar.
>        (install-gcc-ar): Add.
>        (uninstall): Uninstall gcc-ar, gcc-nm, gcc-ranlib.
>        * gcc-ar.c: Add new file.
> ---
>  gcc/Makefile.in |   71 +++++++++++++++++++++++++++++++++++++++--
>  gcc/gcc-ar.c    |   96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 164 insertions(+), 3 deletions(-)
>  create mode 100644 gcc/gcc-ar.c
>
> diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> index 6b28ef5..1b9987a 100644
> --- a/gcc/Makefile.in
> +++ b/gcc/Makefile.in
> @@ -1545,7 +1545,8 @@ MOSTLYCLEANFILES = insn-flags.h insn-config.h insn-codes.h \
>  genrtl.h gt-*.h gtype-*.h gtype-desc.c gtyp-input.list \
>  xgcc$(exeext) cpp$(exeext) cc1$(exeext) $(EXTRA_PASSES) \
>  $(EXTRA_PARTS) $(EXTRA_PROGRAMS) gcc-cross$(exeext) \
> - $(SPECS) collect2$(exeext) lto-wrapper$(exeext) \
> + $(SPECS) collect2$(exeext) gcc-ar$(exeext) gcc-nm$(exeext) \
> + gcc-ranlib$(exeext) \
>  gcov-iov$(build_exeext) gcov$(exeext) gcov-dump$(exeext) \
>  gengtype$(exeext) *.[0-9][0-9].* *.[si] *-checksum.c libbackend.a \
>  libcommon-target.a libcommon.a libgcc.mk
> @@ -1791,7 +1792,8 @@ rest.encap: lang.rest.encap
>  # This is what is made with the host's compiler
>  # whether making a cross compiler or not.
>  native: config.status auto-host.h build-@POSUB@ $(LANGUAGES) \
> -       $(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(COLLECT2) lto-wrapper$(exeext)
> +       $(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(COLLECT2) lto-wrapper$(exeext) \
> +       gcc-ar$(exeext) gcc-nm$(exeext) gcc-ranlib$(exeext)
>
>  ifeq ($(enable_plugin),yes)
>  native: gengtype$(exeext)
> @@ -2049,6 +2051,46 @@ sbitmap.o: sbitmap.c sbitmap.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(BASIC_BLOCK
>  ebitmap.o: ebitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(EBITMAP_H)
>  sparseset.o: sparseset.c $(SYSTEM_H) sparseset.h $(CONFIG_H)
>
> +AR_LIBS = @COLLECT2_LIBS@
> +
> +gcc-ar$(exeext): gcc-ar.o $(LIBDEPS)
> +       +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) gcc-ar.o -o $@ \
> +               $(LIBS) $(AR_LIBS)
> +
> +gcc-nm$(exeext): gcc-nm.o $(LIBDEPS)
> +       +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) gcc-nm.o -o $@ \
> +               $(LIBS) $(AR_LIBS)
> +
> +gcc-ranlib$(exeext): gcc-ranlib.o $(LIBDEPS)
> +       +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) gcc-ranlib.o -o $@ \
> +               $(LIBS) $(AR_LIBS)
> +
> +CFLAGS-gcc-ar.o += $(DRIVER_DEFINES) \
> +       -DTARGET_MACHINE=\"$(target_noncanonical)\" \
> +       @TARGET_SYSTEM_ROOT_DEFINE@ -DPERSONALITY=\"ar\"
> +
> +gcc-ar.o: gcc-ar.c $(CONFIG_H) $(SYSTEM_H) $(LIBIBERTY_H)
> +
> +CFLAGS-gcc-ranlib.o += $(DRIVER_DEFINES) \
> +       -DTARGET_MACHINE=\"$(target_noncanonical)\" \
> +       @TARGET_SYSTEM_ROOT_DEFINE@ -DPERSONALITY=\"ranlib\"
> +
> +gcc-ranlib.o: gcc-ranlib.c $(CONFIG_H) $(SYSTEM_H) $(LIBIBERTY_H)
> +
> +CFLAGS-gcc-nm.o += $(DRIVER_DEFINES) \
> +       -DTARGET_MACHINE=\"$(target_noncanonical)\" \
> +       @TARGET_SYSTEM_ROOT_DEFINE@ -DPERSONALITY=\"nm\"
> +
> +gcc-nm.o: gcc-nm.c $(CONFIG_H) $(SYSTEM_H) $(LIBIBERTY_H)
> +
> +# ??? the implicit rules dont trigger if the source file has a different name
> +# so copy instead
> +gcc-ranlib.c: gcc-ar.c
> +       cp $^ $@
> +
> +gcc-nm.c: gcc-ar.c
> +       cp $^ $@
> +
>  COLLECT2_OBJS = collect2.o collect2-aix.o tlink.o
>  COLLECT2_LIBS = @COLLECT2_LIBS@
>  collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
> @@ -4576,7 +4618,7 @@ maintainer-clean:
>  # broken is small.
>  install: install-common $(INSTALL_HEADERS) \
>     install-cpp install-man install-info install-@POSUB@ \
> -    install-driver install-lto-wrapper
> +    install-driver install-lto-wrapper install-gcc-ar
>
>  ifeq ($(enable_plugin),yes)
>  install: install-plugin
> @@ -4901,6 +4943,23 @@ install-collect2: collect2 installdirs
>  install-lto-wrapper: lto-wrapper$(exeext)
>        $(INSTALL_PROGRAM) lto-wrapper$(exeext) $(DESTDIR)$(libexecsubdir)/lto-wrapper$(exeext)
>
> +install-gcc-ar:
> +       set -e ; \
> +       for i in ar nm ranlib ; do \
> +         install_name=`echo gcc-$$i|sed '$(program_transform_name)'`$(exeext) ;\
> +         target_install_name=$(target_noncanonical)-`echo gcc-$$i|sed '$(program_transform_name)'`$(exeext) ; \
> +         binname=gcc-$$i$(exeext) ; \
> +         rm -f $(DESTDIR)$(bindir)/$$install_name ; \
> +         rm -f $(DESTDIR)$(bindir)/$$target_install_name ; \
> +         $(INSTALL_PROGRAM) $$binname $(DESTDIR)$(bindir)/$$install_name ;\
> +         if test -f $(DESTDIR)$(bindir)$$target_install_name ; then \
> +           :; \
> +         else \
> +           ( cd $(DESTDIR)$(bindir) && \
> +             $(LN) $$install_name $$target_install_name ) ; \
> +         fi ; \
> +       done
> +
>  # Cancel installation by deleting the installed files.
>  uninstall: lang.uninstall
>        -rm -rf $(DESTDIR)$(libsubdir)
> @@ -4915,6 +4974,12 @@ uninstall: lang.uninstall
>        -rm -rf $(DESTDIR)$(man1dir)/cpp$(man1ext)
>        -rm -f $(DESTDIR)$(infodir)/cpp.info* $(DESTDIR)$(infodir)/gcc.info*
>        -rm -f $(DESTDIR)$(infodir)/cppinternals.info* $(DESTDIR)$(infodir)/gccint.info*
> +       for i in ar nm ranlib ; do \
> +         install_name=`echo gcc-$$i|sed '$(program_transform_name)'`$(exeext) ;\
> +         target_install_name=$(target_noncanonical)-`echo gcc-$$i|sed '$(program_transform_name)'`$(exeext) ; \
> +         rm -f $(DESTDIR)$(bindir)/$$install_name ; \
> +         rm -f $(DESTDIR)$(bindir)/$$target_install_name ; \
> +       done
>  #
>  # These targets are for the dejagnu testsuites. The file site.exp
>  # contains global variables that all the testsuites will use.
> diff --git a/gcc/gcc-ar.c b/gcc/gcc-ar.c
> new file mode 100644
> index 0000000..fc7e4a2
> --- /dev/null
> +++ b/gcc/gcc-ar.c
> @@ -0,0 +1,96 @@
> +/* Wrapper for ar/ranlib/nm to pass the LTO plugin.
> +   Copyright (C) 2011 Free Software Foundation, Inc.
> +   Contributed by Andi Kleen.
> +
> +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 <stdio.h>
> +#include "config.h"
> +#include "system.h"
> +#include "libiberty.h"
> +
> +#ifndef PERSONALITY
> +#error "Please set personality"
> +#endif
> +
> +static const char standard_libexec_prefix[] = STANDARD_LIBEXEC_PREFIX;
> +static const char standard_bin_prefix[] = STANDARD_BINDIR_PREFIX;
> +
> +static const char dir_separator[] = { DIR_SEPARATOR, 0 };
> +
> +int
> +main(int ac, char **av)
> +{
> +  const char *nprefix;
> +  const char *exe_name;
> +  char *plugin;
> +  int k, status, err;
> +  const char *err_msg;
> +  const char **nargv;
> +  bool is_ar = !strcmp (PERSONALITY, "ar");
> +
> +  exe_name = PERSONALITY;
> +#ifdef CROSS_DIRECTORY_STRUCTURE
> +  exe_name = concat (target_machine, "-", exe_name, NULL);
> +#endif
> +
> +  /* Find plugin */
> +  /* XXX implement more magic from gcc.c? */
> +  nprefix = getenv ("GCC_EXEC_PREFIX");
> +  if (!nprefix)
> +    nprefix = standard_libexec_prefix;
> +
> +  nprefix = make_relative_prefix (av[0],
> +                                 standard_bin_prefix,
> +                                 nprefix);
> +  plugin = concat (nprefix,
> +                  dir_separator,
> +                   DEFAULT_TARGET_MACHINE,
> +                  dir_separator,
> +                  DEFAULT_TARGET_VERSION,
> +                  dir_separator,
> +                  LTOPLUGINSONAME,
> +                  NULL);
> +  if (access (plugin, X_OK))
> +    {
> +      fprintf (stderr, "%s: Cannot find plugin %s\n", av[0], plugin);
> +      exit (1);
> +    }
> +
> +  /* Create new command line with plugin */
> +  nargv = XCNEWVEC (const char *, ac + 4);
> +  nargv[0] = exe_name;
> +  nargv[1] = "--plugin";
> +  nargv[2] = plugin;
> +  if (is_ar && av[1] && av[1][0] != '-')
> +    av[1] = concat("-", av[1], NULL);
> +  for (k = 1; k < ac; k++)
> +    nargv[2 + k] = av[k];
> +  nargv[2 + k] = NULL;
> +
> +  /* Run utility */
> +  /* ??? the const is misplaced in pex_one's argv? */
> +  err_msg = pex_one (PEX_LAST|PEX_SEARCH,
> +                    exe_name,
> +                    CONST_CAST2 (char * const *, const char **, nargv),
> +                    concat("gcc-", exe_name, NULL),
> +                    NULL,NULL,  &status, &err);
> +  if (err_msg)
> +    fprintf(stderr, "Error running %s: %s\n", exe_name, err_msg);
> +
> +  return err;
> +}
> --
> 1.7.5.4
>
>
diff mbox

Patch

diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 6b28ef5..1b9987a 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1545,7 +1545,8 @@  MOSTLYCLEANFILES = insn-flags.h insn-config.h insn-codes.h \
  genrtl.h gt-*.h gtype-*.h gtype-desc.c gtyp-input.list \
  xgcc$(exeext) cpp$(exeext) cc1$(exeext) $(EXTRA_PASSES) \
  $(EXTRA_PARTS) $(EXTRA_PROGRAMS) gcc-cross$(exeext) \
- $(SPECS) collect2$(exeext) lto-wrapper$(exeext) \
+ $(SPECS) collect2$(exeext) gcc-ar$(exeext) gcc-nm$(exeext) \
+ gcc-ranlib$(exeext) \
  gcov-iov$(build_exeext) gcov$(exeext) gcov-dump$(exeext) \
  gengtype$(exeext) *.[0-9][0-9].* *.[si] *-checksum.c libbackend.a \
  libcommon-target.a libcommon.a libgcc.mk
@@ -1791,7 +1792,8 @@  rest.encap: lang.rest.encap
 # This is what is made with the host's compiler
 # whether making a cross compiler or not.
 native: config.status auto-host.h build-@POSUB@ $(LANGUAGES) \
-	$(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(COLLECT2) lto-wrapper$(exeext)
+	$(EXTRA_PASSES) $(EXTRA_PROGRAMS) $(COLLECT2) lto-wrapper$(exeext) \
+	gcc-ar$(exeext) gcc-nm$(exeext) gcc-ranlib$(exeext)
 
 ifeq ($(enable_plugin),yes)
 native: gengtype$(exeext)
@@ -2049,6 +2051,46 @@  sbitmap.o: sbitmap.c sbitmap.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(BASIC_BLOCK
 ebitmap.o: ebitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(EBITMAP_H)
 sparseset.o: sparseset.c $(SYSTEM_H) sparseset.h $(CONFIG_H)
 
+AR_LIBS = @COLLECT2_LIBS@
+
+gcc-ar$(exeext): gcc-ar.o $(LIBDEPS)
+	+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) gcc-ar.o -o $@ \
+		$(LIBS) $(AR_LIBS)
+
+gcc-nm$(exeext): gcc-nm.o $(LIBDEPS)
+	+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) gcc-nm.o -o $@ \
+		$(LIBS) $(AR_LIBS)
+
+gcc-ranlib$(exeext): gcc-ranlib.o $(LIBDEPS)
+	+$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) gcc-ranlib.o -o $@ \
+		$(LIBS) $(AR_LIBS)
+
+CFLAGS-gcc-ar.o += $(DRIVER_DEFINES) \
+	-DTARGET_MACHINE=\"$(target_noncanonical)\" \
+	@TARGET_SYSTEM_ROOT_DEFINE@ -DPERSONALITY=\"ar\"
+
+gcc-ar.o: gcc-ar.c $(CONFIG_H) $(SYSTEM_H) $(LIBIBERTY_H)
+
+CFLAGS-gcc-ranlib.o += $(DRIVER_DEFINES) \
+	-DTARGET_MACHINE=\"$(target_noncanonical)\" \
+	@TARGET_SYSTEM_ROOT_DEFINE@ -DPERSONALITY=\"ranlib\"
+
+gcc-ranlib.o: gcc-ranlib.c $(CONFIG_H) $(SYSTEM_H) $(LIBIBERTY_H)
+
+CFLAGS-gcc-nm.o += $(DRIVER_DEFINES) \
+	-DTARGET_MACHINE=\"$(target_noncanonical)\" \
+	@TARGET_SYSTEM_ROOT_DEFINE@ -DPERSONALITY=\"nm\"
+
+gcc-nm.o: gcc-nm.c $(CONFIG_H) $(SYSTEM_H) $(LIBIBERTY_H)
+
+# ??? the implicit rules dont trigger if the source file has a different name
+# so copy instead
+gcc-ranlib.c: gcc-ar.c
+	cp $^ $@
+
+gcc-nm.c: gcc-ar.c
+	cp $^ $@
+
 COLLECT2_OBJS = collect2.o collect2-aix.o tlink.o
 COLLECT2_LIBS = @COLLECT2_LIBS@
 collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
@@ -4576,7 +4618,7 @@  maintainer-clean:
 # broken is small.
 install: install-common $(INSTALL_HEADERS) \
     install-cpp install-man install-info install-@POSUB@ \
-    install-driver install-lto-wrapper
+    install-driver install-lto-wrapper install-gcc-ar
 
 ifeq ($(enable_plugin),yes)
 install: install-plugin
@@ -4901,6 +4943,23 @@  install-collect2: collect2 installdirs
 install-lto-wrapper: lto-wrapper$(exeext)
 	$(INSTALL_PROGRAM) lto-wrapper$(exeext) $(DESTDIR)$(libexecsubdir)/lto-wrapper$(exeext)
 
+install-gcc-ar:
+	set -e ; \
+	for i in ar nm ranlib ; do \
+	  install_name=`echo gcc-$$i|sed '$(program_transform_name)'`$(exeext) ;\
+	  target_install_name=$(target_noncanonical)-`echo gcc-$$i|sed '$(program_transform_name)'`$(exeext) ; \
+	  binname=gcc-$$i$(exeext) ; \
+	  rm -f $(DESTDIR)$(bindir)/$$install_name ; \
+	  rm -f $(DESTDIR)$(bindir)/$$target_install_name ; \
+	  $(INSTALL_PROGRAM) $$binname $(DESTDIR)$(bindir)/$$install_name ;\
+	  if test -f $(DESTDIR)$(bindir)$$target_install_name ; then \
+	    :; \
+	  else \
+	    ( cd $(DESTDIR)$(bindir) && \
+	      $(LN) $$install_name $$target_install_name ) ; \
+	  fi ; \
+	done
+
 # Cancel installation by deleting the installed files.
 uninstall: lang.uninstall
 	-rm -rf $(DESTDIR)$(libsubdir)
@@ -4915,6 +4974,12 @@  uninstall: lang.uninstall
 	-rm -rf $(DESTDIR)$(man1dir)/cpp$(man1ext)
 	-rm -f $(DESTDIR)$(infodir)/cpp.info* $(DESTDIR)$(infodir)/gcc.info*
 	-rm -f $(DESTDIR)$(infodir)/cppinternals.info* $(DESTDIR)$(infodir)/gccint.info*
+	for i in ar nm ranlib ; do \
+	  install_name=`echo gcc-$$i|sed '$(program_transform_name)'`$(exeext) ;\
+	  target_install_name=$(target_noncanonical)-`echo gcc-$$i|sed '$(program_transform_name)'`$(exeext) ; \
+	  rm -f $(DESTDIR)$(bindir)/$$install_name ; \
+	  rm -f $(DESTDIR)$(bindir)/$$target_install_name ; \
+	done
 #
 # These targets are for the dejagnu testsuites. The file site.exp
 # contains global variables that all the testsuites will use.
diff --git a/gcc/gcc-ar.c b/gcc/gcc-ar.c
new file mode 100644
index 0000000..fc7e4a2
--- /dev/null
+++ b/gcc/gcc-ar.c
@@ -0,0 +1,96 @@ 
+/* Wrapper for ar/ranlib/nm to pass the LTO plugin.
+   Copyright (C) 2011 Free Software Foundation, Inc.
+   Contributed by Andi Kleen.
+
+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 <stdio.h>
+#include "config.h"
+#include "system.h"
+#include "libiberty.h"
+
+#ifndef PERSONALITY
+#error "Please set personality"
+#endif
+
+static const char standard_libexec_prefix[] = STANDARD_LIBEXEC_PREFIX;
+static const char standard_bin_prefix[] = STANDARD_BINDIR_PREFIX;
+
+static const char dir_separator[] = { DIR_SEPARATOR, 0 };
+
+int 
+main(int ac, char **av)
+{
+  const char *nprefix;
+  const char *exe_name;
+  char *plugin;
+  int k, status, err;
+  const char *err_msg;
+  const char **nargv;
+  bool is_ar = !strcmp (PERSONALITY, "ar");
+
+  exe_name = PERSONALITY;
+#ifdef CROSS_DIRECTORY_STRUCTURE
+  exe_name = concat (target_machine, "-", exe_name, NULL);
+#endif
+
+  /* Find plugin */
+  /* XXX implement more magic from gcc.c? */
+  nprefix = getenv ("GCC_EXEC_PREFIX");
+  if (!nprefix)
+    nprefix = standard_libexec_prefix;
+
+  nprefix = make_relative_prefix (av[0], 
+				  standard_bin_prefix, 
+				  nprefix);
+  plugin = concat (nprefix,
+		   dir_separator,
+                   DEFAULT_TARGET_MACHINE, 
+		   dir_separator,
+		   DEFAULT_TARGET_VERSION,
+	           dir_separator,
+		   LTOPLUGINSONAME,
+		   NULL);
+  if (access (plugin, X_OK))
+    {
+      fprintf (stderr, "%s: Cannot find plugin %s\n", av[0], plugin);
+      exit (1);
+    }
+
+  /* Create new command line with plugin */
+  nargv = XCNEWVEC (const char *, ac + 4);
+  nargv[0] = exe_name;
+  nargv[1] = "--plugin";
+  nargv[2] = plugin;
+  if (is_ar && av[1] && av[1][0] != '-')
+    av[1] = concat("-", av[1], NULL);
+  for (k = 1; k < ac; k++)
+    nargv[2 + k] = av[k];
+  nargv[2 + k] = NULL;
+
+  /* Run utility */
+  /* ??? the const is misplaced in pex_one's argv? */
+  err_msg = pex_one (PEX_LAST|PEX_SEARCH, 
+		     exe_name, 
+		     CONST_CAST2 (char * const *, const char **, nargv),
+		     concat("gcc-", exe_name, NULL), 
+		     NULL,NULL,  &status, &err);
+  if (err_msg) 
+    fprintf(stderr, "Error running %s: %s\n", exe_name, err_msg);
+
+  return err;
+}