|
 |
d570a8 |
commit b53dfeb26ed06e97fff1e8f469e33637ebdf6624
|
|
 |
d570a8 |
Author: Alan Modra <amodra@gmail.com>
|
|
 |
d570a8 |
Date: Sat Oct 18 21:46:48 2014 +1030
|
|
 |
d570a8 |
|
|
 |
d570a8 |
PowerPC64 ELFv1 function symbol definition vs LTO and discarded sections
|
|
 |
d570a8 |
|
|
 |
d570a8 |
When functions are emitted in comdat groups, global symbols defined in
|
|
 |
d570a8 |
duplicates of the group are treated as if they were undefined. That
|
|
 |
d570a8 |
prevents the symbols in the discarded sections from affecting the
|
|
 |
d570a8 |
linker's global symbol hash table or causing duplicate symbol errors.
|
|
 |
d570a8 |
Annoyingly, when gcc emits a function to a comdat group, it does not
|
|
 |
d570a8 |
put *all* of a function's code and data in the comdat group.
|
|
 |
d570a8 |
Typically, constant tables, exception handling info, and debug info
|
|
 |
d570a8 |
are emitted to normal sections outside of the group, which is a
|
|
 |
d570a8 |
perennial source of linker problems due to the special handling needed
|
|
 |
d570a8 |
to deal with the extra-group pieces that ought to be discarded. In
|
|
 |
d570a8 |
the case of powerpc64-gcc, the OPD entry for a function is not put in
|
|
 |
d570a8 |
the group. Since the function symbol is defined on the OPD entry this
|
|
 |
d570a8 |
means we need to handle symbols in .opd specially.
|
|
 |
d570a8 |
|
|
 |
d570a8 |
To see how this affects LTO in particular, consider the linker
|
|
 |
d570a8 |
testcase PR ld/12942 (1). This testcase links an LTO object file
|
|
 |
d570a8 |
pr12942a.o with a normal (non-LTO) object pr12942b.o. Both objects
|
|
 |
d570a8 |
contain a definition for _Z4testv in a comdat group. On loading
|
|
 |
d570a8 |
pr12942a.o, the linker sees a comdat group (actually linkonce section)
|
|
 |
d570a8 |
for _Z4testv and a weak _Z4testv defined in the IR. On loading
|
|
 |
d570a8 |
pr12942b.o, the linker sees the same comdat group, and thus discards
|
|
 |
d570a8 |
it. However, _Z4testv is a weak symbol defined in .opd, not part of
|
|
 |
d570a8 |
the group, so this weak symbol overrides the weak IR symbol. On
|
|
 |
d570a8 |
(re)loading the LTO version of pr12942a.o, the linker sees another
|
|
 |
d570a8 |
weak _Z4testv, but this one does not override the value we have from
|
|
 |
d570a8 |
pr12942b.o. The result is a linker complaint about "`_Z4testv'
|
|
 |
d570a8 |
... defined in discarded section `.group' of tmpdir/pr12942b.o".
|
|
 |
d570a8 |
|
|
 |
d570a8 |
* elf64-ppc.c (ppc64_elf_add_symbol_hook): If function code
|
|
 |
d570a8 |
section for function symbols defined in .opd is discarded, let
|
|
 |
d570a8 |
the symbol appear to be undefined.
|
|
 |
d570a8 |
(opd_entry_value): Ensure the result section is that for the
|
|
 |
d570a8 |
function code section in the same object as the OPD entry.
|
|
 |
d570a8 |
|
|
 |
d570a8 |
--- a/bfd/elf64-ppc.c 2015-02-06 19:28:48.000000000 -0500
|
|
 |
d570a8 |
+++ b/bfd/elf64-ppc.c 2015-02-06 19:24:12.000000000 -0500
|
|
 |
d570a8 |
@@ -4774,22 +4774,37 @@
|
|
 |
d570a8 |
const char **name,
|
|
 |
d570a8 |
flagword *flags ATTRIBUTE_UNUSED,
|
|
 |
d570a8 |
asection **sec,
|
|
 |
d570a8 |
- bfd_vma *value ATTRIBUTE_UNUSED)
|
|
 |
d570a8 |
+ bfd_vma *value)
|
|
 |
d570a8 |
{
|
|
 |
d570a8 |
if ((ibfd->flags & DYNAMIC) == 0
|
|
 |
d570a8 |
&& ELF_ST_BIND (isym->st_info) == STB_GNU_UNIQUE)
|
|
 |
d570a8 |
elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
|
|
 |
d570a8 |
|
|
 |
d570a8 |
- if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
|
|
 |
d570a8 |
+ if ((ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
|
|
 |
d570a8 |
+ && ((ibfd->flags & DYNAMIC) == 0))
|
|
 |
d570a8 |
+ elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
|
|
 |
d570a8 |
+
|
|
 |
d570a8 |
+ if (*sec != NULL
|
|
 |
d570a8 |
+ && strcmp ((*sec)->name, ".opd") == 0)
|
|
 |
d570a8 |
{
|
|
 |
d570a8 |
- if ((ibfd->flags & DYNAMIC) == 0)
|
|
 |
d570a8 |
- elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
|
|
 |
d570a8 |
+ asection *code_sec;
|
|
 |
d570a8 |
+
|
|
 |
d570a8 |
+ if (!(ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC
|
|
 |
d570a8 |
+ || ELF_ST_TYPE (isym->st_info) == STT_FUNC))
|
|
 |
d570a8 |
+ isym->st_info = ELF_ST_INFO (ELF_ST_BIND (isym->st_info), STT_FUNC);
|
|
 |
d570a8 |
+
|
|
 |
d570a8 |
+ /* If the symbol is a function defined in .opd, and the function
|
|
 |
d570a8 |
+ code is in a discarded group, let it appear to be undefined. */
|
|
 |
d570a8 |
+ if (!info->relocatable
|
|
 |
d570a8 |
+ && (*sec)->reloc_count != 0
|
|
 |
d570a8 |
+ && opd_entry_value (*sec, *value, &code_sec, NULL,
|
|
 |
d570a8 |
+ FALSE) != (bfd_vma) -1
|
|
 |
d570a8 |
+ && discarded_section (code_sec))
|
|
 |
d570a8 |
+ {
|
|
 |
d570a8 |
+ *sec = bfd_und_section_ptr;
|
|
 |
d570a8 |
+ isym->st_shndx = SHN_UNDEF;
|
|
 |
d570a8 |
+ }
|
|
 |
d570a8 |
}
|
|
 |
d570a8 |
- else if (ELF_ST_TYPE (isym->st_info) == STT_FUNC)
|
|
 |
d570a8 |
- ;
|
|
 |
d570a8 |
- else if (*sec != NULL
|
|
 |
d570a8 |
- && strcmp ((*sec)->name, ".opd") == 0)
|
|
 |
d570a8 |
- isym->st_info = ELF_ST_INFO (ELF_ST_BIND (isym->st_info), STT_FUNC);
|
|
 |
d570a8 |
|
|
 |
d570a8 |
if ((STO_PPC64_LOCAL_MASK & isym->st_other) != 0)
|
|
 |
d570a8 |
{
|
|
 |
d570a8 |
@@ -5855,7 +5870,8 @@
|
|
 |
d570a8 |
}
|
|
 |
d570a8 |
|
|
 |
d570a8 |
/* OFFSET in OPD_SEC specifies a function descriptor. Return the address
|
|
 |
d570a8 |
- of the code entry point, and its section. */
|
|
 |
d570a8 |
+ of the code entry point, and its section, which must be in the same
|
|
 |
d570a8 |
+ object as OPD_SEC. Returns (bfd_vma) -1 on error. */
|
|
 |
d570a8 |
|
|
 |
d570a8 |
static bfd_vma
|
|
 |
d570a8 |
opd_entry_value (asection *opd_sec,
|
|
 |
d570a8 |
@@ -5938,32 +5954,10 @@
|
|
 |
d570a8 |
&& ELF64_R_TYPE ((look + 1)->r_info) == R_PPC64_TOC)
|
|
 |
d570a8 |
{
|
|
 |
d570a8 |
unsigned long symndx = ELF64_R_SYM (look->r_info);
|
|
 |
d570a8 |
- asection *sec;
|
|
 |
d570a8 |
+ asection *sec = NULL;
|
|
 |
d570a8 |
|
|
 |
d570a8 |
- if (symndx < symtab_hdr->sh_info
|
|
 |
d570a8 |
- || elf_sym_hashes (opd_bfd) == NULL)
|
|
 |
d570a8 |
- {
|
|
 |
d570a8 |
- Elf_Internal_Sym *sym;
|
|
 |
d570a8 |
-
|
|
 |
d570a8 |
- sym = (Elf_Internal_Sym *) symtab_hdr->contents;
|
|
 |
d570a8 |
- if (sym == NULL)
|
|
 |
d570a8 |
- {
|
|
 |
d570a8 |
- size_t symcnt = symtab_hdr->sh_info;
|
|
 |
d570a8 |
- if (elf_sym_hashes (opd_bfd) == NULL)
|
|
 |
d570a8 |
- symcnt = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
|
|
 |
d570a8 |
- sym = bfd_elf_get_elf_syms (opd_bfd, symtab_hdr, symcnt,
|
|
 |
d570a8 |
- 0, NULL, NULL, NULL);
|
|
 |
d570a8 |
- if (sym == NULL)
|
|
 |
d570a8 |
- break;
|
|
 |
d570a8 |
- symtab_hdr->contents = (bfd_byte *) sym;
|
|
 |
d570a8 |
- }
|
|
 |
d570a8 |
-
|
|
 |
d570a8 |
- sym += symndx;
|
|
 |
d570a8 |
- val = sym->st_value;
|
|
 |
d570a8 |
- sec = bfd_section_from_elf_index (opd_bfd, sym->st_shndx);
|
|
 |
d570a8 |
- BFD_ASSERT ((sec->flags & SEC_MERGE) == 0);
|
|
 |
d570a8 |
- }
|
|
 |
d570a8 |
- else
|
|
 |
d570a8 |
+ if (symndx >= symtab_hdr->sh_info
|
|
 |
d570a8 |
+ && elf_sym_hashes (opd_bfd) != NULL)
|
|
 |
d570a8 |
{
|
|
 |
d570a8 |
struct elf_link_hash_entry **sym_hashes;
|
|
 |
d570a8 |
struct elf_link_hash_entry *rh;
|
|
 |
d570a8 |
@@ -5977,24 +5971,48 @@
|
|
 |
d570a8 |
|| rh->root.type == bfd_link_hash_defweak);
|
|
 |
d570a8 |
val = rh->root.u.def.value;
|
|
 |
d570a8 |
sec = rh->root.u.def.section;
|
|
 |
d570a8 |
+ if (sec->owner != opd_bfd)
|
|
 |
d570a8 |
+ {
|
|
 |
d570a8 |
+ sec = NULL;
|
|
 |
d570a8 |
+ val = (bfd_vma) -1;
|
|
 |
d570a8 |
+ }
|
|
 |
d570a8 |
+ }
|
|
 |
d570a8 |
+ }
|
|
 |
d570a8 |
+
|
|
 |
d570a8 |
+ if (sec == NULL)
|
|
 |
d570a8 |
+ {
|
|
 |
d570a8 |
+ Elf_Internal_Sym *sym;
|
|
 |
d570a8 |
+
|
|
 |
d570a8 |
+ if (symndx < symtab_hdr->sh_info)
|
|
 |
d570a8 |
+ {
|
|
 |
d570a8 |
+ sym = (Elf_Internal_Sym *) symtab_hdr->contents;
|
|
 |
d570a8 |
+ if (sym == NULL)
|
|
 |
d570a8 |
+ {
|
|
 |
d570a8 |
+ size_t symcnt = symtab_hdr->sh_info;
|
|
 |
d570a8 |
+ sym = bfd_elf_get_elf_syms (opd_bfd, symtab_hdr,
|
|
 |
d570a8 |
+ symcnt, 0,
|
|
 |
d570a8 |
+ NULL, NULL, NULL);
|
|
 |
d570a8 |
+ if (sym == NULL)
|
|
 |
d570a8 |
+ break;
|
|
 |
d570a8 |
+ symtab_hdr->contents = (bfd_byte *) sym;
|
|
 |
d570a8 |
+ }
|
|
 |
d570a8 |
+ sym += symndx;
|
|
 |
d570a8 |
}
|
|
 |
d570a8 |
else
|
|
 |
d570a8 |
{
|
|
 |
d570a8 |
- /* Handle the odd case where we can be called
|
|
 |
d570a8 |
- during bfd_elf_link_add_symbols before the
|
|
 |
d570a8 |
- symbol hashes have been fully populated. */
|
|
 |
d570a8 |
- Elf_Internal_Sym *sym;
|
|
 |
d570a8 |
-
|
|
 |
d570a8 |
- sym = bfd_elf_get_elf_syms (opd_bfd, symtab_hdr, 1,
|
|
 |
d570a8 |
- symndx, NULL, NULL, NULL);
|
|
 |
d570a8 |
+ sym = bfd_elf_get_elf_syms (opd_bfd, symtab_hdr,
|
|
 |
d570a8 |
+ 1, symndx,
|
|
 |
d570a8 |
+ NULL, NULL, NULL);
|
|
 |
d570a8 |
if (sym == NULL)
|
|
 |
d570a8 |
break;
|
|
 |
d570a8 |
-
|
|
 |
d570a8 |
- val = sym->st_value;
|
|
 |
d570a8 |
- sec = bfd_section_from_elf_index (opd_bfd, sym->st_shndx);
|
|
 |
d570a8 |
- free (sym);
|
|
 |
d570a8 |
}
|
|
 |
d570a8 |
+ sec = bfd_section_from_elf_index (opd_bfd, sym->st_shndx);
|
|
 |
d570a8 |
+ if (sec == NULL)
|
|
 |
d570a8 |
+ break;
|
|
 |
d570a8 |
+ BFD_ASSERT ((sec->flags & SEC_MERGE) == 0);
|
|
 |
d570a8 |
+ val = sym->st_value;
|
|
 |
d570a8 |
}
|
|
 |
d570a8 |
+
|
|
 |
d570a8 |
val += look->r_addend;
|
|
 |
d570a8 |
if (code_off != NULL)
|
|
 |
d570a8 |
*code_off = val;
|
|
 |
d570a8 |
@@ -6005,7 +6023,7 @@
|
|
 |
d570a8 |
else
|
|
 |
d570a8 |
*code_sec = sec;
|
|
 |
d570a8 |
}
|
|
 |
d570a8 |
- if (sec != NULL && sec->output_section != NULL)
|
|
 |
d570a8 |
+ if (sec->output_section != NULL)
|
|
 |
d570a8 |
val += sec->output_section->vma + sec->output_offset;
|
|
 |
d570a8 |
}
|
|
 |
d570a8 |
break;
|