Hi.

The patch is about better symbol table manipulation
for debug info objects. The patch fixes reported issue
on hppa64-hp-hpux11.11.

Patch can bootstrap on x86_64-linux-gnu and survives regression tests.

Ready to be installed?
Thanks,
Martin

libiberty/ChangeLog:

2019-08-27  Martin Liska  <mli...@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.
---
 libiberty/simple-object-elf.c | 71 +++++++++++++++++++++++------------
 1 file changed, 48 insertions(+), 23 deletions(-)


diff --git a/libiberty/simple-object-elf.c b/libiberty/simple-object-elf.c
index 75159266596..b637e4b0c92 100644
--- a/libiberty/simple-object-elf.c
+++ b/libiberty/simple-object-elf.c
@@ -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,41 @@ 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.  */
+	  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_Addr);
+	    }
+
 	  for (ent = buf; ent < buf + length; ent += entsize)
 	    {
 	      unsigned st_shndx = ELF_FETCH_FIELD (type_functions, ei_class,
@@ -1426,9 +1448,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 +1483,15 @@ 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);
+				     ent, st_name, Elf_Addr,
+				     prevailing_name_idx);
+
 		      ELF_SET_FIELD (type_functions, ei_class, Sym,
 				     ent, st_shndx, Elf_Half, SHN_UNDEF);
 		    }
@@ -1482,7 +1508,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)

Reply via email to