From 5ca5bb354599855357bd35d99dfa07a729f91095 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Thu, 13 Dec 2012 21:07:16 +0000 Subject: Check local IFUNC calls bfd/ 2012-12-13 H.J. Lu PR ld/14956 * elf32-i386.c (elf_i386_adjust_dynamic_symbol): Check local IFUNC calls. * elf64-x86-64.c (elf_x86_64_adjust_dynamic_symbol): Likewise. ld/testsuite/ 2012-12-13 H.J. Lu PR ld/14956 * ld-ifunc/ifunc-14-i386.d: Renamed to ... * ld-ifunc/ifunc-14a-i386.d: This. * ld-ifunc/ifunc-14-x86-64.d: Renamed to ... * ld-ifunc/ifunc-14a-x86-64.d: This. * ld-ifunc/ifunc-14b-i386.d: New file. * ld-ifunc/ifunc-14b-x86-64.d: Likewise. * ld-ifunc/ifunc-14c-i386.d: Likewise. * ld-ifunc/ifunc-14c-x86-64.d: Likewise. * ld-ifunc/ifunc-14d-i386.d: Likewise. * ld-ifunc/ifunc-14d-x86-64.d: Likewise. --- bfd/ChangeLog | 7 +++++++ bfd/elf32-i386.c | 32 +++++++++++++++++++++++++++++--- bfd/elf64-x86-64.c | 32 +++++++++++++++++++++++++++++--- ld/testsuite/ChangeLog | 16 ++++++++++++++++ ld/testsuite/ld-ifunc/ifunc-14-i386.d | 11 ----------- ld/testsuite/ld-ifunc/ifunc-14-x86-64.d | 11 ----------- ld/testsuite/ld-ifunc/ifunc-14a-i386.d | 11 +++++++++++ ld/testsuite/ld-ifunc/ifunc-14a-x86-64.d | 11 +++++++++++ ld/testsuite/ld-ifunc/ifunc-14b-i386.d | 11 +++++++++++ ld/testsuite/ld-ifunc/ifunc-14b-x86-64.d | 11 +++++++++++ ld/testsuite/ld-ifunc/ifunc-14c-i386.d | 11 +++++++++++ ld/testsuite/ld-ifunc/ifunc-14c-x86-64.d | 11 +++++++++++ ld/testsuite/ld-ifunc/ifunc-14d-i386.d | 11 +++++++++++ ld/testsuite/ld-ifunc/ifunc-14d-x86-64.d | 11 +++++++++++ 14 files changed, 169 insertions(+), 28 deletions(-) delete mode 100644 ld/testsuite/ld-ifunc/ifunc-14-i386.d delete mode 100644 ld/testsuite/ld-ifunc/ifunc-14-x86-64.d create mode 100644 ld/testsuite/ld-ifunc/ifunc-14a-i386.d create mode 100644 ld/testsuite/ld-ifunc/ifunc-14a-x86-64.d create mode 100644 ld/testsuite/ld-ifunc/ifunc-14b-i386.d create mode 100644 ld/testsuite/ld-ifunc/ifunc-14b-x86-64.d create mode 100644 ld/testsuite/ld-ifunc/ifunc-14c-i386.d create mode 100644 ld/testsuite/ld-ifunc/ifunc-14c-x86-64.d create mode 100644 ld/testsuite/ld-ifunc/ifunc-14d-i386.d create mode 100644 ld/testsuite/ld-ifunc/ifunc-14d-x86-64.d diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 5c4ace1..1ff8574 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2012-12-13 H.J. Lu + + PR ld/14956 + * elf32-i386.c (elf_i386_adjust_dynamic_symbol): Check local + IFUNC calls. + * elf64-x86-64.c (elf_x86_64_adjust_dynamic_symbol): Likewise. + 2012-12-10 Edgar E. Iglesias * reloc.c (MICROBLAZE): Document new relocations diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 1b04a6e..bb41302 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -2066,10 +2066,39 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, { struct elf_i386_link_hash_table *htab; asection *s; + struct elf_i386_link_hash_entry *eh; + struct elf_dyn_relocs *p; /* STT_GNU_IFUNC symbol must go through PLT. */ if (h->type == STT_GNU_IFUNC) { + /* Check local STT_GNU_IFUNC calls. */ + if (h->ref_regular + && SYMBOL_CALLS_LOCAL (info, h)) + { + bfd_size_type pc_count = 0; + struct elf_dyn_relocs **pp; + + eh = (struct elf_i386_link_hash_entry *) h; + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + { + pc_count += p->pc_count; + p->count -= p->pc_count; + p->pc_count = 0; + if (p->count == 0) + *pp = p->next; + else + pp = &p->next; + } + + if (pc_count) + { + h->needs_plt = 1; + h->plt.refcount += 1; + h->non_got_ref = 1; + } + } + if (h->plt.refcount <= 0) { h->plt.offset = (bfd_vma) -1; @@ -2155,9 +2184,6 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, if (ELIMINATE_COPY_RELOCS && !get_elf_i386_backend_data (info->output_bfd)->is_vxworks) { - struct elf_i386_link_hash_entry * eh; - struct elf_dyn_relocs *p; - eh = (struct elf_i386_link_hash_entry *) h; for (p = eh->dyn_relocs; p != NULL; p = p->next) { diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index d58384f..ec38ddc 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -2134,10 +2134,39 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info, { struct elf_x86_64_link_hash_table *htab; asection *s; + struct elf_x86_64_link_hash_entry *eh; + struct elf_dyn_relocs *p; /* STT_GNU_IFUNC symbol must go through PLT. */ if (h->type == STT_GNU_IFUNC) { + /* Check local STT_GNU_IFUNC calls. */ + if (h->ref_regular + && SYMBOL_CALLS_LOCAL (info, h)) + { + bfd_size_type pc_count = 0; + struct elf_dyn_relocs **pp; + + eh = (struct elf_x86_64_link_hash_entry *) h; + for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) + { + pc_count += p->pc_count; + p->count -= p->pc_count; + p->pc_count = 0; + if (p->count == 0) + *pp = p->next; + else + pp = &p->next; + } + + if (pc_count) + { + h->needs_plt = 1; + h->plt.refcount += 1; + h->non_got_ref = 1; + } + } + if (h->plt.refcount <= 0) { h->plt.offset = (bfd_vma) -1; @@ -2214,9 +2243,6 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info, if (ELIMINATE_COPY_RELOCS) { - struct elf_x86_64_link_hash_entry * eh; - struct elf_dyn_relocs *p; - eh = (struct elf_x86_64_link_hash_entry *) h; for (p = eh->dyn_relocs; p != NULL; p = p->next) { diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index b534021..994ee04 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,19 @@ +2012-12-13 H.J. Lu + + PR ld/14956 + * ld-ifunc/ifunc-14-i386.d: Renamed to ... + * ld-ifunc/ifunc-14a-i386.d: This. + + * ld-ifunc/ifunc-14-x86-64.d: Renamed to ... + * ld-ifunc/ifunc-14a-x86-64.d: This. + + * ld-ifunc/ifunc-14b-i386.d: New file. + * ld-ifunc/ifunc-14b-x86-64.d: Likewise. + * ld-ifunc/ifunc-14c-i386.d: Likewise. + * ld-ifunc/ifunc-14c-x86-64.d: Likewise. + * ld-ifunc/ifunc-14d-i386.d: Likewise. + * ld-ifunc/ifunc-14d-x86-64.d: Likewise. + 2012-12-07 H.J. Lu * ld-elf/pr14926.d: Use "readelf -S --wide". diff --git a/ld/testsuite/ld-ifunc/ifunc-14-i386.d b/ld/testsuite/ld-ifunc/ifunc-14-i386.d deleted file mode 100644 index 0edc9fb..0000000 --- a/ld/testsuite/ld-ifunc/ifunc-14-i386.d +++ /dev/null @@ -1,11 +0,0 @@ -#source: ifunc-14a.s -#source: ifunc-14b.s -#ld: -shared -m elf_i386 -z nocombreloc -#as: --32 -#readelf: -d --wide -#target: x86_64-*-* i?86-*-* - -#failif -#... -.*\(TEXTREL\).* -#... diff --git a/ld/testsuite/ld-ifunc/ifunc-14-x86-64.d b/ld/testsuite/ld-ifunc/ifunc-14-x86-64.d deleted file mode 100644 index 2c4ebbb..0000000 --- a/ld/testsuite/ld-ifunc/ifunc-14-x86-64.d +++ /dev/null @@ -1,11 +0,0 @@ -#source: ifunc-14a.s -#source: ifunc-14b.s -#ld: -shared -m elf_x86_64 -z nocombreloc -#as: --64 -#readelf: -d -#target: x86_64-*-* - -#failif -#... -.*\(TEXTREL\).* -#... diff --git a/ld/testsuite/ld-ifunc/ifunc-14a-i386.d b/ld/testsuite/ld-ifunc/ifunc-14a-i386.d new file mode 100644 index 0000000..0edc9fb --- /dev/null +++ b/ld/testsuite/ld-ifunc/ifunc-14a-i386.d @@ -0,0 +1,11 @@ +#source: ifunc-14a.s +#source: ifunc-14b.s +#ld: -shared -m elf_i386 -z nocombreloc +#as: --32 +#readelf: -d --wide +#target: x86_64-*-* i?86-*-* + +#failif +#... +.*\(TEXTREL\).* +#... diff --git a/ld/testsuite/ld-ifunc/ifunc-14a-x86-64.d b/ld/testsuite/ld-ifunc/ifunc-14a-x86-64.d new file mode 100644 index 0000000..2c4ebbb --- /dev/null +++ b/ld/testsuite/ld-ifunc/ifunc-14a-x86-64.d @@ -0,0 +1,11 @@ +#source: ifunc-14a.s +#source: ifunc-14b.s +#ld: -shared -m elf_x86_64 -z nocombreloc +#as: --64 +#readelf: -d +#target: x86_64-*-* + +#failif +#... +.*\(TEXTREL\).* +#... diff --git a/ld/testsuite/ld-ifunc/ifunc-14b-i386.d b/ld/testsuite/ld-ifunc/ifunc-14b-i386.d new file mode 100644 index 0000000..948237d --- /dev/null +++ b/ld/testsuite/ld-ifunc/ifunc-14b-i386.d @@ -0,0 +1,11 @@ +#source: ifunc-14b.s +#source: ifunc-14a.s +#ld: -shared -m elf_i386 -z nocombreloc +#as: --32 +#readelf: -d --wide +#target: x86_64-*-* i?86-*-* + +#failif +#... +.*\(TEXTREL\).* +#... diff --git a/ld/testsuite/ld-ifunc/ifunc-14b-x86-64.d b/ld/testsuite/ld-ifunc/ifunc-14b-x86-64.d new file mode 100644 index 0000000..cc1f5ae --- /dev/null +++ b/ld/testsuite/ld-ifunc/ifunc-14b-x86-64.d @@ -0,0 +1,11 @@ +#source: ifunc-14b.s +#source: ifunc-14a.s +#ld: -shared -m elf_x86_64 -z nocombreloc +#as: --64 +#readelf: -d +#target: x86_64-*-* + +#failif +#... +.*\(TEXTREL\).* +#... diff --git a/ld/testsuite/ld-ifunc/ifunc-14c-i386.d b/ld/testsuite/ld-ifunc/ifunc-14c-i386.d new file mode 100644 index 0000000..ca360a3 --- /dev/null +++ b/ld/testsuite/ld-ifunc/ifunc-14c-i386.d @@ -0,0 +1,11 @@ +#source: ifunc-14a.s +#source: ifunc-14b.s +#ld: -shared -m elf_i386 -z nocombreloc +#as: --32 +#readelf: -r --wide +#target: x86_64-*-* i?86-*-* + +#failif +#... +.* +R_386_NONE +.* +#... diff --git a/ld/testsuite/ld-ifunc/ifunc-14c-x86-64.d b/ld/testsuite/ld-ifunc/ifunc-14c-x86-64.d new file mode 100644 index 0000000..76bfa84 --- /dev/null +++ b/ld/testsuite/ld-ifunc/ifunc-14c-x86-64.d @@ -0,0 +1,11 @@ +#source: ifunc-14a.s +#source: ifunc-14b.s +#ld: -shared -m elf_x86_64 -z nocombreloc +#as: --64 +#readelf: -r --wide +#target: x86_64-*-* + +#failif +#... +.* +R_X86_64_NONE +.* +#... diff --git a/ld/testsuite/ld-ifunc/ifunc-14d-i386.d b/ld/testsuite/ld-ifunc/ifunc-14d-i386.d new file mode 100644 index 0000000..2327278 --- /dev/null +++ b/ld/testsuite/ld-ifunc/ifunc-14d-i386.d @@ -0,0 +1,11 @@ +#source: ifunc-14b.s +#source: ifunc-14a.s +#ld: -shared -m elf_i386 -z nocombreloc +#as: --32 +#readelf: -r --wide +#target: x86_64-*-* i?86-*-* + +#failif +#... +.* +R_386_NONE +.* +#... diff --git a/ld/testsuite/ld-ifunc/ifunc-14d-x86-64.d b/ld/testsuite/ld-ifunc/ifunc-14d-x86-64.d new file mode 100644 index 0000000..789584b --- /dev/null +++ b/ld/testsuite/ld-ifunc/ifunc-14d-x86-64.d @@ -0,0 +1,11 @@ +#source: ifunc-14b.s +#source: ifunc-14a.s +#ld: -shared -m elf_x86_64 -z nocombreloc +#as: --64 +#readelf: -r --wide +#target: x86_64-*-* + +#failif +#... +.* +R_X86_64_NONE +.* +#... -- cgit v1.1