> Am 04.04.2025 um 19:50 schrieb Jakub Jelinek <ja...@redhat.com>:
>
> Hi!
>
> 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.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Ok
> Or do you want something further (like
> switch (global_options.x_flag_cf_protection & ~CF_SET)
> )?
Dunno what that CF_SET is, we’re supposed to record options like the user
specified so we can merge them. Why does the backend alter this?
> 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.
>
> --- gcc/lto-opts.cc.jj 2025-01-02 11:23:09.939608681 +0100
> +++ gcc/lto-opts.cc 2025-04-04 15:29:57.295211103 +0200
> @@ -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. */
>
> Jakub
>