On 08/10/2018 04:33 PM, Jan Hubicka wrote: > 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
Thank you Honza for it. Would it be then subject for backporting into GCC-8 branch? Martin > > 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++; >