Bug 2427891
| Summary: | GCC 16 breaks QEMU static PIE build with libatomic.a relocation errors | ||
|---|---|---|---|
| Product: | [Fedora] Fedora | Reporter: | Daniel Berrangé <berrange> |
| Component: | gcc | Assignee: | Jakub Jelinek <jakub> |
| Status: | NEW --- | QA Contact: | Fedora Extras Quality Assurance <extras-qa> |
| Severity: | high | Docs Contact: | |
| Priority: | unspecified | ||
| Version: | rawhide | CC: | cfergeau, dmalcolm, fweimer, jakub, jlaw, josmyers, jwakely, mcermak, mpolacek, msebor, nickc, nixuser, pbonzini, rjones, sam, sipoyare |
| Target Milestone: | --- | ||
| Target Release: | --- | ||
| Hardware: | Unspecified | ||
| OS: | Linux | ||
| Whiteboard: | |||
| Fixed In Version: | Doc Type: | --- | |
| Doc Text: | Story Points: | --- | |
| Clone Of: | Environment: | ||
| Last Closed: | Type: | --- | |
| Regression: | --- | Mount Type: | --- |
| Documentation: | --- | CRM: | |
| Verified Versions: | Category: | --- | |
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
| Cloudforms Team: | --- | Target Upstream Version: | |
| Embargoed: | |||
| Bug Depends On: | |||
| Bug Blocks: | 2424310 | ||
|
Description
Daniel Berrangé
2026-01-08 11:48:17 UTC
Koji log showing RPM versions - tldr: gcc-16.0.0-0.4.fc44 https://kojipkgs.fedoraproject.org//work/tasks/5317/140855317/root.log GCC since https://gcc.gnu.org/PR81358 indeed adds --push-state --as-needed -latomic --pop-state to the link line from the gcc/g++ etc. drivers, if -fno-link-libatomic option isn't used. And indeed this causes some issues with libtool which ignores the --push-state --as-needed and --pop-state wrappers around the -latomic option and so in some cases can link -latomic even when not really needed. Does qemu actually need -latomic? From the word about it previously buildrequiring libatomic-static I'd guess it does. But in that case I have no idea what further things changed. libatomic.a itself has been compiled with -fPIC both in GCC 15 and 16. QEMU added a BR on libatomic-static due to glib2 introducing a dep on libatomic - this was redundant in QEMU though, because glib2-static already had a Requires: libatomic-static dep. I'm unclear if QEMU explicitly needs -latomic or not - we've never directly added that ourselves in QEMU, but we use various atomic functions ? Passing the new -fno-link-libatomic flag to GCC avoids the QEMU build errors, but that still leaves the question of why linking to libatomic.a is broken to begin with in GCC 16 ? With GCC 15 if I explicitly added /usr/lib/gcc/x86_64-redhat-linux/15/libatomic.a to QEMU's linker args, we saw no PIE failures. Actually without -fPIC for both GCC 15 and 16, only libatomic.so.6 has been built with -fPIC. And it seems it never worked even in GCC 15: gcc --version gcc (GCC) 15.2.1 20251022 (Red Hat 15.2.1-3) Copyright (C) 2025 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. gcc -static-pie -fpie -o a a.c -Wl,--whole-archive -latomic -Wl,--no-whole-archive /usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/15/libatomic.a(gload.o): relocation R_X86_64_32S against `.rodata' can not be used when making a PIE object; recompile with -fPIE /usr/bin/ld: failed to set dynamic section sizes: bad value collect2: error: ld returned 1 exit status I've cut down the QEMU code until I found a minimal reproducer:
$ cat a.c
__int128_t demo(__int128_t cmpv, __int128_t newv)
{
__int128_t *ptr = 0x0;
(void)__atomic_compare_exchange_n(ptr, &cmpv, newv, false,
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return cmpv;
}
int main() {
demo(1, 1);
return 0;
}
Works GCC 16 with static build:
$ gcc --static ../accel/tcg/a.c
Fails GCC 16 with static PIE build:
$ gcc --static-pie ../accel/tcg/a.c
/usr/bin/ld: /usr/lib/gcc/x86_64-redhat-linux/16/libatomic.a(cas_16_.o): relocation R_X86_64_32 against hidden symbol `libat_compare_exchange_16_i1' can not be used when making a PIE object
/usr/bin/ld: failed to set dynamic section sizes: bad value
collect2: error: ld returned 1 exit status
This example also fails with GCC 15, so looks like a pre-existing bug in libatomic.a before GCC 16 too.
The reason why QEMU builds OK with GCC 15 is that it does NOT use __atomic_compare_exchange_n() with int128, as its configure script detects that as not supported, so QEMU did a fallback codepath using __sync_val_compare_and_swap_16 instead.
Based on the comment in include/qemu/atomic128.h you need to change the configure checks, because GCC 16's new behaviour of linking to libatomic automatically makes the check misbehave. The check thinks it can use __atomic_compare_exchange_n without involving libatomic, but actually it's just getting a libatomic call that no longer causes a linker error. (In reply to Jonathan Wakely from comment #7) > Based on the comment in include/qemu/atomic128.h you need to change the > configure checks, because GCC 16's new behaviour of linking to libatomic > automatically makes the check misbehave. The check thinks it can use > __atomic_compare_exchange_n without involving libatomic, but actually it's > just getting a libatomic call that no longer causes a linker error. Yeah, so we're back at needing to modify qemu's meson.buld script to always add -fno-link-libatomic, if GCC supports that arg. I'm still surprised libatomic.a breaks with -static-pie for int128 though. If that's a valid bug for GCC to fix then this bug could track it, otherwise feel free to close this and I'll fix QEMU's check regardless The reason for __atomic_compare_exchange_16 not being supported inline is that while CAS works, for __atomic_* one needs also working atomic load and because the loaded address can be also in .rodata section, CAS loop can't be used for that. And only recently Intel/AMD guaranteed in their docs that for AVX and higher vmovaps load is atomic if the address is 16-byte aligned, a few other chip makers did too but nobody from VIA said anything. So libatomic is used instead and has an IFUNC which selects hw instructions for AVX on Intel/AMD. While libgcc.a is built with -fPIE, I think libstdc++.a is too, most other *.a libraries are not and so are not supported in -static-pie. For the record, I've sent the following fix upstream to QEMU https://lists.nongnu.org/archive/html/qemu-devel/2026-01/msg01140.html > most other *.a libraries are not and so are not supported in -static-pie.
Should libatomic should be built with -fPIE, since it's added automatically (even if within as-needed)? For QEMU it's anyway the right thing to add -fno-link-libatomic, but still.
|