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

Reply via email to