Created attachment 48956 [details] LTO debug output GCC may generate separate debug info files which contain undefined symbols without relocations. Here is the lto output from binutils LTO build: [hjl@gnu-cfl-2 binutils-cross-run]$ readelf -rsW /tmp/gcc.lto.debug.o | grep lreal 96: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND lrealpath [hjl@gnu-cfl-2 binutils-cross-run]$ It triggered a linker bug: https://sourceware.org/bugzilla/show_bug.cgi?id=26314
Such early debug is bogus - do you have the preprocessed source for the corresponding TU?
A testcase is on pr96385 branch at: https://gitlab.com/x86-gcc/gcc-bugs
On Thu, 30 Jul 2020, hjl.tools at gmail dot com wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96385 > > H.J. Lu <hjl.tools at gmail dot com> changed: > > What |Removed |Added > ---------------------------------------------------------------------------- > Status|WAITING |NEW > > --- Comment #2 from H.J. Lu <hjl.tools at gmail dot com> --- > A testcase is on pr96385 branch at: > > https://gitlab.com/x86-gcc/gcc-bugs I'd like to have the _source_ to whichever of the .o files has the bogus relocation in the .gnulto.debug_info section. The bug happens at the compile stage.
On Thu, 30 Jul 2020, rguenther at suse dot de wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96385 > > --- Comment #3 from rguenther at suse dot de <rguenther at suse dot de> --- > On Thu, 30 Jul 2020, hjl.tools at gmail dot com wrote: > > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96385 > > > > H.J. Lu <hjl.tools at gmail dot com> changed: > > > > What |Removed |Added > > ---------------------------------------------------------------------------- > > Status|WAITING |NEW > > > > --- Comment #2 from H.J. Lu <hjl.tools at gmail dot com> --- > > A testcase is on pr96385 branch at: > > > > https://gitlab.com/x86-gcc/gcc-bugs > > I'd like to have the _source_ to whichever of the .o files > has the bogus relocation in the .gnulto.debug_info section. > > The bug happens at the compile stage. More specifically, .rela.gnu.debuglto_.debug_info may only contain relocations to other .gnu.debuglto_.* sections and definitely _not_ relocations to UNDEF symbols.
Please get users/hjl/pr26314/test branch at https://gitlab.com/x86-binutils/binutils-gdb/-/tree/users/hjl/pr26314/test and build binutils with GCC 10: CC="/usr/gcc-10.1.1-x32/bin/gcc -flto -ffat-lto-objects -Wl,--as-needed -fcf-protection" CXX="/usr/gcc-10.1.1-x32/bin/g++ -flto -ffat-lto-objects -Wl,--as-needed -fcf-protection" /export/gnu/import/git/gitlab/x86-binutils/configure \ --enable-shared \ \ --enable-plugins --disable-gdb --disable-gdbserver --disable-libdecnumber --disable-readline --disable-sim --with-sysroot=/ --with-system-zlib \ --prefix=/usr/local \ --with-local-prefix=/usr/local I got [hjl@gnu-cfl-2 build-x86_64-linux]$ nm -D binutils/.libs/ar | grep lrealpath 0000000000000000 A lrealpath [hjl@gnu-cfl-2 build-x86_64-linux]$
There is a small testcase in https://sourceware.org/bugzilla/show_bug.cgi?id=26324
[hjl@gnu-cfl-2 pr26324]$ cat pr15146a.c extern int xxx; int bar (void) { return xxx; } int main () { return 0; } [hjl@gnu-cfl-2 pr26324]$ cat pr15146b.c int xxx = 3; [hjl@gnu-cfl-2 pr26324]$ cat pr15146c.c [hjl@gnu-cfl-2 pr26324]$ make gcc -B./ -O2 -g -o x -Wl,-R,. \ -Wl,--no-copy-dt-needed-entries -Wl,--no-as-needed pr15146a.o pr15146c.so ./ld: /tmp/ccHirkTe.debug.temp.o: undefined reference to symbol 'xxx' ./ld: ./pr15146b.so: error adding symbols: DSO missing from command line collect2: error: ld returned 1 exit status make: *** [Makefile:15: x] Error 1 [hjl@gnu-cfl-2 pr26324]$
The original pr26324a.o debug info contains reference to xxx. But reference to xxx has been removed by LTO. simple_object_copy_lto_debug_sections fails to remove the un-referenced symbol, xxx, from symbol table.
Created attachment 48975 [details] A testcase [hjl@gnu-cfl-2 pr26324]$ make gcc -B./ -O2 -g -flto -ffat-lto-objects -c -o pr26324a.o pr26324a.c gcc -B./ -O2 -g -fPIC -c -o pr15146c.o pr15146c.c gcc -B./ -O2 -g -fPIC -c -o pr15146b.o pr15146b.c gcc -B./ -shared -o pr15146b.so pr15146b.o gcc -B./ -shared -o pr15146c.so pr15146c.o pr15146b.so gcc -B./ -O2 -g -o x -Wl,-R,. \ -Wl,--no-copy-dt-needed-entries -Wl,--no-as-needed pr26324a.o pr15146c.so ./ld: /tmp/ccCGQCqp.debug.temp.o: undefined reference to symbol 'xxx' ./ld: ./pr15146b.so: error adding symbols: DSO missing from command line collect2: error: ld returned 1 exit status make: *** [Makefile:20: x] Error 1 [hjl@gnu-cfl-2 pr26324]$ -flto -ffat-lto-objects is the key.
(In reply to H.J. Lu from comment #8) > The original pr26324a.o debug info contains reference to xxx. But reference > to xxx has been removed by LTO. simple_object_copy_lto_debug_sections fails > to remove the un-referenced symbol, xxx, from symbol table. The alternative is to ask linker to handle it: https://sourceware.org/pipermail/binutils/2020-July/112673.html
GCC 7.3.1 is OK: [hjl@gnu-cfl-2 pr26324]$ make /usr/gcc-7.3.1-x32/bin/gcc -B./ -O2 -g -flto -ffat-lto-objects -c -o pr26324a.o pr26324a.c /usr/gcc-7.3.1-x32/bin/gcc -B./ -O2 -g -fPIC -c -o pr15146c.o pr15146c.c /usr/gcc-7.3.1-x32/bin/gcc -B./ -O2 -g -fPIC -c -o pr15146b.o pr15146b.c /usr/gcc-7.3.1-x32/bin/gcc -B./ -shared -o pr15146b.so pr15146b.o /usr/gcc-7.3.1-x32/bin/gcc -B./ -shared -o pr15146c.so pr15146c.o pr15146b.so /usr/gcc-7.3.1-x32/bin/gcc -B./ -O2 -g -o x -Wl,-R,. \ -Wl,--no-copy-dt-needed-entries -Wl,--no-as-needed pr26324a.o pr15146c.so ./x PASS [hjl@gnu-cfl-2 pr26324]$
(In reply to H.J. Lu from comment #10) > (In reply to H.J. Lu from comment #8) > > The original pr26324a.o debug info contains reference to xxx. But reference > > to xxx has been removed by LTO. simple_object_copy_lto_debug_sections fails > > to remove the un-referenced symbol, xxx, from symbol table. > > The alternative is to ask linker to handle it: > > https://sourceware.org/pipermail/binutils/2020-July/112673.html The bug is we create the reference in the first place.
(In reply to Richard Biener from comment #12) > (In reply to H.J. Lu from comment #10) > > (In reply to H.J. Lu from comment #8) > > > The original pr26324a.o debug info contains reference to xxx. But reference > > > to xxx has been removed by LTO. simple_object_copy_lto_debug_sections fails > > > to remove the un-referenced symbol, xxx, from symbol table. > > > > The alternative is to ask linker to handle it: > > > > https://sourceware.org/pipermail/binutils/2020-July/112673.html > > The bug is we create the reference in the first place. Oh, I see. So we had multiple choices for "pruning" symbols from the symbol table during simple_object_copy_lto_debug_sections and factoring in HP-UX and Solaris (sic!...) emptying UND symbol names didn't work out. So we do now if (discard) { /* Make discarded symbols undefined and unnamed in case it is local. */ int bind = ELF_ST_BIND (*st_info); int other = STV_DEFAULT; if (bind == STB_LOCAL) { /* Make discarded local symbols unnamed and defined in the first prevailing section. */ ELF_SET_FIELD (type_functions, ei_class, Sym, ent, st_name, Elf_Word, 0); ELF_SET_FIELD (type_functions, ei_class, Sym, ent, st_shndx, Elf_Half, sh_map[first_shndx]); } else { /* Make discarded global symbols hidden weak undefined and sharing a name of a prevailing symbol. */ bind = STB_WEAK; other = STV_HIDDEN; ELF_SET_FIELD (type_functions, ei_class, Sym, ent, st_name, Elf_Word, prevailing_name_idx); ELF_SET_FIELD (type_functions, ei_class, Sym, ent, st_shndx, Elf_Half, SHN_UNDEF); } *st_other = other; *st_info = ELF_ST_INFO (bind, STT_NOTYPE); ELF_SET_FIELD (type_functions, ei_class, Sym, ent, st_value, Elf_Addr, 0); ELF_SET_FIELD (type_functions, ei_class, Sym, ent, st_size, Elf_Word, 0); } but somehow the else path isn't triggered(?). Note that all we try to avoid is the need to rewrite relocation sections if we really would prune symbols rather than NULL-ifying them somehow. You can trace history as to how the above code morphed with various bugs in the past... Hmm, we don't treat SHN_UNDEF any special here - I guess we could at most make all of them WEAK ... the following should address this. diff --git a/libiberty/simple-object-elf.c b/libiberty/simple-object-elf.c index c62d5bba551..7c9d492f6a4 100644 --- a/libiberty/simple-object-elf.c +++ b/libiberty/simple-object-elf.c @@ -1467,6 +1467,11 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj, && st_shndx < shnum && pfnret[st_shndx - 1] == -1) discard = 1; + /* We also need to remove global UNDEFs which can + cause link fails later. */ + else if (st_shndx == SHN_UNDEF + && ELF_ST_BIND (*st_info) == STB_GLOBAL) + discard = 1; if (discard) {
Note the symbol table entry should be "unused" (if there's anything like that). At least ld usually treats it like so. IIRC I left those dangling because UNDEFs into the copied .debug_info section are bogus - and I did not want to parse relocation sections to see where it is referenced from (otherwise I'd assert for such UNDEFs). I know it's all a bit awkward but originally this was supposed to be a temporary measure until ld + plugin API understands how to only partly claim an object and make ld link the original .gnu.debuglto_ prefixed debug-info sections unchanged into the final object ... So you basically found a case where ld does _not_ treat the UNDEF as "unused". In case that is not a bug in ld I am not really understanding how the bug manifests which means I have a hard time creating a testcase for GCCs LTO testsuite :/ Now the patch itself should be quite safe (we shouldn't be left with any global UNDEFs). But I'm curious if it resolves a "real" bug...
I also wonder if the result of the patch, 34: 0000000000000000 0 NOTYPE WEAK HIDDEN 1 t.c.5958f17d 35: 0000000000000000 0 NOTYPE WEAK HIDDEN UND t.c.5958f17d 36: 0000000000000000 0 NOTYPE WEAK HIDDEN UND t.c.5958f17d 37: 0000000000000000 0 NOTYPE WEAK HIDDEN UND t.c.5958f17d is in any way "safer" from an ELF perspective (not so much GNU ld since we've dealt with Solaris and HP-UX linker issues in the past). Alan, you fiddled with this earlier so any comments?
It looks fine to me, assuming you don't need to keep any of these undefined symbols.
The master branch has been updated by Richard Biener <rguenth@gcc.gnu.org>: https://gcc.gnu.org/g:b32c5d0b72fda2588b4e170e75a9c64e4bf266c7 commit r11-2506-gb32c5d0b72fda2588b4e170e75a9c64e4bf266c7 Author: Richard Biener <rguenther@suse.de> Date: Mon Aug 3 15:05:37 2020 +0200 lto/96385 - avoid unused global UNDEFs in debug objects Unused global UNDEFs can have side-effects in some circumstances so the following patch avoids them by treating them the same as other to be discarded DEFs - make them local. 2020-08-03 Richard Biener <rguenther@suse.de> PR lto/96385 libiberty/ * simple-object-elf.c (simple_object_elf_copy_lto_debug_sections): Localize global UNDEFs and reuse the prevailing name.
So let's see whether HPUX or Solaris folks complain.
The releases/gcc-10 branch has been updated by Richard Biener <rguenth@gcc.gnu.org>: https://gcc.gnu.org/g:63a2bdbfb42628800a6999e98804928855592ce7 commit r10-8746-g63a2bdbfb42628800a6999e98804928855592ce7 Author: Richard Biener <rguenther@suse.de> Date: Mon Aug 3 15:05:37 2020 +0200 lto/96385 - avoid unused global UNDEFs in debug objects Unused global UNDEFs can have side-effects in some circumstances so the following patch avoids them by treating them the same as other to be discarded DEFs - make them local. 2020-08-03 Richard Biener <rguenther@suse.de> PR lto/96385 libiberty/ * simple-object-elf.c (simple_object_elf_copy_lto_debug_sections): Localize global UNDEFs and reuse the prevailing name. (cherry picked from commit b32c5d0b72fda2588b4e170e75a9c64e4bf266c7)
The releases/gcc-9 branch has been updated by Richard Biener <rguenth@gcc.gnu.org>: https://gcc.gnu.org/g:969be2412231d3bdd73300ac32684d416345a029 commit r9-9340-g969be2412231d3bdd73300ac32684d416345a029 Author: Richard Biener <rguenther@suse.de> Date: Mon Aug 3 15:05:37 2020 +0200 lto/96385 - avoid unused global UNDEFs in debug objects Unused global UNDEFs can have side-effects in some circumstances so the following patch avoids them by treating them the same as other to be discarded DEFs - make them local. 2020-08-03 Richard Biener <rguenther@suse.de> PR lto/96385 libiberty/ * simple-object-elf.c (simple_object_elf_copy_lto_debug_sections): Localize global UNDEFs and reuse the prevailing name. (cherry picked from commit b32c5d0b72fda2588b4e170e75a9c64e4bf266c7)
The releases/gcc-8 branch has been updated by Richard Biener <rguenth@gcc.gnu.org>: https://gcc.gnu.org/g:e6a720bf5b1328ff018880063ae3d1e777e5b61d commit r8-10922-ge6a720bf5b1328ff018880063ae3d1e777e5b61d Author: Richard Biener <rguenther@suse.de> Date: Mon Aug 3 15:05:37 2020 +0200 lto/96385 - avoid unused global UNDEFs in debug objects Unused global UNDEFs can have side-effects in some circumstances so the following patch avoids them by treating them the same as other to be discarded DEFs - make them local. 2020-08-03 Richard Biener <rguenther@suse.de> PR lto/96385 libiberty/ * simple-object-elf.c (simple_object_elf_copy_lto_debug_sections): Localize global UNDEFs and reuse the prevailing name. (cherry picked from commit b32c5d0b72fda2588b4e170e75a9c64e4bf266c7)
Fixed.