diff mbox

PATCH: PR driver/59321: -fuse-ld has no effect on -print-prog-name nor on --with-ld=

Message ID 20131202124901.GA2429@gmail.com
State New
Headers show

Commit Message

H.J. Lu Dec. 2, 2013, 12:49 p.m. UTC
Hi,

"ld" is a special name for GCC driver.  find_a_file has

#ifdef DEFAULT_LINKER
  if (! strcmp (name, "ld") && access (DEFAULT_LINKER, mode) == 0)
      return xstrdup (DEFAULT_LINKER);
      #endif
#endif

It does 2 things:

1. Print DEFAULT_LINKER for -print-prog-name=ld.
2. Run DEFAULT_LINKER when ld is needed to run.

But gcc.c fails to check -print-prog-name=ld with -fuse-ld= and
collect2.c fails to properly handle -fuse-ld= when DEFAULT_LINKER
is defined.  This patches fixes those 2 problems:

1. Check "ld" + suffix specicied by -fuse-ld= for -print-prog-name=ld.
2. Try DEFAULT_LINKER + suffix specicied by -fuse-ld=.

This patch also tries to handle HOST_EXECUTABLE_SUFFIX. Tested on
Linux/x86.  OK to install?

Thanks.


H.J.
---
2013-11-30  H.J. Lu  <hongjiu.lu@intel.com>

	PR driver/59321
	* collect2.c (main): Check -fuse-ld=[bfd|gold] when
	DEFAULT_LINKER is defined.
	* gcc.c (use_ld): New variable.
	(process_command): Set use_ld for OPT_fuse_ld_bfd and
	OPT_fuse_ld_gold.
	(main): Check -fuse-ld=[bfd|gold] for -print-prog-name=ld.

Comments

Joseph Myers Dec. 19, 2013, 12:13 a.m. UTC | #1
On Mon, 2 Dec 2013, H.J. Lu wrote:

> @@ -3952,6 +3955,10 @@ process_command (unsigned int decoded_options_count,
>            free (fname);
>  	  continue;
>  	}
> +      else if (decoded_options[j].opt_index == OPT_fuse_ld_bfd)
> +	use_ld = ".bfd";
> +      else if (decoded_options[j].opt_index == OPT_fuse_ld_gold)
> +	use_ld = ".gold";

Is there a reason these options need handling there rather than in the 
switch statement in driver_handle_option?
H.J. Lu Dec. 19, 2013, 3:57 a.m. UTC | #2
On Wed, Dec 18, 2013 at 4:13 PM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> On Mon, 2 Dec 2013, H.J. Lu wrote:
>
>> @@ -3952,6 +3955,10 @@ process_command (unsigned int decoded_options_count,
>>            free (fname);
>>         continue;
>>       }
>> +      else if (decoded_options[j].opt_index == OPT_fuse_ld_bfd)
>> +     use_ld = ".bfd";
>> +      else if (decoded_options[j].opt_index == OPT_fuse_ld_gold)
>> +     use_ld = ".gold";
>
> Is there a reason these options need handling there rather than in the
> switch statement in driver_handle_option?
>

It is because driver_handle_option isn't called for -fuse-ld=gold:

Starting program: /export/build/gnu/gcc/build-x86_64-linux/gcc/xgcc
-B./ -print-prog-name=ld -fuse-ld=gold

Breakpoint 5, driver_handle_option (opts=0x6e5580 <global_options>,
    opts_set=0x6e6020 <global_options_set>, decoded=0x6fbab0,
    lang_mask=524288, kind=0, loc=0, handlers=0x7fffffffddc0,
    dc=0x6e6b00 <global_diagnostic_context>)
    at /export/gnu/import/git/gcc/gcc/gcc.c:3291
3291      size_t opt_index = decoded->opt_index;
$5 = {opt_index = 116, warn_message = 0x0, arg = 0x7fffffffe4f8 "./",
  orig_option_with_args_text = 0x6fa410 "-B./", canonical_option = {
    0x495bcc "-B", 0x7fffffffe4f8 "./", 0x0, 0x0},
  canonical_option_num_elements = 2, value = 1, errors = 0}
(gdb) c
Continuing.

Breakpoint 5, driver_handle_option (opts=0x6e5580 <global_options>,
    opts_set=0x6e6020 <global_options_set>, decoded=0x6fbb00,
    lang_mask=524288, kind=0, loc=0, handlers=0x7fffffffddc0,
    dc=0x6e6b00 <global_diagnostic_context>)
    at /export/gnu/import/git/gcc/gcc/gcc.c:3291
3291      size_t opt_index = decoded->opt_index;
$6 = {opt_index = 1212, warn_message = 0x0, arg = 0x7fffffffe50c "ld",
  orig_option_with_args_text = 0x6fa440 "-print-prog-name=ld",
  canonical_option = {0x6fa420 "-print-prog-name=ld", 0x0, 0x0, 0x0},
  canonical_option_num_elements = 1, value = 1, errors = 0}
(gdb) c
Continuing.
ld

Breakpoint 3, 0x0000003a91a39290 in exit () from /lib64/libc.so.6
(gdb)
Joseph Myers Dec. 19, 2013, 4:13 p.m. UTC | #3
On Wed, 18 Dec 2013, H.J. Lu wrote:

> On Wed, Dec 18, 2013 at 4:13 PM, Joseph S. Myers
> <joseph@codesourcery.com> wrote:
> > On Mon, 2 Dec 2013, H.J. Lu wrote:
> >
> >> @@ -3952,6 +3955,10 @@ process_command (unsigned int decoded_options_count,
> >>            free (fname);
> >>         continue;
> >>       }
> >> +      else if (decoded_options[j].opt_index == OPT_fuse_ld_bfd)
> >> +     use_ld = ".bfd";
> >> +      else if (decoded_options[j].opt_index == OPT_fuse_ld_gold)
> >> +     use_ld = ".gold";
> >
> > Is there a reason these options need handling there rather than in the
> > switch statement in driver_handle_option?
> >
> 
> It is because driver_handle_option isn't called for -fuse-ld=gold:

Try adding Driver to the .opt entries for these options.
diff mbox

Patch

diff --git a/gcc/collect2.c b/gcc/collect2.c
index 95f817d..1d8ea4f 100644
--- a/gcc/collect2.c
+++ b/gcc/collect2.c
@@ -1121,7 +1121,35 @@  main (int argc, char **argv)
   /* Maybe we know the right file to use (if not cross).  */
   ld_file_name = 0;
 #ifdef DEFAULT_LINKER
-  if (access (DEFAULT_LINKER, X_OK) == 0)
+  if (selected_linker == USE_BFD_LD || selected_linker == USE_GOLD_LD)
+    {
+      char *linker_name;
+# ifdef HOST_EXECUTABLE_SUFFIX
+      int len = (sizeof (DEFAULT_LINKER)
+		 - sizeof (HOST_EXECUTABLE_SUFFIX));
+      linker_name = NULL;
+      if (len > 0)
+	{
+	  char *default_linker = xstrdup (DEFAULT_LINKER);
+	  /* Strip HOST_EXECUTABLE_SUFFIX if DEFAULT_LINKER contains
+	     HOST_EXECUTABLE_SUFFIX.  */
+	  if (! strcmp (&default_linker[len], HOST_EXECUTABLE_SUFFIX))
+	    {
+	      default_linker[len] = '\0';
+	      linker_name = concat (default_linker,
+				    &ld_suffixes[selected_linker][2],
+				    HOST_EXECUTABLE_SUFFIX, NULL);
+	    }
+	}
+      if (linker_name == NULL)
+# endif
+      linker_name = concat (DEFAULT_LINKER,
+			    &ld_suffixes[selected_linker][2],
+			    NULL);
+      if (access (linker_name, X_OK) == 0)
+	ld_file_name = linker_name;
+    }
+  if (ld_file_name == 0 && access (DEFAULT_LINKER, X_OK) == 0)
     ld_file_name = DEFAULT_LINKER;
   if (ld_file_name == 0)
 #endif
diff --git a/gcc/gcc.c b/gcc/gcc.c
index b895f22..68b3df6 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -105,6 +105,9 @@  static int verbose_only_flag;
 
 static int print_subprocess_help;
 
+/* Linker suffix passed to -fuse-ld=... */
+static const char *use_ld;
+
 /* Whether we should report subprocess execution times to a file.  */
 
 FILE *report_times_to_file = NULL;
@@ -3952,6 +3955,10 @@  process_command (unsigned int decoded_options_count,
           free (fname);
 	  continue;
 	}
+      else if (decoded_options[j].opt_index == OPT_fuse_ld_bfd)
+	use_ld = ".bfd";
+      else if (decoded_options[j].opt_index == OPT_fuse_ld_gold)
+	use_ld = ".gold";
 
       read_cmdline_option (&global_options, &global_options_set,
 			   decoded_options + j, UNKNOWN_LOCATION,
@@ -6708,6 +6715,38 @@  main (int argc, char **argv)
 
   if (print_prog_name)
     {
+      if (use_ld != NULL && ! strcmp (print_prog_name, "ld"))
+	{
+	  /* Append USE_LD to to the default linker.  */
+#ifdef DEFAULT_LINKER
+	  char *ld;
+# ifdef HAVE_HOST_EXECUTABLE_SUFFIX
+	  int len = (sizeof (DEFAULT_LINKER)
+		     - sizeof (HOST_EXECUTABLE_SUFFIX));
+	  ld = NULL;
+	  if (len > 0)
+	    {
+	      char *default_linker = xstrdup (DEFAULT_LINKER);
+	      /* Strip HOST_EXECUTABLE_SUFFIX if DEFAULT_LINKER contains
+		 HOST_EXECUTABLE_SUFFIX.  */
+	      if (! strcmp (&default_linker[len], HOST_EXECUTABLE_SUFFIX))
+		{
+		  default_linker[len] = '\0';
+		  ld = concat (default_linker, use_ld,
+			       HOST_EXECUTABLE_SUFFIX, NULL);
+		}
+	    }
+	  if (ld == NULL)
+# endif
+	  ld = concat (DEFAULT_LINKER, use_ld, NULL);
+	  if (access (ld, X_OK) == 0)
+	    {
+	      printf ("%s\n", ld);
+	      return (0);
+	    }
+#endif
+	  print_prog_name = concat (print_prog_name, use_ld, NULL);
+	}
       char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK, 0);
       printf ("%s\n", (newname ? newname : print_prog_name));
       return (0);