PR25384, PowerPC64 ELFv1 copy relocs against function symbols

Function symbols of course don't normally want .dynbss copies but
with some old versions of gcc they are needed to copy the function
descriptor.  This patch restricts the cases where they are useful to
compilers using dot-symbols, and enables the warning regardless of
whether a PLT entry is emitted in the executable.  PLTs in shared
libraries are affected by a .dynbss copy in the executable.

bfd/
	PR 25384
	* elf64-ppc.c (ELIMINATE_COPY_RELOCS): Update comment.
	(ppc64_elf_adjust_dynamic_symbol): Don't allow .dynbss copies
	of function symbols unless dot symbols are present.  Do warn
	whenever one is created, regardles of whether a PLT entry is
	also emitted for the function symbol.
ld/
	* testsuite/ld-powerpc/ambiguousv1b.d: Adjust expected output.
	* testsuite/ld-powerpc/funref.s: Align func_tab.
	* testsuite/ld-powerpc/funref2.s: Likewise.
	* testsuite/ld-powerpc/funv1.s: Add dot symbols.
This commit is contained in:
Alan Modra 2020-01-14 20:45:53 +10:30
parent ff47f4f06d
commit e1c6cf618c
7 changed files with 58 additions and 27 deletions

View File

@ -1,3 +1,12 @@
2020-01-15 Alan Modra <amodra@gmail.com>
PR 25384
* elf64-ppc.c (ELIMINATE_COPY_RELOCS): Update comment.
(ppc64_elf_adjust_dynamic_symbol): Don't allow .dynbss copies
of function symbols unless dot symbols are present. Do warn
whenever one is created, regardles of whether a PLT entry is
also emitted for the function symbol.
2020-01-14 Alan Modra <amodra@gmail.com> 2020-01-14 Alan Modra <amodra@gmail.com>
* som.c (som_bfd_count_ar_symbols): Error when file position * som.c (som_bfd_count_ar_symbols): Error when file position

View File

@ -2788,20 +2788,20 @@ must_be_dyn_reloc (struct bfd_link_info *info,
} }
/* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid /* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid
copying dynamic variables from a shared lib into an app's dynbss copying dynamic variables from a shared lib into an app's .dynbss
section, and instead use a dynamic relocation to point into the section, and instead use a dynamic relocation to point into the
shared lib. With code that gcc generates, it's vital that this be shared lib. With code that gcc generates it is vital that this be
enabled; In the PowerPC64 ABI, the address of a function is actually enabled; In the PowerPC64 ELFv1 ABI the address of a function is
the address of a function descriptor, which resides in the .opd actually the address of a function descriptor which resides in the
section. gcc uses the descriptor directly rather than going via the .opd section. gcc uses the descriptor directly rather than going
GOT as some other ABI's do, which means that initialized function via the GOT as some other ABIs do, which means that initialized
pointers must reference the descriptor. Thus, a function pointer function pointers reference the descriptor. Thus, a function
initialized to the address of a function in a shared library will pointer initialized to the address of a function in a shared
either require a copy reloc, or a dynamic reloc. Using a copy reloc library will either require a .dynbss copy and a copy reloc, or a
redefines the function descriptor symbol to point to the copy. This dynamic reloc. Using a .dynbss copy redefines the function
presents a problem as a plt entry for that function is also descriptor symbol to point to the copy. This presents a problem as
initialized from the function descriptor symbol and the copy reloc a PLT entry for that function is also initialized from the function
may not be initialized first. */ descriptor symbol and the copy may not be initialized first. */
#define ELIMINATE_COPY_RELOCS 1 #define ELIMINATE_COPY_RELOCS 1
/* Section name for stubs is the associated section name plus this /* Section name for stubs is the associated section name plus this
@ -6462,13 +6462,23 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
|| h->protected_def) || h->protected_def)
return TRUE; return TRUE;
if (h->plt.plist != NULL) if (h->type == STT_FUNC
|| h->type == STT_GNU_IFUNC)
{ {
/* We should never get here, but unfortunately there are versions /* .dynbss copies of function symbols only work if we have
of gcc out there that improperly (for this ABI) put initialized ELFv1 dot-symbols. ELFv1 compilers since 2004 default to not
function pointers, vtable refs and suchlike in read-only use dot-symbols and set the function symbol size to the text
sections. Allow them to proceed, but warn that this might size of the function rather than the size of the descriptor.
break at runtime. */ That's wrong for copying a descriptor. */
if (((struct ppc_link_hash_entry *) h)->oh == NULL
|| !(h->size == 24 || h->size == 16))
return TRUE;
/* We should never get here, but unfortunately there are old
versions of gcc (circa gcc-3.2) that improperly for the
ELFv1 ABI put initialized function pointers, vtable refs and
suchlike in read-only sections. Allow them to proceed, but
warn that this might break at runtime. */
info->callbacks->einfo info->callbacks->einfo
(_("%P: copy reloc against `%pT' requires lazy plt linking; " (_("%P: copy reloc against `%pT' requires lazy plt linking; "
"avoid setting LD_BIND_NOW=1 or upgrade gcc\n"), "avoid setting LD_BIND_NOW=1 or upgrade gcc\n"),

View File

@ -1,3 +1,10 @@
2020-01-15 Alan Modra <amodra@gmail.com>
* testsuite/ld-powerpc/ambiguousv1b.d: Adjust expected output.
* testsuite/ld-powerpc/funref.s: Align func_tab.
* testsuite/ld-powerpc/funref2.s: Likewise.
* testsuite/ld-powerpc/funv1.s: Add dot symbols.
2020-01-14 Lili Cui <lili.cui@intel.com> 2020-01-14 Lili Cui <lili.cui@intel.com>
* testsuite/ld-i386/align-branch-1.d: Updated for i686-pc-elf. * testsuite/ld-i386/align-branch-1.d: Updated for i686-pc-elf.

View File

@ -3,6 +3,7 @@
#as: -a64 #as: -a64
#ld: -melf64ppc --emit-stub-syms #ld: -melf64ppc --emit-stub-syms
#ld_after_inputfiles: tmpdir/funv1.so #ld_after_inputfiles: tmpdir/funv1.so
#warning: .*requires lazy plt linking.*
#readelf: -rs --wide #readelf: -rs --wide
# Check that we do the right thing with funref2.s that doesn't have # Check that we do the right thing with funref2.s that doesn't have
# anything to mark it as ELFv1 or ELFv2. Since my_func address is # anything to mark it as ELFv1 or ELFv2. Since my_func address is
@ -15,9 +16,9 @@ Relocation section .* contains 1 entry:
Symbol table '\.dynsym' contains 2 entries: Symbol table '\.dynsym' contains 2 entries:
#... #...
.*: 0*[1-9a-f][0-9a-f]* 4 FUNC GLOBAL DEFAULT 1[23] my_func .*: 0*[1-9a-f][0-9a-f]* +24 FUNC +GLOBAL DEFAULT +1[23] my_func
#... #...
Symbol table '\.symtab' contains .* entries: Symbol table '\.symtab' contains .* entries:
#... #...
.*: 0*[1-9a-f][0-9a-f]* 4 FUNC GLOBAL DEFAULT 1[23] my_func .*: 0*[1-9a-f][0-9a-f]* +24 FUNC +GLOBAL DEFAULT +1[23] my_func
#pass #pass

View File

@ -1,4 +1,5 @@
.data .data
.globl func_tab .globl func_tab
.p2align 3
func_tab: func_tab:
.dc.a my_func .dc.a my_func

View File

@ -1,4 +1,5 @@
.section .rodata,"a",@progbits .section .rodata,"a",@progbits
.globl func_tab .globl func_tab
.p2align 3
func_tab: func_tab:
.dc.a my_func .dc.a my_func

View File

@ -1,10 +1,12 @@
.globl my_func # old style ELFv1, with dot-symbols
.type my_func,@function .globl my_func, .my_func
.section .opd,"aw",@progbits .type .my_func, @function
.section .opd, "aw", @progbits
my_func: my_func:
.quad .Lmy_func, .TOC.@tocbase .quad .my_func, .TOC.@tocbase, 0
.size my_func, . - my_func
.text .text
.Lmy_func: .my_func:
blr blr
.size my_func,.-.Lmy_func .size .my_func, . - .my_func