Message ID | 20121129041841.GA14005@gmail.com |
---|---|
State | New |
Headers | show |
On Thu, Nov 29, 2012 at 5:18 AM, H.J. Lu <hjl.tools@gmail.com> wrote: > From: "H.J. Lu" <hjl.tools@gmail.com> > To: gcc-patches@gcc.gnu.org > Cc: Joseph Myers <joseph@codesourcery.com>, Paolo Bonzini <bonzini@gnu.org> > Bcc: > Subject: [PATCH] Support -fuse-ld=bfd and -fuse-ld=gold > Reply-To: > > Hi, > > Binutils supports 2 linkers, ld.gold and ld.bfd. One of them is > configured as the default linker, ld, which is used by GCC. Sometimes, > we want to use the alternate linker with GCC at run-time. This patch > adds -fuse-ld=bfd and -fuse-ld=gold options to GCC driver. It changes > collect2.c to pick either ld.bfd or ld.gold. It also adds > ORIGINAL_LD_BFD_FOR_TARGET and ORIGINAL_LD_GOLD_FOR_TARGET to > exec-tool.in to add -fuse-ld=bfd and -fuse-ld=gold support to > collect-ld. Since ld.bfd nor ld.gold know the new options, you > will get > > # ./xgcc -B./ /tmp/x.c -fuse-ld=gold -v > ... > ./collect-ld --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -fuse-ld=gold /lib/../lib64/crt1.o /lib/../lib64/crti.o ./crtbegin.o -L. -L/lib/../lib64 -L/usr/lib/../lib64 /tmp/cclVWcGz.o -v -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed ./crtend.o /lib/../lib64/crtn.o > GNU gold (Linux/GNU Binutils 2.23.51.0.7.20121127) 1.11 > /usr/local/bin/ld.gold: fatal error: -f/--auxiliary may not be used without -shared > collect2: error: ld returned 1 exit status > > This is because we pass everything to ld and ld.bfd/ld.gold doesn't > understand -fuse-ld=bfd/-fuse-ld=gold. It isn't a problem for collect2 > since it will filter-out -fuse-ld=bfd/-fuse-ld=gold. I will submit a > binutils patch to ignore -fuse-ld=bfd/-fuse-ld=gold, similar to -flto > options. > > OK to install? Do we need to consider GNU ld and gold coming from different binutils versions and thus do we need two sets of linker feature tests at configure time? Eventually also if GNU ld and gold are not in feature-parity for the same binutils version? That is, isn't this going to create hard to debug issues for users? Thanks, Richard. > Thanks. > > > H.J. > --- > 2012-11-28 Nick Clifton <nickc@redhat.com> > Matthias Klose <doko@debian.org> > Doug Kwan <dougkwan@google.com> > H.J. Lu <hongjiu.lu@intel.com> > > PR driver/55470 > * collect2.c (main): Support -fuse-ld=bfd and -fuse-ld=gold. > > * common.opt: Add fuse-ld=bfd and fuse-ld=gold. > > * configure.ac (ORIGINAL_LD_BFD_FOR_TARGET): New AC_PATH_PROG. > (ORIGINAL_LD_GOLD_FOR_TARGET): Likewise. > * configure: Regenerated. > > * exec-tool.in (ORIGINAL_LD_BFD_FOR_TARGET): New variable. > (ORIGINAL_LD_GOLD_FOR_TARGET): Likewise. > Use $ORIGINAL_LD_BFD_FOR_TARGET for collect-ld when seeing > -fuse-ld=bfd. Use =$ORIGINAL_LD_GOLD_FOR_TARGET for collect-ld > when seeing -fuse-ld=gold. Issue an error if linker isn't > found. > > * gcc.c (LINK_COMMAND_SPEC): Pass -fuse-ld=* to collect2. > > * opts.c (comman_handle_option): Ignore -fuse-ld=bfd and > -fuse-ld=gold. > > * doc/invoke.texi: Document -fuse-ld=bfd and -fuse-ld=gold. > diff --git a/gcc/collect2.c b/gcc/collect2.c > index 49c4030..4e8cdf0 100644 > --- a/gcc/collect2.c > +++ b/gcc/collect2.c > @@ -842,8 +842,21 @@ maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst, > int > main (int argc, char **argv) > { > - static const char *const ld_suffix = "ld"; > - static const char *const plugin_ld_suffix = PLUGIN_LD_SUFFIX; > + enum linker_select > + { > + USE_DEFAULT_LD, > + USE_PLUGIN_LD, > + USE_GOLD_LD, > + USE_BFD_LD, > + USE_LD_MAX > + } selected_linker = USE_DEFAULT_LD; > + static const char *const ld_suffixes[USE_LD_MAX] = > + { > + "ld", > + PLUGIN_LD_SUFFIX, > + "ld.gold", > + "ld.bfd" > + }; > static const char *const real_ld_suffix = "real-ld"; > static const char *const collect_ld_suffix = "collect-ld"; > static const char *const nm_suffix = "nm"; > @@ -854,16 +867,13 @@ main (int argc, char **argv) > static const char *const strip_suffix = "strip"; > static const char *const gstrip_suffix = "gstrip"; > > + const char *full_ld_suffixes[USE_LD_MAX]; > #ifdef CROSS_DIRECTORY_STRUCTURE > /* If we look for a program in the compiler directories, we just use > the short name, since these directories are already system-specific. > But it we look for a program in the system directories, we need to > qualify the program name with the target machine. */ > > - const char *const full_ld_suffix = > - concat(target_machine, "-", ld_suffix, NULL); > - const char *const full_plugin_ld_suffix = > - concat(target_machine, "-", plugin_ld_suffix, NULL); > const char *const full_nm_suffix = > concat (target_machine, "-", nm_suffix, NULL); > const char *const full_gnm_suffix = > @@ -877,13 +887,11 @@ main (int argc, char **argv) > const char *const full_gstrip_suffix = > concat (target_machine, "-", gstrip_suffix, NULL); > #else > - const char *const full_ld_suffix = ld_suffix; > - const char *const full_plugin_ld_suffix = plugin_ld_suffix; > - const char *const full_nm_suffix = nm_suffix; > - const char *const full_gnm_suffix = gnm_suffix; > #ifdef LDD_SUFFIX > const char *const full_ldd_suffix = ldd_suffix; > #endif > + const char *const full_nm_suffix = nm_suffix; > + const char *const full_gnm_suffix = gnm_suffix; > const char *const full_strip_suffix = strip_suffix; > const char *const full_gstrip_suffix = gstrip_suffix; > #endif /* CROSS_DIRECTORY_STRUCTURE */ > @@ -900,6 +908,7 @@ main (int argc, char **argv) > char **ld1_argv; > const char **ld1; > bool use_plugin = false; > + bool use_collect_ld = false; > > /* The kinds of symbols we will have to consider when scanning the > outcome of a first pass link. This is ALL to start with, then might > @@ -919,6 +928,15 @@ main (int argc, char **argv) > int first_file; > int num_c_args; > char **old_argv; > + int i; > + > + for (i = 0; i < USE_LD_MAX; i++) > + full_ld_suffixes[i] > +#ifdef CROSS_DIRECTORY_STRUCTURE > + = concat(target_machine, "-", ld_suffixes[i], NULL); > +#else > + = ld_suffixes[i]; > +#endif > > p = argv[0] + strlen (argv[0]); > while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1])) > @@ -980,7 +998,6 @@ main (int argc, char **argv) > are called. We also look for the -flto or -flto-partition=none flag to know > what LTO mode we are in. */ > { > - int i; > bool no_partition = false; > > for (i = 1; argv[i] != NULL; i ++) > @@ -998,7 +1015,14 @@ main (int argc, char **argv) > { > use_plugin = true; > lto_mode = LTO_MODE_NONE; > + if (selected_linker == USE_DEFAULT_LD) > + selected_linker = USE_PLUGIN_LD; > } > + else if (strcmp (argv[i], "-fuse-ld=bfd") == 0) > + selected_linker = USE_BFD_LD; > + else if (strcmp (argv[i], "-fuse-ld=gold") == 0) > + selected_linker = USE_GOLD_LD; > + > #ifdef COLLECT_EXPORT_LIST > /* since -brtl, -bexport, -b64 are not position dependent > also check for them here */ > @@ -1095,21 +1119,18 @@ main (int argc, char **argv) > ld_file_name = find_a_file (&cpath, real_ld_suffix); > /* Likewise for `collect-ld'. */ > if (ld_file_name == 0) > - ld_file_name = find_a_file (&cpath, collect_ld_suffix); > + { > + ld_file_name = find_a_file (&cpath, collect_ld_suffix); > + use_collect_ld = ld_file_name != 0; > + } > /* Search the compiler directories for `ld'. We have protection against > recursive calls in find_a_file. */ > if (ld_file_name == 0) > - ld_file_name = find_a_file (&cpath, > - use_plugin > - ? plugin_ld_suffix > - : ld_suffix); > + ld_file_name = find_a_file (&cpath, ld_suffixes[selected_linker]); > /* Search the ordinary system bin directories > for `ld' (if native linking) or `TARGET-ld' (if cross). */ > if (ld_file_name == 0) > - ld_file_name = find_a_file (&path, > - use_plugin > - ? full_plugin_ld_suffix > - : full_ld_suffix); > + ld_file_name = find_a_file (&path, full_ld_suffixes[selected_linker]); > > #ifdef REAL_NM_FILE_NAME > nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME); > @@ -1266,6 +1287,13 @@ main (int argc, char **argv) > "configuration"); > #endif > } > + else if (!use_collect_ld > + && strncmp (arg, "-fuse-ld=", 9) == 0) > + { > + /* Do not pass -fuse-ld={bfd|gold} to the linker. */ > + ld1--; > + ld2--; > + } > #ifdef TARGET_AIX_VERSION > else > { > diff --git a/gcc/common.opt b/gcc/common.opt > index 4c8bd11..7b36ba3 100644 > --- a/gcc/common.opt > +++ b/gcc/common.opt > @@ -2171,6 +2171,12 @@ funwind-tables > Common Report Var(flag_unwind_tables) Optimization > Just generate unwind tables for exception handling > > +fuse-ld=bfd > +Common Var(flag_use_ld_bfd) Negative(fuse-ld=gold) Undocumented > + > +fuse-ld=gold > +Common Var(flag_use_ld_gold) Negative(fuse-ld=bfd) Undocumented > + > fuse-linker-plugin > Common Undocumented > > diff --git a/gcc/configure.ac b/gcc/configure.ac > index c6f57bd..14f0974 100644 > --- a/gcc/configure.ac > +++ b/gcc/configure.ac > @@ -2095,9 +2095,14 @@ changequote(,)dnl > gcc_cv_gld_major_version=`expr "$gcc_cv_gld_version" : "VERSION=\([0-9]*\)"` > gcc_cv_gld_minor_version=`expr "$gcc_cv_gld_version" : "VERSION=[0-9]*\.\([0-9]*\)"` > changequote([,])dnl > + ORIGINAL_LD_BFD_FOR_TARGET=../ld/ld-new$build_exeext > + ORIGINAL_LD_GOLD_FOR_TARGET=../gold/ld-new$build_exeext > else > AC_MSG_RESULT($gcc_cv_ld) > in_tree_ld=no > + gcc_cvs_ld_program=`basename $gcc_cv_ld $host_exeext` > + AC_PATH_PROG(ORIGINAL_LD_BFD_FOR_TARGET, ${gcc_cvs_ld_program}.bfd) > + AC_PATH_PROG(ORIGINAL_LD_GOLD_FOR_TARGET, ${gcc_cvs_ld_program}.gold) > fi > > # Figure out what nm we will be using. > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > index 51b6e85..3558f43 100644 > --- a/gcc/doc/invoke.texi > +++ b/gcc/doc/invoke.texi > @@ -425,7 +425,7 @@ Objective-C and Objective-C++ Dialects}. > -funit-at-a-time -funroll-all-loops -funroll-loops @gol > -funsafe-loop-optimizations -funsafe-math-optimizations -funswitch-loops @gol > -fvariable-expansion-in-unroller -fvect-cost-model -fvpt -fweb @gol > --fwhole-program -fwpa -fuse-linker-plugin @gol > +-fwhole-program -fwpa -fuse-ld=@var{linker} -fuse-linker-plugin @gol > --param @var{name}=@var{value} > -O -O0 -O1 -O2 -O3 -Os -Ofast -Og} > > @@ -8419,6 +8419,12 @@ the comparison operation before register allocation is complete. > > Enabled at levels @option{-O}, @option{-O2}, @option{-O3}, @option{-Os}. > > +@item -fuse-ld=gold > +Use the @command{gold} linker instead of the default linker. > + > +@item -fuse-ld=bfd > +Use the @command{ld.bfd} linker instead of the default linker. > + > @item -fcprop-registers > @opindex fcprop-registers > After register allocation and post-register allocation instruction splitting, > diff --git a/gcc/exec-tool.in b/gcc/exec-tool.in > index 8a10775..e6a96d8 100644 > --- a/gcc/exec-tool.in > +++ b/gcc/exec-tool.in > @@ -21,6 +21,8 @@ > > ORIGINAL_AS_FOR_TARGET="@ORIGINAL_AS_FOR_TARGET@" > ORIGINAL_LD_FOR_TARGET="@ORIGINAL_LD_FOR_TARGET@" > +ORIGINAL_LD_BFD_FOR_TARGET="@ORIGINAL_LD_BFD_FOR_TARGET@" > +ORIGINAL_LD_GOLD_FOR_TARGET="@ORIGINAL_LD_GOLD_FOR_TARGET@" > ORIGINAL_PLUGIN_LD_FOR_TARGET="@ORIGINAL_PLUGIN_LD_FOR_TARGET@" > ORIGINAL_NM_FOR_TARGET="@ORIGINAL_NM_FOR_TARGET@" > exeext=@host_exeext@ > @@ -36,12 +38,27 @@ case "$invoked" in > dir=gas > ;; > collect-ld) > - # when using a linker plugin, gcc will always pass '-plugin' as the > - # first or second option to the linker. > - if test x"$1" = "x-plugin" || test x"$2" = "x-plugin"; then > - original=$ORIGINAL_PLUGIN_LD_FOR_TARGET > - else > - original=$ORIGINAL_LD_FOR_TARGET > + # Check -fuse-ld=bfd and -fuse-ld=gold > + case " $* " in > + *\ -fuse-ld=bfd\ *) > + original=$ORIGINAL_LD_BFD_FOR_TARGET > + ;; > + *\ -fuse-ld=gold\ *) > + original=$ORIGINAL_LD_GOLD_FOR_TARGET > + ;; > + *) > + # when using a linker plugin, gcc will always pass '-plugin' as the > + # first or second option to the linker. > + if test x"$1" = "x-plugin" || test x"$2" = "x-plugin"; then > + original=$ORIGINAL_PLUGIN_LD_FOR_TARGET > + else > + original=$ORIGINAL_LD_FOR_TARGET > + fi > + ;; > + esac > + if test ! -x "${original}"; then > + echo "fatal error: cannot find 'ld'" > + exit 1 > fi > prog=ld-new$exeext > dir=ld > diff --git a/gcc/gcc.c b/gcc/gcc.c > index 13e93e5..e0fee40 100644 > --- a/gcc/gcc.c > +++ b/gcc/gcc.c > @@ -705,7 +705,8 @@ proper position among the other output files. */ > LINK_PLUGIN_SPEC \ > "%{flto|flto=*:%<fcompare-debug*} \ > %{flto} %{flto=*} %l " LINK_PIE_SPEC \ > - "%X %{o*} %{e*} %{N} %{n} %{r}\ > + "%{fuse-ld=*:-fuse-ld=%*}\ > + %X %{o*} %{e*} %{N} %{n} %{r}\ > %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}}\ > %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\ > %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)}\ > diff --git a/gcc/opts.c b/gcc/opts.c > index b3a9afe..ff1b51e 100644 > --- a/gcc/opts.c > +++ b/gcc/opts.c > @@ -1753,6 +1753,8 @@ common_handle_option (struct gcc_options *opts, > dc->max_errors = value; > break; > > + case OPT_fuse_ld_bfd: > + case OPT_fuse_ld_gold: > case OPT_fuse_linker_plugin: > /* No-op. Used by the driver and passed to us because it starts with f.*/ > break; > -- > 1.7.11.7 >
On 2012.11.29 at 09:43 +0100, Richard Biener wrote: > On Thu, Nov 29, 2012 at 5:18 AM, H.J. Lu <hjl.tools@gmail.com> wrote: > > From: "H.J. Lu" <hjl.tools@gmail.com> > > To: gcc-patches@gcc.gnu.org > > Cc: Joseph Myers <joseph@codesourcery.com>, Paolo Bonzini <bonzini@gnu.org> > > Bcc: > > Subject: [PATCH] Support -fuse-ld=bfd and -fuse-ld=gold > > Reply-To: > > > > Hi, > > > > Binutils supports 2 linkers, ld.gold and ld.bfd. One of them is > > configured as the default linker, ld, which is used by GCC. Sometimes, > > we want to use the alternate linker with GCC at run-time. This patch > > adds -fuse-ld=bfd and -fuse-ld=gold options to GCC driver. It changes > > collect2.c to pick either ld.bfd or ld.gold. It also adds > > ORIGINAL_LD_BFD_FOR_TARGET and ORIGINAL_LD_GOLD_FOR_TARGET to > > exec-tool.in to add -fuse-ld=bfd and -fuse-ld=gold support to > > collect-ld. Since ld.bfd nor ld.gold know the new options, you > > will get > > > > # ./xgcc -B./ /tmp/x.c -fuse-ld=gold -v > > ... > > ./collect-ld --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -fuse-ld=gold /lib/../lib64/crt1.o /lib/../lib64/crti.o ./crtbegin.o -L. -L/lib/../lib64 -L/usr/lib/../lib64 /tmp/cclVWcGz.o -v -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed ./crtend.o /lib/../lib64/crtn.o > > GNU gold (Linux/GNU Binutils 2.23.51.0.7.20121127) 1.11 > > /usr/local/bin/ld.gold: fatal error: -f/--auxiliary may not be used without -shared > > collect2: error: ld returned 1 exit status > > > > This is because we pass everything to ld and ld.bfd/ld.gold doesn't > > understand -fuse-ld=bfd/-fuse-ld=gold. It isn't a problem for collect2 > > since it will filter-out -fuse-ld=bfd/-fuse-ld=gold. I will submit a > > binutils patch to ignore -fuse-ld=bfd/-fuse-ld=gold, similar to -flto > > options. > > > > OK to install? > > Do we need to consider GNU ld and gold coming from different binutils versions > and thus do we need two sets of linker feature tests at configure > time? Eventually > also if GNU ld and gold are not in feature-parity for the same binutils version? > > That is, isn't this going to create hard to debug issues for users? Additionally, what is the rationale for this patch? IOW why isn't the following enough? x4 ~ # ln -f /usr/x86_64-pc-linux-gnu/binutils-bin/git/ld.gold /usr/x86_64-pc-linux-gnu/binutils-bin/git/ld x4 ~ # ld -v GNU gold (GNU Binutils 2.23.51.20121126) 1.11 x4 ~ # ln -f /usr/x86_64-pc-linux-gnu/binutils-bin/git/ld.bfd /usr/x86_64-pc-linux-gnu/binutils-bin/git/ld x4 ~ # ld -v GNU ld (GNU Binutils) 2.23.51.20121126 Or is this meant as a temporary workaround hack for gold bugs?
On Thu, Nov 29, 2012 at 1:10 AM, Markus Trippelsdorf <markus@trippelsdorf.de> wrote: > On 2012.11.29 at 09:43 +0100, Richard Biener wrote: >> On Thu, Nov 29, 2012 at 5:18 AM, H.J. Lu <hjl.tools@gmail.com> wrote: >> > From: "H.J. Lu" <hjl.tools@gmail.com> >> > To: gcc-patches@gcc.gnu.org >> > Cc: Joseph Myers <joseph@codesourcery.com>, Paolo Bonzini <bonzini@gnu.org> >> > Bcc: >> > Subject: [PATCH] Support -fuse-ld=bfd and -fuse-ld=gold >> > Reply-To: >> > >> > Hi, >> > >> > Binutils supports 2 linkers, ld.gold and ld.bfd. One of them is >> > configured as the default linker, ld, which is used by GCC. Sometimes, >> > we want to use the alternate linker with GCC at run-time. This patch >> > adds -fuse-ld=bfd and -fuse-ld=gold options to GCC driver. It changes >> > collect2.c to pick either ld.bfd or ld.gold. It also adds >> > ORIGINAL_LD_BFD_FOR_TARGET and ORIGINAL_LD_GOLD_FOR_TARGET to >> > exec-tool.in to add -fuse-ld=bfd and -fuse-ld=gold support to >> > collect-ld. Since ld.bfd nor ld.gold know the new options, you >> > will get >> > >> > # ./xgcc -B./ /tmp/x.c -fuse-ld=gold -v >> > ... >> > ./collect-ld --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -fuse-ld=gold /lib/../lib64/crt1.o /lib/../lib64/crti.o ./crtbegin.o -L. -L/lib/../lib64 -L/usr/lib/../lib64 /tmp/cclVWcGz.o -v -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed ./crtend.o /lib/../lib64/crtn.o >> > GNU gold (Linux/GNU Binutils 2.23.51.0.7.20121127) 1.11 >> > /usr/local/bin/ld.gold: fatal error: -f/--auxiliary may not be used without -shared >> > collect2: error: ld returned 1 exit status >> > >> > This is because we pass everything to ld and ld.bfd/ld.gold doesn't >> > understand -fuse-ld=bfd/-fuse-ld=gold. It isn't a problem for collect2 >> > since it will filter-out -fuse-ld=bfd/-fuse-ld=gold. I will submit a >> > binutils patch to ignore -fuse-ld=bfd/-fuse-ld=gold, similar to -flto >> > options. >> > >> > OK to install? >> >> Do we need to consider GNU ld and gold coming from different binutils versions >> and thus do we need two sets of linker feature tests at configure >> time? Eventually >> also if GNU ld and gold are not in feature-parity for the same binutils version? This is no different from run-time linker vs configure-time linker. If it is a link-time failure, we can check: [hjl@gnu-6 tmp]$ gcc x.o -v -Wl,-v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.7.2/lto-wrapper Target: x86_64-redhat-linux Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --disable-build-with-cxx --disable-build-poststage1-with-cxx --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --with-multilib-list=m32,m64,mx32 --build=x86_64-redhat-linux Thread model: posix gcc version 4.7.2 20120921 (Red Hat 4.7.2-2) (GCC) COMPILER_PATH=/usr/libexec/gcc/x86_64-redhat-linux/4.7.2/:/usr/libexec/gcc/x86_64-redhat-linux/4.7.2/:/usr/libexec/gcc/x86_64-redhat-linux/:/usr/lib/gcc/x86_64-redhat-linux/4.7.2/:/usr/lib/gcc/x86_64-redhat-linux/ LIBRARY_PATH=/usr/lib/gcc/x86_64-redhat-linux/4.7.2/:/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64/:/lib/../lib64/:/usr/lib/../lib64/:/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-v' '-mtune=generic' '-march=x86-64' /usr/libexec/gcc/x86_64-redhat-linux/4.7.2/collect2 --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.7.2/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.7.2 -L/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../.. x.o -v -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/4.7.2/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64/crtn.o collect2 version 4.7.2 20120921 (Red Hat 4.7.2-2) /usr/local/bin/ld --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.7.2/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.7.2 -L/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../.. x.o -v -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/4.7.2/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64/crtn.o GNU ld (GNU Binutils) 2.23.51.20121128 [hjl@gnu-6 tmp]$ >> That is, isn't this going to create hard to debug issues for users? User uses it by choice. You can check which linker is used. > Additionally, what is the rationale for this patch? IOW why isn't the following > enough? > > x4 ~ # ln -f /usr/x86_64-pc-linux-gnu/binutils-bin/git/ld.gold /usr/x86_64-pc-linux-gnu/binutils-bin/git/ld > x4 ~ # ld -v > GNU gold (GNU Binutils 2.23.51.20121126) 1.11 > x4 ~ # ln -f /usr/x86_64-pc-linux-gnu/binutils-bin/git/ld.bfd /usr/x86_64-pc-linux-gnu/binutils-bin/git/ld > x4 ~ # ld -v > GNU ld (GNU Binutils) 2.23.51.20121126 > > Or is this meant as a temporary workaround hack for gold bugs? > Yes, it is used as a temporary workaround for linker bugs. --- H.J.
Am 29.11.2012 09:43, schrieb Richard Biener: > Do we need to consider GNU ld and gold coming from different binutils versions > and thus do we need two sets of linker feature tests at configure > time? both GNU ld and gold are built from the same sources. So it is likely that they come from the same binutils version (at least that is the current situation). > Eventually > also if GNU ld and gold are not in feature-parity for the same binutils version? > > That is, isn't this going to create hard to debug issues for users? How would that be different than today's issues? If both versions are built, then any of them can be picked up once these are installed. How is today's situation? Debian/Ubuntu do build both linkers (and I assume other distributions do as well). One is the default (currently GNU ld), and you can make the other the system wide default using diversions (a distribution mechanism to change /usr/bin/ld). I have: $ ls -l /usr/lib/*-ld /usr/lib/compat-ld: lrwxrwxrwx 1 root root 16 Nov 26 08:13 ld -> ../../bin/ld.bfd /usr/lib/gold-ld: lrwxrwxrwx 1 root root 17 Nov 26 08:13 ld -> ../../bin/ld.gold so to explicitly use one linker you have to know the location, and then pass the appropriate -B option. Having this option makes this choice independent of the location. Having this location independence is my rationale for this patch. Matthias
Am 29.11.2012 10:10, schrieb Markus Trippelsdorf: > Additionally, what is the rationale for this patch? IOW why isn't the following > enough? > > x4 ~ # ln -f /usr/x86_64-pc-linux-gnu/binutils-bin/git/ld.gold /usr/x86_64-pc-linux-gnu/binutils-bin/git/ld > x4 ~ # ld -v > GNU gold (GNU Binutils 2.23.51.20121126) 1.11 > x4 ~ # ln -f /usr/x86_64-pc-linux-gnu/binutils-bin/git/ld.bfd /usr/x86_64-pc-linux-gnu/binutils-bin/git/ld > x4 ~ # ld -v > GNU ld (GNU Binutils) 2.23.51.20121126 because you have to find out about these hard-coded path for every single installation of binutils.
On Thu, Nov 29, 2012 at 12:43 AM, Richard Biener <richard.guenther@gmail.com> wrote: > On Thu, Nov 29, 2012 at 5:18 AM, H.J. Lu <hjl.tools@gmail.com> wrote: >> From: "H.J. Lu" <hjl.tools@gmail.com> >> To: gcc-patches@gcc.gnu.org >> Cc: Joseph Myers <joseph@codesourcery.com>, Paolo Bonzini <bonzini@gnu.org> >> Bcc: >> Subject: [PATCH] Support -fuse-ld=bfd and -fuse-ld=gold >> Reply-To: >> >> Hi, >> >> Binutils supports 2 linkers, ld.gold and ld.bfd. One of them is >> configured as the default linker, ld, which is used by GCC. Sometimes, >> we want to use the alternate linker with GCC at run-time. This patch >> adds -fuse-ld=bfd and -fuse-ld=gold options to GCC driver. It changes >> collect2.c to pick either ld.bfd or ld.gold. It also adds >> ORIGINAL_LD_BFD_FOR_TARGET and ORIGINAL_LD_GOLD_FOR_TARGET to >> exec-tool.in to add -fuse-ld=bfd and -fuse-ld=gold support to >> collect-ld. Since ld.bfd nor ld.gold know the new options, you >> will get >> >> # ./xgcc -B./ /tmp/x.c -fuse-ld=gold -v >> ... >> ./collect-ld --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -fuse-ld=gold /lib/../lib64/crt1.o /lib/../lib64/crti.o ./crtbegin.o -L. -L/lib/../lib64 -L/usr/lib/../lib64 /tmp/cclVWcGz.o -v -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed ./crtend.o /lib/../lib64/crtn.o >> GNU gold (Linux/GNU Binutils 2.23.51.0.7.20121127) 1.11 >> /usr/local/bin/ld.gold: fatal error: -f/--auxiliary may not be used without -shared >> collect2: error: ld returned 1 exit status >> >> This is because we pass everything to ld and ld.bfd/ld.gold doesn't >> understand -fuse-ld=bfd/-fuse-ld=gold. It isn't a problem for collect2 >> since it will filter-out -fuse-ld=bfd/-fuse-ld=gold. I will submit a >> binutils patch to ignore -fuse-ld=bfd/-fuse-ld=gold, similar to -flto >> options. >> >> OK to install? > > Do we need to consider GNU ld and gold coming from different binutils versions > and thus do we need two sets of linker feature tests at configure > time? Eventually > also if GNU ld and gold are not in feature-parity for the same binutils version? > > That is, isn't this going to create hard to debug issues for users? > Actually, it helps to debug issues for users. At the moment, we don't know which linker is the default linker. With -fuse-ld, we can specify which linker to use.
diff --git a/gcc/collect2.c b/gcc/collect2.c index 49c4030..4e8cdf0 100644 --- a/gcc/collect2.c +++ b/gcc/collect2.c @@ -842,8 +842,21 @@ maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst, int main (int argc, char **argv) { - static const char *const ld_suffix = "ld"; - static const char *const plugin_ld_suffix = PLUGIN_LD_SUFFIX; + enum linker_select + { + USE_DEFAULT_LD, + USE_PLUGIN_LD, + USE_GOLD_LD, + USE_BFD_LD, + USE_LD_MAX + } selected_linker = USE_DEFAULT_LD; + static const char *const ld_suffixes[USE_LD_MAX] = + { + "ld", + PLUGIN_LD_SUFFIX, + "ld.gold", + "ld.bfd" + }; static const char *const real_ld_suffix = "real-ld"; static const char *const collect_ld_suffix = "collect-ld"; static const char *const nm_suffix = "nm"; @@ -854,16 +867,13 @@ main (int argc, char **argv) static const char *const strip_suffix = "strip"; static const char *const gstrip_suffix = "gstrip"; + const char *full_ld_suffixes[USE_LD_MAX]; #ifdef CROSS_DIRECTORY_STRUCTURE /* If we look for a program in the compiler directories, we just use the short name, since these directories are already system-specific. But it we look for a program in the system directories, we need to qualify the program name with the target machine. */ - const char *const full_ld_suffix = - concat(target_machine, "-", ld_suffix, NULL); - const char *const full_plugin_ld_suffix = - concat(target_machine, "-", plugin_ld_suffix, NULL); const char *const full_nm_suffix = concat (target_machine, "-", nm_suffix, NULL); const char *const full_gnm_suffix = @@ -877,13 +887,11 @@ main (int argc, char **argv) const char *const full_gstrip_suffix = concat (target_machine, "-", gstrip_suffix, NULL); #else - const char *const full_ld_suffix = ld_suffix; - const char *const full_plugin_ld_suffix = plugin_ld_suffix; - const char *const full_nm_suffix = nm_suffix; - const char *const full_gnm_suffix = gnm_suffix; #ifdef LDD_SUFFIX const char *const full_ldd_suffix = ldd_suffix; #endif + const char *const full_nm_suffix = nm_suffix; + const char *const full_gnm_suffix = gnm_suffix; const char *const full_strip_suffix = strip_suffix; const char *const full_gstrip_suffix = gstrip_suffix; #endif /* CROSS_DIRECTORY_STRUCTURE */ @@ -900,6 +908,7 @@ main (int argc, char **argv) char **ld1_argv; const char **ld1; bool use_plugin = false; + bool use_collect_ld = false; /* The kinds of symbols we will have to consider when scanning the outcome of a first pass link. This is ALL to start with, then might @@ -919,6 +928,15 @@ main (int argc, char **argv) int first_file; int num_c_args; char **old_argv; + int i; + + for (i = 0; i < USE_LD_MAX; i++) + full_ld_suffixes[i] +#ifdef CROSS_DIRECTORY_STRUCTURE + = concat(target_machine, "-", ld_suffixes[i], NULL); +#else + = ld_suffixes[i]; +#endif p = argv[0] + strlen (argv[0]); while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1])) @@ -980,7 +998,6 @@ main (int argc, char **argv) are called. We also look for the -flto or -flto-partition=none flag to know what LTO mode we are in. */ { - int i; bool no_partition = false; for (i = 1; argv[i] != NULL; i ++) @@ -998,7 +1015,14 @@ main (int argc, char **argv) { use_plugin = true; lto_mode = LTO_MODE_NONE; + if (selected_linker == USE_DEFAULT_LD) + selected_linker = USE_PLUGIN_LD; } + else if (strcmp (argv[i], "-fuse-ld=bfd") == 0) + selected_linker = USE_BFD_LD; + else if (strcmp (argv[i], "-fuse-ld=gold") == 0) + selected_linker = USE_GOLD_LD; + #ifdef COLLECT_EXPORT_LIST /* since -brtl, -bexport, -b64 are not position dependent also check for them here */ @@ -1095,21 +1119,18 @@ main (int argc, char **argv) ld_file_name = find_a_file (&cpath, real_ld_suffix); /* Likewise for `collect-ld'. */ if (ld_file_name == 0) - ld_file_name = find_a_file (&cpath, collect_ld_suffix); + { + ld_file_name = find_a_file (&cpath, collect_ld_suffix); + use_collect_ld = ld_file_name != 0; + } /* Search the compiler directories for `ld'. We have protection against recursive calls in find_a_file. */ if (ld_file_name == 0) - ld_file_name = find_a_file (&cpath, - use_plugin - ? plugin_ld_suffix - : ld_suffix); + ld_file_name = find_a_file (&cpath, ld_suffixes[selected_linker]); /* Search the ordinary system bin directories for `ld' (if native linking) or `TARGET-ld' (if cross). */ if (ld_file_name == 0) - ld_file_name = find_a_file (&path, - use_plugin - ? full_plugin_ld_suffix - : full_ld_suffix); + ld_file_name = find_a_file (&path, full_ld_suffixes[selected_linker]); #ifdef REAL_NM_FILE_NAME nm_file_name = find_a_file (&path, REAL_NM_FILE_NAME); @@ -1266,6 +1287,13 @@ main (int argc, char **argv) "configuration"); #endif } + else if (!use_collect_ld + && strncmp (arg, "-fuse-ld=", 9) == 0) + { + /* Do not pass -fuse-ld={bfd|gold} to the linker. */ + ld1--; + ld2--; + } #ifdef TARGET_AIX_VERSION else { diff --git a/gcc/common.opt b/gcc/common.opt index 4c8bd11..7b36ba3 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -2171,6 +2171,12 @@ funwind-tables Common Report Var(flag_unwind_tables) Optimization Just generate unwind tables for exception handling +fuse-ld=bfd +Common Var(flag_use_ld_bfd) Negative(fuse-ld=gold) Undocumented + +fuse-ld=gold +Common Var(flag_use_ld_gold) Negative(fuse-ld=bfd) Undocumented + fuse-linker-plugin Common Undocumented diff --git a/gcc/configure.ac b/gcc/configure.ac index c6f57bd..14f0974 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -2095,9 +2095,14 @@ changequote(,)dnl gcc_cv_gld_major_version=`expr "$gcc_cv_gld_version" : "VERSION=\([0-9]*\)"` gcc_cv_gld_minor_version=`expr "$gcc_cv_gld_version" : "VERSION=[0-9]*\.\([0-9]*\)"` changequote([,])dnl + ORIGINAL_LD_BFD_FOR_TARGET=../ld/ld-new$build_exeext + ORIGINAL_LD_GOLD_FOR_TARGET=../gold/ld-new$build_exeext else AC_MSG_RESULT($gcc_cv_ld) in_tree_ld=no + gcc_cvs_ld_program=`basename $gcc_cv_ld $host_exeext` + AC_PATH_PROG(ORIGINAL_LD_BFD_FOR_TARGET, ${gcc_cvs_ld_program}.bfd) + AC_PATH_PROG(ORIGINAL_LD_GOLD_FOR_TARGET, ${gcc_cvs_ld_program}.gold) fi # Figure out what nm we will be using. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 51b6e85..3558f43 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -425,7 +425,7 @@ Objective-C and Objective-C++ Dialects}. -funit-at-a-time -funroll-all-loops -funroll-loops @gol -funsafe-loop-optimizations -funsafe-math-optimizations -funswitch-loops @gol -fvariable-expansion-in-unroller -fvect-cost-model -fvpt -fweb @gol --fwhole-program -fwpa -fuse-linker-plugin @gol +-fwhole-program -fwpa -fuse-ld=@var{linker} -fuse-linker-plugin @gol --param @var{name}=@var{value} -O -O0 -O1 -O2 -O3 -Os -Ofast -Og} @@ -8419,6 +8419,12 @@ the comparison operation before register allocation is complete. Enabled at levels @option{-O}, @option{-O2}, @option{-O3}, @option{-Os}. +@item -fuse-ld=gold +Use the @command{gold} linker instead of the default linker. + +@item -fuse-ld=bfd +Use the @command{ld.bfd} linker instead of the default linker. + @item -fcprop-registers @opindex fcprop-registers After register allocation and post-register allocation instruction splitting, diff --git a/gcc/exec-tool.in b/gcc/exec-tool.in index 8a10775..e6a96d8 100644 --- a/gcc/exec-tool.in +++ b/gcc/exec-tool.in @@ -21,6 +21,8 @@ ORIGINAL_AS_FOR_TARGET="@ORIGINAL_AS_FOR_TARGET@" ORIGINAL_LD_FOR_TARGET="@ORIGINAL_LD_FOR_TARGET@" +ORIGINAL_LD_BFD_FOR_TARGET="@ORIGINAL_LD_BFD_FOR_TARGET@" +ORIGINAL_LD_GOLD_FOR_TARGET="@ORIGINAL_LD_GOLD_FOR_TARGET@" ORIGINAL_PLUGIN_LD_FOR_TARGET="@ORIGINAL_PLUGIN_LD_FOR_TARGET@" ORIGINAL_NM_FOR_TARGET="@ORIGINAL_NM_FOR_TARGET@" exeext=@host_exeext@ @@ -36,12 +38,27 @@ case "$invoked" in dir=gas ;; collect-ld) - # when using a linker plugin, gcc will always pass '-plugin' as the - # first or second option to the linker. - if test x"$1" = "x-plugin" || test x"$2" = "x-plugin"; then - original=$ORIGINAL_PLUGIN_LD_FOR_TARGET - else - original=$ORIGINAL_LD_FOR_TARGET + # Check -fuse-ld=bfd and -fuse-ld=gold + case " $* " in + *\ -fuse-ld=bfd\ *) + original=$ORIGINAL_LD_BFD_FOR_TARGET + ;; + *\ -fuse-ld=gold\ *) + original=$ORIGINAL_LD_GOLD_FOR_TARGET + ;; + *) + # when using a linker plugin, gcc will always pass '-plugin' as the + # first or second option to the linker. + if test x"$1" = "x-plugin" || test x"$2" = "x-plugin"; then + original=$ORIGINAL_PLUGIN_LD_FOR_TARGET + else + original=$ORIGINAL_LD_FOR_TARGET + fi + ;; + esac + if test ! -x "${original}"; then + echo "fatal error: cannot find 'ld'" + exit 1 fi prog=ld-new$exeext dir=ld diff --git a/gcc/gcc.c b/gcc/gcc.c index 13e93e5..e0fee40 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -705,7 +705,8 @@ proper position among the other output files. */ LINK_PLUGIN_SPEC \ "%{flto|flto=*:%<fcompare-debug*} \ %{flto} %{flto=*} %l " LINK_PIE_SPEC \ - "%X %{o*} %{e*} %{N} %{n} %{r}\ + "%{fuse-ld=*:-fuse-ld=%*}\ + %X %{o*} %{e*} %{N} %{n} %{r}\ %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}}\ %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\ %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)}\ diff --git a/gcc/opts.c b/gcc/opts.c index b3a9afe..ff1b51e 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -1753,6 +1753,8 @@ common_handle_option (struct gcc_options *opts, dc->max_errors = value; break; + case OPT_fuse_ld_bfd: + case OPT_fuse_ld_gold: case OPT_fuse_linker_plugin: /* No-op. Used by the driver and passed to us because it starts with f.*/ break;
From: "H.J. Lu" <hjl.tools@gmail.com> To: gcc-patches@gcc.gnu.org Cc: Joseph Myers <joseph@codesourcery.com>, Paolo Bonzini <bonzini@gnu.org> Bcc: Subject: [PATCH] Support -fuse-ld=bfd and -fuse-ld=gold Reply-To: Hi, Binutils supports 2 linkers, ld.gold and ld.bfd. One of them is configured as the default linker, ld, which is used by GCC. Sometimes, we want to use the alternate linker with GCC at run-time. This patch adds -fuse-ld=bfd and -fuse-ld=gold options to GCC driver. It changes collect2.c to pick either ld.bfd or ld.gold. It also adds ORIGINAL_LD_BFD_FOR_TARGET and ORIGINAL_LD_GOLD_FOR_TARGET to exec-tool.in to add -fuse-ld=bfd and -fuse-ld=gold support to collect-ld. Since ld.bfd nor ld.gold know the new options, you will get # ./xgcc -B./ /tmp/x.c -fuse-ld=gold -v ... ./collect-ld --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -fuse-ld=gold /lib/../lib64/crt1.o /lib/../lib64/crti.o ./crtbegin.o -L. -L/lib/../lib64 -L/usr/lib/../lib64 /tmp/cclVWcGz.o -v -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed ./crtend.o /lib/../lib64/crtn.o GNU gold (Linux/GNU Binutils 2.23.51.0.7.20121127) 1.11 /usr/local/bin/ld.gold: fatal error: -f/--auxiliary may not be used without -shared collect2: error: ld returned 1 exit status This is because we pass everything to ld and ld.bfd/ld.gold doesn't understand -fuse-ld=bfd/-fuse-ld=gold. It isn't a problem for collect2 since it will filter-out -fuse-ld=bfd/-fuse-ld=gold. I will submit a binutils patch to ignore -fuse-ld=bfd/-fuse-ld=gold, similar to -flto options. OK to install? Thanks. H.J. --- 2012-11-28 Nick Clifton <nickc@redhat.com> Matthias Klose <doko@debian.org> Doug Kwan <dougkwan@google.com> H.J. Lu <hongjiu.lu@intel.com> PR driver/55470 * collect2.c (main): Support -fuse-ld=bfd and -fuse-ld=gold. * common.opt: Add fuse-ld=bfd and fuse-ld=gold. * configure.ac (ORIGINAL_LD_BFD_FOR_TARGET): New AC_PATH_PROG. (ORIGINAL_LD_GOLD_FOR_TARGET): Likewise. * configure: Regenerated. * exec-tool.in (ORIGINAL_LD_BFD_FOR_TARGET): New variable. (ORIGINAL_LD_GOLD_FOR_TARGET): Likewise. Use $ORIGINAL_LD_BFD_FOR_TARGET for collect-ld when seeing -fuse-ld=bfd. Use =$ORIGINAL_LD_GOLD_FOR_TARGET for collect-ld when seeing -fuse-ld=gold. Issue an error if linker isn't found. * gcc.c (LINK_COMMAND_SPEC): Pass -fuse-ld=* to collect2. * opts.c (comman_handle_option): Ignore -fuse-ld=bfd and -fuse-ld=gold. * doc/invoke.texi: Document -fuse-ld=bfd and -fuse-ld=gold.