PR25384, PowerPC64 ELFv1 copy relocs against function symbols

Carlos O'Donell carlos@redhat.com
Wed Jan 15 13:18:00 GMT 2020


On Tue, Jan 14, 2020 at 9:49 PM Alan Modra <amodra@gmail.com> wrote:
>
> 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.

Thanks for expanding the fix for this.

This patch is certainly an improvement over what we have today.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>

> 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.
>
> diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
> index a451c4753a..8319a21940 100644
> --- a/bfd/elf64-ppc.c
> +++ b/bfd/elf64-ppc.c
> @@ -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
> -   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
> -   shared lib.  With code that gcc generates, it's vital that this be
> -   enabled;  In the PowerPC64 ABI, the address of a function is actually
> -   the address of a function descriptor, which resides in the .opd
> -   section.  gcc uses the descriptor directly rather than going via the
> -   GOT as some other ABI's do, which means that initialized function
> -   pointers must reference the descriptor.  Thus, a function pointer
> -   initialized to the address of a function in a shared library will
> -   either require a copy reloc, or a dynamic reloc.  Using a copy reloc
> -   redefines the function descriptor symbol to point to the copy.  This
> -   presents a problem as a plt entry for that function is also
> -   initialized from the function descriptor symbol and the copy reloc
> -   may not be initialized first.  */
> +   shared lib.  With code that gcc generates it is vital that this be
> +   enabled;  In the PowerPC64 ELFv1 ABI the address of a function is
> +   actually the address of a function descriptor which resides in the
> +   .opd section.  gcc uses the descriptor directly rather than going
> +   via the GOT as some other ABIs do, which means that initialized
> +   function pointers reference the descriptor.  Thus, a function
> +   pointer initialized to the address of a function in a shared
> +   library will either require a .dynbss copy and a copy reloc, or a
> +   dynamic reloc.  Using a .dynbss copy redefines the function
> +   descriptor symbol to point to the copy.  This presents a problem as
> +   a PLT entry for that function is also initialized from the function
> +   descriptor symbol and the copy may not be initialized first.  */

OK. I like this new text and it's much clearer than what we had before.

>  #define ELIMINATE_COPY_RELOCS 1
>
>  /* 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)
>      return TRUE;
>
> -  if (h->plt.plist != NULL)
> +  if (h->type == STT_FUNC
> +      || h->type == STT_GNU_IFUNC)

OK. You expand the scope of what is being handled (regardless of a PLT
entry being created).

>      {
> -      /* We should never get here, but unfortunately there are versions
> -        of gcc out there that improperly (for this 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.  */
> +      /* .dynbss copies of function symbols only work if we have
> +        ELFv1 dot-symbols.  ELFv1 compilers since 2004 default to not
> +        use dot-symbols and set the function symbol size to the text
> +        size of the function rather than the size of the descriptor.
> +        That's wrong for copying a descriptor.  */
> +      if (((struct ppc_link_hash_entry *) h)->oh == NULL
> +         || !(h->size == 24 || h->size == 16))
> +       return TRUE;

OK. Though I wonder if we can't have a text size that's 24-bytes ;-)

> +
> +      /* 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
>         (_("%P: copy reloc against `%pT' requires lazy plt linking; "
>            "avoid setting LD_BIND_NOW=1 or upgrade gcc\n"),
> diff --git a/ld/testsuite/ld-powerpc/ambiguousv1b.d b/ld/testsuite/ld-powerpc/ambiguousv1b.d
> index 9be1371e5e..205f7ea46f 100644
> --- a/ld/testsuite/ld-powerpc/ambiguousv1b.d
> +++ b/ld/testsuite/ld-powerpc/ambiguousv1b.d
> @@ -3,6 +3,7 @@
>  #as: -a64
>  #ld: -melf64ppc --emit-stub-syms
>  #ld_after_inputfiles: tmpdir/funv1.so
> +#warning: .*requires lazy plt linking.*

OK.

>  #readelf: -rs --wide
>  # 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
> @@ -15,9 +16,9 @@ Relocation section .* contains 1 entry:
>
>  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

OK.

>  #...
>  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

OK.

>  #pass
> diff --git a/ld/testsuite/ld-powerpc/funref.s b/ld/testsuite/ld-powerpc/funref.s
> index 3f7de479ce..27c1bcf6b1 100644
> --- a/ld/testsuite/ld-powerpc/funref.s
> +++ b/ld/testsuite/ld-powerpc/funref.s
> @@ -1,4 +1,5 @@
>   .data
>   .globl func_tab
> + .p2align 3

OK.

>  func_tab:
>   .dc.a my_func
> diff --git a/ld/testsuite/ld-powerpc/funref2.s b/ld/testsuite/ld-powerpc/funref2.s
> index a2bf949126..14c58f0123 100644
> --- a/ld/testsuite/ld-powerpc/funref2.s
> +++ b/ld/testsuite/ld-powerpc/funref2.s
> @@ -1,4 +1,5 @@
>   .section .rodata,"a",@progbits
>   .globl func_tab
> + .p2align 3

OK.

>  func_tab:
>   .dc.a my_func
> diff --git a/ld/testsuite/ld-powerpc/funv1.s b/ld/testsuite/ld-powerpc/funv1.s
> index e79009d1d2..988ad0d8c1 100644
> --- a/ld/testsuite/ld-powerpc/funv1.s
> +++ b/ld/testsuite/ld-powerpc/funv1.s
> @@ -1,10 +1,12 @@
> - .globl my_func
> - .type my_func,@function
> - .section .opd,"aw",@progbits
> +# old style ELFv1, with dot-symbols

OK.

> + .globl my_func, .my_func
> + .type .my_func, @function
> + .section .opd, "aw", @progbits
>  my_func:
> - .quad .Lmy_func, .TOC.@tocbase
> + .quad .my_func, .TOC.@tocbase, 0
> + .size my_func, . - my_func
>
>   .text
> -.Lmy_func:
> +.my_func:
>   blr
> - .size my_func,.-.Lmy_func
> + .size .my_func, . - .my_func
>
> --
> Alan Modra
> Australia Development Lab, IBM
>



More information about the Binutils mailing list