https://gcc.gnu.org/g:d25728c98682c058bfda79333c94b0a8cf2a3f49
commit r15-9210-gd25728c98682c058bfda79333c94b0a8cf2a3f49 Author: Jakub Jelinek <ja...@redhat.com> Date: Fri Apr 4 20:57:09 2025 +0200 lto: lto-opts fixes [PR119625] I can reproduce a really weird error in our distro i686 trunk gcc (but haven't managed to reproduce it with vanilla trunk yet). echo 'void foo (void) {}' > a.c; gcc -O2 -flto=auto -m32 -march=i686 -ffat-lto-objects -fhardened -o a.o -c a.c; gcc -O2 -flto=auto -m32 -march=i686 -r -o a.lo a.o lto1: fatal error: open failed: No such file or directory compilation terminated. lto-wrapper: fatal error: gcc returned 1 exit status The error is because cat ./a.lo.lto.o-args.0 "" a.o My suspicion is that this "" in there is caused by weird .gnu.lto_.opts section content during gcc -O2 -flto=auto -m32 -march=i686 -ffat-lto-objects -fhardened -S -o a.s -c a.c compilation (and I can reproduce that one with vanilla trunk). The above results in .section .gnu.lto_.opts,"e",@progbits .string "'-fno-openmp' '-fno-openacc' '-fPIC' '' '-m32' '-march=i686' '-O2' '-flto=auto' '-ffat-lto-objects'" There are two weird things, one (IMHO the cause of the "" later on) is the '' part, I think it comes from lto_write_options doing append_to_collect_gcc_options (&temporary_obstack, &first_p, ""); IMHO it shouldn't call append_to_collect_gcc_options at all for that case. The -fhardened option causes global_options.x_flag_cf_protection to be set to CF_FULL and later on the backend option processing sets it to CF_FULL | CF_SET (i.e. 7, a value not handled in lto_write_options). The following patch fixes it by not emitting anything there if flag_cf_protection is one of the unhandled values. Perhaps it could incrementally use switch (global_options.x_flag_cf_protection & ~CF_SET) instead, dunno. And the other problem is that the -fPIC in there is really weird. Our distro compiler or vanilla configured trunk certainly doesn't default to -fPIC and -fhardened uses -fPIE when -fPIC/-fpic/-fno-pie/-fno-pic is not specified, so I was expecting -fPIE in there. The thing is that the -fpie option causes setting of both global_options.x_flag_pi{c,e} to 1, -fPIE both to 2: /* If -fPIE or -fpie is used, turn on PIC. */ if (opts->x_flag_pie) opts->x_flag_pic = opts->x_flag_pie; else if (opts->x_flag_pic == -1) opts->x_flag_pic = 0; if (opts->x_flag_pic && !opts->x_flag_pie) opts->x_flag_shlib = 1; so checking first for flag_pic == 2 and then flag_pic == 1 and only afterwards for flag_pie means we never print -fPIE/-fpie. Or do you want something further (like switch (global_options.x_flag_cf_protection & ~CF_SET) )? 2025-04-04 Jakub Jelinek <ja...@redhat.com> PR lto/119625 * lto-opts.cc (lto_write_options): If neither flag_pic nor flag_pie are set, check first for flag_pie and only later for flag_pic rather than the other way around, use a temporary variable. If flag_cf_protection is not set, don't append anything if flag_cf_protection is none of CF_{NONE,FULL,BRANCH,RETURN} and use a temporary variable. Diff: --- gcc/lto-opts.cc | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/gcc/lto-opts.cc b/gcc/lto-opts.cc index dee1caafc558..3959598b497c 100644 --- a/gcc/lto-opts.cc +++ b/gcc/lto-opts.cc @@ -82,31 +82,32 @@ lto_write_options (void) subject of merging in lto-wrapper. */ if (!OPTION_SET_P (flag_pic) && !OPTION_SET_P (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"); + const char *pic = "-fno-pie"; + if (global_options.x_flag_pie == 2) + pic = "-fPIE"; + else if (global_options.x_flag_pie == 1) + pic = "-fpie"; + else if (global_options.x_flag_pic == 2) + pic = "-fPIC"; + else if (global_options.x_flag_pic == 1) + pic = "-fpic"; + append_to_collect_gcc_options (&temporary_obstack, &first_p, pic); } if (!OPTION_SET_P (flag_cf_protection)) { - append_to_collect_gcc_options ( - &temporary_obstack, &first_p, - global_options.x_flag_cf_protection == CF_NONE - ? "-fcf-protection=none" - : global_options.x_flag_cf_protection == CF_FULL - ? "-fcf-protection=full" - : global_options.x_flag_cf_protection == CF_BRANCH - ? "-fcf-protection=branch" - : global_options.x_flag_cf_protection == CF_RETURN - ? "-fcf-protection=return" - : ""); + const char *cf_protection = NULL; + switch (global_options.x_flag_cf_protection) + { + case CF_NONE: cf_protection = "-fcf-protection=none"; break; + case CF_FULL: cf_protection = "-fcf-protection=full"; break; + case CF_BRANCH: cf_protection = "-fcf-protection=branch"; break; + case CF_RETURN: cf_protection = "-fcf-protection=return"; break; + default: break; + } + if (cf_protection) + append_to_collect_gcc_options (&temporary_obstack, &first_p, + cf_protection); } /* If debug info is enabled append -g. */