https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84847
Bug ID: 84847 Summary: [8 Regression] Incompatibility between early LTO debug and "-Wl,--gc-sections" leads to corrupt DWARF debuginfo Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: lto Assignee: unassigned at gcc dot gnu.org Reporter: dmalcolm at gcc dot gnu.org CC: marxin at gcc dot gnu.org, nickc at gcc dot gnu.org, rguenth at gcc dot gnu.org Target Milestone: --- The downstream bug report: https://bugzilla.redhat.com/show_bug.cgi?id=1543912 describes a problem building systemd and systemd-bootchart with gcc 8, which turned out to be due to those packages' configure scripts injecting both -flto and -Wl,--gc-sections They build fine with just one of them, but with both, the binaries have corrupt DWARF debuginfo. Adding "-Wl,--print-gc-sections" shows the issue more clearly. I created a minimal reproducer here: https://github.com/davidmalcolm/rhbz-1543912 with which I can reproduce the issue, using: gcc-8.0.1-0.16.fc29.x86_64 binutils-2.30-6.fc29.x86_64 (this is on Fedora in a chroot via "mock -r fedora-rawhide-x86_64 shell"; I'm still working on reproducing this outside a chroot) $ make gcc -I ./src -flto -O2 -g -c src/bootchart.c -o build/bootchart.o gcc -I ./src -flto -O2 -g -c src/log.c -o build/log.o gcc -flto -g -Wl,--gc-sections -Wl,--print-gc-sections \ build/bootchart.o build/log.o \ -o build/systemd-bootchart /usr/bin/ld: Removing unused section '.rodata.cst4' in file '/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crt1.o' /usr/bin/ld: Removing unused section '.data' in file '/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/crt1.o' /usr/bin/ld: Removing unused section '.rodata' in file '/usr/lib/gcc/x86_64-redhat-linux/8/crtbegin.o' /usr/bin/ld: Removing unused section '.debug_abbrev' in file '/tmp/cc1vnNPxdebugobj' /usr/bin/ld: Removing unused section '.debug_str' in file '/tmp/cc1vnNPxdebugobj' /usr/lib/rpm/debugedit build/systemd-bootchart /usr/lib/rpm/debugedit: build/systemd-bootchart: Invalid .line_table offset 0x2b0803 /usr/lib/rpm/debugedit: build/systemd-bootchart: Could not find DWARF abbreviation 7 In the above, note how ld has garbage-collected the '.debug_abbrev' and '.debug_str' sections from the /tmp/cc*debugobj file. Examining the binary via eu-readelf -w build/systemd-bootchart shows bogus-looking compile_unit DIEs in the binary: DWARF section [23] '.debug_info' at offset 0x10a6: [Offset] Compilation unit at offset 0: Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4 [ b] compile_unit producer (strp) "/builddir/build/BUILD/minimizing-2" language (data1) C99 (12) name (strp) "/builddir/build/BUILD/minimizing-2" comp_dir (strp) "/builddir/build/BUILD/minimizing-2" ranges (sec_offset) range list [ 2] low_pc (addr) 0x000000250e030100 Compilation unit at offset 105: Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4 [ 74] compile_unit producer (strp) "/builddir/build/BUILD/minimizing-2" language (data1) C99 (12) name (strp) "/builddir/build/BUILD/minimizing-2" comp_dir (strp) "/builddir/build/BUILD/minimizing-2" ranges (sec_offset) range list [ 2] low_pc (addr) 0x0000870006030100 Note how every string is using string 0. Removing the -Wl,--gc-sections leads to sane-looking DIEs. The issue seems to be that lto-wrapper generates /tmp/cc*debugobj files containing "early LTO debug info", but, quoting Nick in: https://bugzilla.redhat.com/show_bug.cgi?id=1543912#c22 > I have now found out what it happening, although I am still a little bit > confused as to why it should be occurring. The LTO pass is producing an > object file that only contains debug information: > > /dev/shm/ccqhNEybdebugobj > > (There was a clue in the filename, but I did not pay attention to this). > > The linker's garbage collection code reasons that any file that does not > have *any* allocatable sections[1] can automatically be discarded, since it > cannot have any effect on the execution of the resulting binary, right ? > ... > > So this is why the .debug_abbrev and .debug_str sections are being > discarded. > I do not know why the LTO pass is producing this file. Perhaps someone > else > more familiar with LTO can explain. > > A simple fix would be remove the code from the linker's garbage collector > that discards non-allocatable input files, but this seems rather heavy > handed. I would rather know if there is some way to deduce that a given > file really is needed, despite it only containing debug information, and > then choose to keep it. I guess it all comes down to why the LTO pass is > generating this file, and what it contains. > > Cheers > Nick > > [1]. Actually the linker first checks to see if any allocatable sections > can be discarded. Then if the file did not contain any allocatable > sections, or all of the allocatable sections can be discarded, then the > whole file is discarded. Nick has posted a patch for lto-wrapper at: https://bugzilla.redhat.com/show_bug.cgi?id=1543912#c28 as a workaround for this (actually, a 2nd iteration, based on some nit-picking by me - but Richard is the expert at this).