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).