https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96385

--- Comment #13 from Richard Biener <rguenth at gcc dot gnu.org> ---
(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)
                {

Reply via email to