This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Fix even more merging PIC and PIE options


Hi,
this patch should fix merging of PIC and PIE options so we always resort
to the least common denominator of the object files compiled (i.e. 
linking together -fpic and -fPIE will result in -fpie binary).
Note that we also use information about format of output passed by linker
plugin so we will disable pic/pie when resulting binary is not relocatable.
However for shared libraries and pie we want to pick right mode that makes
sense.

I wrote simple script that tries all possible options of combining two files.
Mode picked is specified in the output file.

To support targets that default to pic/pie well, I had to also hack
lto_write_options to always stream what mode was used in the given file.

lto-bootstrapped/regtested x86_64-linux, OK?

Honza

	PR lto/86517
	* lto-opts.c (lto_write_options): Always stream PIC/PIE mode.
	* lto-wrapper.c (merge_and_complain): Fix merging of PIC/PIE
Index: lto-opts.c
===================================================================
--- lto-opts.c	(revision 263356)
+++ lto-opts.c	(working copy)
@@ -78,6 +78,22 @@ lto_write_options (void)
       && !global_options.x_flag_openacc)
     append_to_collect_gcc_options (&temporary_obstack, &first_p,
 				   "-fno-openacc");
+  /* Append PIC/PIE mode because its default depends on target and it is
+     subject of merging in lto-wrapper.  */
+  if ((!global_options_set.x_flag_pic || global_options.x_flag_pic == 0)
+      && !global_options_set.x_flag_pie)
+    {
+       append_to_collect_gcc_options (&temporary_obstack, &first_p,
+				      global_options.x_flag_pic == 2
+				      ? "-fPIC"
+				      : global_options.x_flag_pic == 1
+				      ? "-fpic"
+				      : global_options.x_flag_pie == 2
+				      ? "-fPIE"
+				      : global_options.x_flag_pie == 1
+				      ? "-fpie"
+				      : "-fno-pie");
+    }
 
   /* Append options from target hook and store them to offload_lto section.  */
   if (lto_stream_offload_p)
Index: lto-wrapper.c
===================================================================
--- lto-wrapper.c	(revision 263356)
+++ lto-wrapper.c	(working copy)
@@ -408,6 +408,11 @@ merge_and_complain (struct cl_decoded_op
      It is a common mistake to mix few -fPIC compiled objects into otherwise
      non-PIC code.  We do not want to build everything with PIC then.
 
+     Similarly we merge PIE options, however in addition we keep
+      -fPIC + -fPIE = -fPIE
+      -fpic + -fPIE = -fpie
+      -fPIC/-fpic + -fpie = -fpie
+
      It would be good to warn on mismatches, but it is bit hard to do as
      we do not know what nothing translates to.  */
     
@@ -415,11 +420,38 @@ merge_and_complain (struct cl_decoded_op
     if ((*decoded_options)[j].opt_index == OPT_fPIC
         || (*decoded_options)[j].opt_index == OPT_fpic)
       {
-	if (!pic_option
-	    || (pic_option->value > 0) != ((*decoded_options)[j].value > 0))
-	  remove_option (decoded_options, j, decoded_options_count);
-	else if (pic_option->opt_index == OPT_fPIC
-		 && (*decoded_options)[j].opt_index == OPT_fpic)
+	/* -fno-pic in one unit implies -fno-pic everywhere.  */
+	if ((*decoded_options)[j].value == 0)
+	  j++;
+	/* If we have no pic option or merge in -fno-pic, we still may turn
+	   existing pic/PIC mode into pie/PIE if -fpie/-fPIE is present.  */
+	else if ((pic_option && pic_option->value == 0)
+		 || !pic_option)
+	  {
+	    if (pie_option)
+	      {
+		bool big = (*decoded_options)[j].opt_index == OPT_fPIC
+			   && pie_option->opt_index == OPT_fPIE;
+	        (*decoded_options)[j].opt_index = big ? OPT_fPIE : OPT_fpie;
+		if (pie_option->value)
+	          (*decoded_options)[j].canonical_option[0] = big ? "-fPIE" : "-fpie";
+		else
+	          (*decoded_options)[j].canonical_option[0] = big ? "-fno-pie" : "-fno-pie";
+		(*decoded_options)[j].value = pie_option->value;
+	        j++;
+	      }
+	    else if (pic_option)
+	      {
+	        (*decoded_options)[j] = *pic_option;
+	        j++;
+	      }
+	    /* We do not know if target defaults to pic or not, so just remove
+	       option if it is missing in one unit but enabled in other.  */
+	    else
+	      remove_option (decoded_options, j, decoded_options_count);
+	  }
+	else if (pic_option->opt_index == OPT_fpic
+		 && (*decoded_options)[j].opt_index == OPT_fPIC)
 	  {
 	    (*decoded_options)[j] = *pic_option;
 	    j++;
@@ -430,11 +462,42 @@ merge_and_complain (struct cl_decoded_op
    else if ((*decoded_options)[j].opt_index == OPT_fPIE
             || (*decoded_options)[j].opt_index == OPT_fpie)
       {
-	if (!pie_option
-	    || pie_option->value != (*decoded_options)[j].value)
-	  remove_option (decoded_options, j, decoded_options_count);
-	else if (pie_option->opt_index == OPT_fPIE
-		 && (*decoded_options)[j].opt_index == OPT_fpie)
+	/* -fno-pie in one unit implies -fno-pie everywhere.  */
+	if ((*decoded_options)[j].value == 0)
+	  j++;
+	/* If we have no pie option or merge in -fno-pie, we still preserve
+	   PIE/pie if pic/PIC is present.  */
+	else if ((pie_option && pie_option->value == 0)
+		 || !pie_option)
+	  {
+	    /* If -fPIC/-fpic is given, merge it with -fPIE/-fpie.  */
+	    if (pic_option)
+	      {
+		if (pic_option->opt_index == OPT_fpic
+		    && (*decoded_options)[j].opt_index == OPT_fPIE)
+		  {
+	            (*decoded_options)[j].opt_index = OPT_fpie;
+	            (*decoded_options)[j].canonical_option[0]
+			 = pic_option->value ? "-fpie" : "-fno-pie";
+		  }
+		else if (!pic_option->value)
+		  (*decoded_options)[j].canonical_option[0] = "-fno-pie";
+		(*decoded_options)[j].value = pic_option->value;
+		j++;
+	      }
+	    else if (pie_option)
+	      {
+	        (*decoded_options)[j] = *pie_option;
+		j++;
+	      }
+	    /* Because we always append pic/PIE options this code path should
+	       not happen unless the LTO object was built by old lto1 which
+	       did not contain that logic yet.  */
+	    else
+	      remove_option (decoded_options, j, decoded_options_count);
+	  }
+	else if (pie_option->opt_index == OPT_fpie
+		 && (*decoded_options)[j].opt_index == OPT_fPIE)
 	  {
 	    (*decoded_options)[j] = *pie_option;
 	    j++;

Attachment: test.sh
Description: Bourne shell script

Attachment: test-output
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]