Share a prevailing name for remove debug info symbols w/ LTO.
authorMartin Liska <mliska@suse.cz>
Tue, 27 Aug 2019 13:36:15 +0000 (15:36 +0200)
committerMartin Liska <marxin@gcc.gnu.org>
Tue, 27 Aug 2019 13:36:15 +0000 (13:36 +0000)
2019-08-27  Martin Liska  <mliska@suse.cz>

PR lto/91478
* simple-object-elf.c (simple_object_elf_copy_lto_debug_sections):
First find a WEAK HIDDEN symbol in symbol table that will be
preserved.  Later, use the symbol name for all removed symbols.

From-SVN: r274955

libiberty/ChangeLog
libiberty/simple-object-elf.c

index c1fe2f62b44de0fddd76afc11a54bfc137aeea42..cf101e7f8a12f785a6749e133202da637064e3ea 100644 (file)
@@ -1,3 +1,10 @@
+2019-08-27  Martin Liska  <mliska@suse.cz>
+
+       PR lto/91478
+       * simple-object-elf.c (simple_object_elf_copy_lto_debug_sections):
+       First find a WEAK HIDDEN symbol in symbol table that will be
+       preserved.  Later, use the symbol name for all removed symbols.
+
 2019-08-12  Martin Liska  <mliska@suse.cz>
 
        * Makefile.in: Add filedescriptor.c.
index 7515926659694ba930aa0a7d1a22e84b05c117c8..03ca42498f3028a2e25e48c124f4352644d3ead1 100644 (file)
@@ -1366,30 +1366,17 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
          return errmsg;
        }
 
-      /* If we are processing .symtab purge __gnu_lto_slim symbol
-        from it and any symbols in discarded sections.  */
+      /* If we are processing .symtab purge any symbols
+        in discarded sections.  */
       if (sh_type == SHT_SYMTAB)
        {
          unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
                                              shdr, sh_entsize, Elf_Addr);
          unsigned strtab = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
                                             shdr, sh_link, Elf_Word);
-         unsigned char *strshdr = shdrs + (strtab - 1) * shdr_size;
-         off_t stroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
-                                         strshdr, sh_offset, Elf_Addr);
-         size_t strsz = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
-                                         strshdr, sh_size, Elf_Addr);
-         char *strings = XNEWVEC (char, strsz);
-         char *gnu_lto = strings;
+         size_t prevailing_name_idx = 0;
          unsigned char *ent;
          unsigned *shndx_table = NULL;
-         simple_object_internal_read (sobj->descriptor,
-                                      sobj->offset + stroff,
-                                      (unsigned char *)strings,
-                                      strsz, &errmsg, err);
-         /* Find first '\0' in strings.  */
-         gnu_lto = (char *) memchr (gnu_lto + 1, '\0',
-                                    strings + strsz - gnu_lto);
          /* Read the section index table if present.  */
          if (symtab_indices_shndx[i - 1] != 0)
            {
@@ -1404,6 +1391,45 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
                                           (unsigned char *)shndx_table,
                                           sidxsz, &errmsg, err);
            }
+
+         /* Find a WEAK HIDDEN symbol which name we will use for removed
+            symbols.  We know there's a prevailing weak hidden symbol
+            at the start of the .debug_info section.  */
+         for (ent = buf; ent < buf + length; ent += entsize)
+           {
+             unsigned st_shndx = ELF_FETCH_FIELD (type_functions, ei_class,
+                                                  Sym, ent,
+                                                  st_shndx, Elf_Half);
+             unsigned char *st_info;
+             unsigned char *st_other;
+             if (ei_class == ELFCLASS32)
+               {
+                 st_info = &((Elf32_External_Sym *)ent)->st_info;
+                 st_other = &((Elf32_External_Sym *)ent)->st_other;
+               }
+             else
+               {
+                 st_info = &((Elf64_External_Sym *)ent)->st_info;
+                 st_other = &((Elf64_External_Sym *)ent)->st_other;
+               }
+             if (st_shndx == SHN_XINDEX)
+               st_shndx = type_functions->fetch_Elf_Word
+                   ((unsigned char *)(shndx_table + (ent - buf) / entsize));
+
+             if (st_shndx != SHN_COMMON
+                 && !(st_shndx != SHN_UNDEF
+                      && st_shndx < shnum
+                      && pfnret[st_shndx - 1] == -1)
+                 && ELF_ST_BIND (*st_info) == STB_WEAK
+                 && *st_other == STV_HIDDEN)
+               {
+                 prevailing_name_idx = ELF_FETCH_FIELD (type_functions,
+                                                        ei_class, Sym, ent,
+                                                        st_name, Elf_Word);
+                 break;
+               }
+           }
+
          for (ent = buf; ent < buf + length; ent += entsize)
            {
              unsigned st_shndx = ELF_FETCH_FIELD (type_functions, ei_class,
@@ -1426,9 +1452,10 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
              if (st_shndx == SHN_XINDEX)
                st_shndx = type_functions->fetch_Elf_Word
                    ((unsigned char *)(shndx_table + (ent - buf) / entsize));
-             /* Eliminate all COMMONs - this includes __gnu_lto_v1
-                and __gnu_lto_slim which otherwise cause endless
-                LTO plugin invocation.  */
+             /* Eliminate all COMMONs - this includes __gnu_lto_slim
+                which otherwise cause endless LTO plugin invocation.
+                FIXME: remove the condition once we remove emission
+                of __gnu_lto_slim symbol.  */
              if (st_shndx == SHN_COMMON)
                discard = 1;
              /* We also need to remove symbols refering to sections
@@ -1460,12 +1487,13 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
                  else
                    {
                      /* Make discarded global symbols hidden weak
-                        undefined and sharing the gnu_lto_ name.  */
+                        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,
-                                    gnu_lto - strings);
+                                    prevailing_name_idx);
                      ELF_SET_FIELD (type_functions, ei_class, Sym,
                                     ent, st_shndx, Elf_Half, SHN_UNDEF);
                    }
@@ -1482,7 +1510,6 @@ simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
                ELF_SET_FIELD (type_functions, ei_class, Sym,
                               ent, st_shndx, Elf_Half, sh_map[st_shndx]);
            }
-         XDELETEVEC (strings);
          XDELETEVEC (shndx_table);
        }
       else if (sh_type == SHT_GROUP)