GCC 15.2.0-16 produces non-deterministic DWARF debug information when building the same source twice with identical flags, parallelism, and build environment on amd64. The generated machine code is byte-for-byte identical across builds, but .debug_info and .debug_loclists differ in size and content. All other debug sections (.debug_abbrev, .debug_line, .debug_str, .debug_line_str, .debug_aranges, .debug_rnglists) are identical. Because the build-id is computed over the unstripped binary, the differing debug sections cause the build-id to change, which then propagates into the stripped binary via .gnu_debuglink. The end result is that the final .deb is not reproducible even though the actual executable code has not changed. I confirmed this is not caused by dwz by repeating the test with dh_dwz disabled. The result is the same. I was unable to reproduce this with a small standalone test case; it may require a large codebase to trigger. If this turns out to be a linker issue, please reassign to binutils. I noticed this while investigating reproducibility failures for the quickshell package (src:quickshell, 0.2.1-1). The Salsa CI debrebuild job passed with gcc-15 15.2.0-14 and began failing after the update to 15.2.0-16. Both builds in my local test used sbuild with ninja -j2, the same build path, the same SOURCE_DATE_EPOCH, and the same package versions. In a local two-build comparison (dwz disabled), the debug section sizes were: .debug_info: 0x34eaf8c vs 0x34eb0aa (+286 bytes) .debug_loclists: 0x30c72c vs 0x30c729 (-3 bytes) The stripped binary differed in only 61 bytes, all within .note.gnu.build-id and .gnu_debuglink. The reproducible-builds.org results for this package can be seen at: https://tests.reproducible-builds.org/debian/rb-pkg/unstable/amd64/quickshell.html https://tests.reproducible-builds.org/debian/rb-pkg/forky/amd64/quickshell.html
I'm unaware of any Debian specific changes that might have caused that. So once you have a reproducer, please report that upstream. You can find the date of the gcc-15 branch used in the Debian changelog. Checking that with gcc-16 (trunk) would also be helpful.
I've narrowed this down to precompiled header (.gch) generation. Building quickshell twice in unstable sbuild chroot with gcc-15 15.2.0-16, ninja -j2, same build path, same SOURCE_DATE_EPOCH results in 6 out of 475 .o files differing between builds. The set of differing files changes each run, however all 6 .gch files differ every time. They are: qs-pchset-common.dir/cmake_pch.hxx.gch qs-pchset-large.dir/cmake_pch.hxx.gch qs-pchset-plugin.dir/cmake_pch.hxx.gch qs-pchset-dbus.dir/cmake_pch.hxx.gch qs-pchset-launch.dir/cmake_pch.hxx.gch qs-pchset-wayland-protocol.dir/cmake_pch.hxx.gch Recompiling the same .cpp file twice against the same .gch produces identical .o files. The non-determinism is entirely in the .gch generation itself. The debug info (.debug_info, .debug_loclists) serialized into the PCH varies between runs, and the .o files that include the PCH inherit this. The .text, .rodata and all code/data sections are identical across builds. Only debug sections differ. Also tested with gcc-16 (16.0.1 20260308, trunk r16-7949) and get the same issue. All 6 PCH files differ, and 33 out of 475 .o files differ (vs 6 with gcc-15). I will file this upstream on GCC bugzilla.
This was reported upstream at: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124811 It is now fixed on GCC master: commit cc08be7bf549072bf3699a57d3d37222e8c1087d (r17-3240) (https://gcc.gnu.org/g:cc08be7bf549072bf3699a57d3d37222e8c1087d) The commit is on master only and has not been backported to the gcc-15 branch yet, so gcc-15 is still affected until it is picked up. I thought this update would be helpful. Regards, Michael Lloyd