From 7382d32a7585355b62f6628439c405fb589f9c13 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 2 Jul 2008 13:31:53 +0000 Subject: [PATCH] * elf32-ppc.c (is_pic_glink_stub): New function. (ppc_elf_get_synthetic_symtab): Don't generate symbols when multiple shared/pie stubs per plt entry. --- bfd/ChangeLog | 6 ++++++ bfd/elf32-ppc.c | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index fc4ac1f2258..abadb37dd82 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2008-07-02 Alan Modra + + * elf32-ppc.c (is_pic_glink_stub): New function. + (ppc_elf_get_synthetic_symtab): Don't generate symbols when + multiple shared/pie stubs per plt entry. + 2008-06-30 Richard Sandiford * elf.c (_bfd_elf_get_synthetic_symtab): Increment p by diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c index 0ad11757909..92f812fda30 100644 --- a/bfd/elf32-ppc.c +++ b/bfd/elf32-ppc.c @@ -2291,6 +2291,29 @@ ppc_elf_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED) apuinfo_list_finish (); } +static bfd_boolean +is_pic_glink_stub (bfd *abfd, asection *glink, bfd_vma off) +{ + bfd_byte buf[16]; + unsigned int insn; + + if (!bfd_get_section_contents (abfd, glink, buf, off, 16)) + return FALSE; + + insn = bfd_get_32 (abfd, buf); + if ((insn & 0xffff0000) == LWZ_11_30 + && bfd_get_32 (abfd, buf + 4) == MTCTR_11 + && bfd_get_32 (abfd, buf + 8) == BCTR) + return TRUE; + + if ((insn & 0xffff0000) == ADDIS_11_30 + && (bfd_get_32 (abfd, buf + 4) & 0xffff0000) == LWZ_11_11 + && bfd_get_32 (abfd, buf + 8) == MTCTR_11 + && bfd_get_32 (abfd, buf + 12) == BCTR) + return TRUE; + return FALSE; +} + static bfd_boolean section_covers_vma (bfd *abfd ATTRIBUTE_UNUSED, asection *section, void *ptr) { @@ -2419,12 +2442,22 @@ ppc_elf_get_synthetic_symtab (bfd *abfd, long symcount, asymbol **syms, } } + count = relplt->size / sizeof (Elf32_External_Rela); + stub_vma = glink_vma - (bfd_vma) count * 16; + /* If the stubs are those for -shared/-pie then we might have + multiple stubs for each plt entry. If that is the case then + there is no way to associate stubs with their plt entries short + of figuring out the GOT pointer value used in the stub. */ + if (!bfd_get_section_contents (abfd, glink, buf, + stub_vma - glink->vma, 4) + || ((bfd_get_32 (abfd, buf) & 0xffff0000) != LIS_11 + && is_pic_glink_stub (abfd, glink, stub_vma - glink->vma - 16))) + return 0; + slurp_relocs = get_elf_backend_data (abfd)->s->slurp_reloc_table; if (! (*slurp_relocs) (abfd, relplt, dynsyms, TRUE)) return -1; - count = relplt->size / sizeof (Elf32_External_Rela); - stub_vma = glink_vma - (bfd_vma) count * 16; size = count * sizeof (asymbol); p = relplt->relocation; for (i = 0; i < count; i++, p++) -- 2.30.2