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)