The following enables a hpux specific workaround for the WEAK UNDEF symbols used by LTO debuginfo extraction. It makes sure to use a special name (gnu_lto_v1) for those.
It also adjusts removed local symbols to not use UNDEFs (similar to solaris ld for globals hpux doesn't like undefs it cannot resolve even if they are unused). Instead it uses DEFS with NULL name. I also fixed some readelf complaints about stale sh_info/link in removed sections. (maybe that fixes the solaris complaints? ... just having some christmas wishes ;)) LTO Bootstrapped and tested on x86_64-unknown-linux-gnu. I've tested GNU ld and gold for a simple testcase exercising multiple WEAK UNDEFs with the same name and local defs, they seem happy (but they also retain all those local defs now in the partial link ... :/) I'll probably see to implement "real" section removal in stage3 to fix the Solaris complaints but I hope to not need reloc section rewriting (aka really pruning stuff from the symtab). If I hear back from John / Rainer about this patch (or Alan) I see to commit this during the holidays when it is convenient. Richard. 2017-12-19 Richard Biener <rguent...@suse.de> PR lto/83452 * simple-object-elf.c (simple_object_elf_copy_lto_debug_section): Do not use UNDEF locals for removed symbols but instead just define them in the first prevailing section and with no name. Use the same gnu_lto_v1 name for all removed globals we promote to WEAK UNDEFs so hpux can use a stub to provide this symbol. Clear sh_info and sh_link in removed sections. Index: libiberty/simple-object-elf.c =================================================================== --- libiberty/simple-object-elf.c (revision 255777) +++ libiberty/simple-object-elf.c (working copy) @@ -1091,6 +1091,7 @@ simple_object_elf_copy_lto_debug_section int changed; int *pfnret; const char **pfnname; + unsigned first_shndx = 0; shdr_size = (ei_class == ELFCLASS32 ? sizeof (Elf32_External_Shdr) @@ -1158,6 +1159,9 @@ simple_object_elf_copy_lto_debug_section ret = (*pfn) (&name); pfnret[i - 1] = ret == 1 ? 0 : -1; pfnname[i - 1] = name; + if (first_shndx == 0 + && pfnret[i - 1] == 0) + first_shndx = i; } /* Mark sections as preserved that are required by to be preserved @@ -1327,6 +1331,15 @@ simple_object_elf_copy_lto_debug_section sobj->offset + stroff, (unsigned char *)strings, strsz, &errmsg, err); + /* Find gnu_lto_ in strings. */ + char *gnu_lto = strings; + while ((gnu_lto = memchr (gnu_lto, 'g', + strings + strsz - gnu_lto))) + if (strncmp (gnu_lto, "gnu_lto_v1", + strings + strsz - gnu_lto) == 0) + break; + else + gnu_lto++; for (ent = buf; ent < buf + length; ent += entsize) { unsigned st_shndx = ELF_FETCH_FIELD (type_functions, ei_class, @@ -1366,31 +1379,27 @@ simple_object_elf_copy_lto_debug_section in case it is local. */ int bind = ELF_ST_BIND (*st_info); int other = STV_DEFAULT; - size_t st_name; - if (bind == STB_LOCAL) - ELF_SET_FIELD (type_functions, ei_class, Sym, - ent, st_name, Elf_Word, 0); + { + /* 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, first_shndx); + } else { + /* Make discarded global symbols hidden weak + undefined and sharing the gnu_lto_ name. */ bind = STB_WEAK; - st_name = ELF_FETCH_FIELD (type_functions, ei_class, - Sym, ent, st_name, - Elf_Word); - if (st_name < strsz) - { - char *p = strings + st_name; - if (p[0] == '_' - && p[1] == '_' - && strncmp (p + (p[2] == '_'), - "__gnu_lto_", 10) == 0) - { - other = STV_HIDDEN; - ELF_SET_FIELD (type_functions, ei_class, Sym, - ent, st_name, Elf_Word, - st_name + 2); - } - } + other = STV_HIDDEN; + if (gnu_lto) + ELF_SET_FIELD (type_functions, ei_class, Sym, + ent, st_name, Elf_Word, + gnu_lto - strings); + 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); @@ -1398,8 +1407,6 @@ simple_object_elf_copy_lto_debug_section ent, st_value, Elf_Addr, 0); ELF_SET_FIELD (type_functions, ei_class, Sym, ent, st_size, Elf_Word, 0); - ELF_SET_FIELD (type_functions, ei_class, Sym, - ent, st_shndx, Elf_Half, SHN_UNDEF); } } XDELETEVEC (strings); @@ -1422,6 +1429,10 @@ simple_object_elf_copy_lto_debug_section link. */ ELF_SET_FIELD (type_functions, ei_class, Shdr, shdr, sh_type, Elf_Word, SHT_NULL); + ELF_SET_FIELD (type_functions, ei_class, Shdr, + shdr, sh_info, Elf_Word, 0); + ELF_SET_FIELD (type_functions, ei_class, Shdr, + shdr, sh_link, Elf_Word, 0); } flags = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,