From 7be867377db57e62bc2dc7f0756b484bdac30fda Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Fri, 7 Jan 2011 03:34:23 +0000 Subject: [PATCH] Optimize _bfd_elf_allocate_ifunc_dyn_relocs. 2011-01-06 H.J. Lu * elf-ifunc.c (_bfd_elf_allocate_ifunc_dyn_relocs): Optimized. --- bfd/ChangeLog | 4 ++++ bfd/elf-ifunc.c | 42 ++++++++++++++++++++++++------------------ 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index afa0a44ff5..c2c015708d 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,7 @@ +2011-01-06 H.J. Lu + + * elf-ifunc.c (_bfd_elf_allocate_ifunc_dyn_relocs): Optimized. + 2011-01-06 H.J. Lu PR ld/12366 diff --git a/bfd/elf-ifunc.c b/bfd/elf-ifunc.c index 17b23c2ffc..81429b8433 100644 --- a/bfd/elf-ifunc.c +++ b/bfd/elf-ifunc.c @@ -194,25 +194,20 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info, where it is marked with regular reference, but not non-GOT reference. It may happen if we didn't see STT_GNU_IFUNC symbol at the time when checking relocations. */ - bfd_size_type count = 0; - if (info->shared && !h->non_got_ref && h->ref_regular) - { - for (p = *head; p != NULL; p = p->next) - count += p->count; - if (count != 0) - h->non_got_ref = 1; - } + for (p = *head; p != NULL; p = p->next) + if (p->count) + { + h->non_got_ref = 1; + goto keep; + } - if (count == 0) - { - h->got = htab->init_got_offset; - h->plt = htab->init_plt_offset; - *head = NULL; - return TRUE; - } + h->got = htab->init_got_offset; + h->plt = htab->init_plt_offset; + *head = NULL; + return TRUE; } /* Return and discard space for dynamic relocations against it if @@ -228,6 +223,7 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info, return TRUE; } +keep: bed = get_elf_backend_data (info->output_bfd); if (bed->rela_plts_and_copies_p) sizeof_reloc = bed->s->sizeof_rela; @@ -277,10 +273,20 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info, *head = NULL; /* Finally, allocate space. */ - for (p = *head; p != NULL; p = p->next) - htab->irelifunc->size += p->count * sizeof_reloc; + p = *head; + if (p != NULL) + { + bfd_size_type count = 0; + do + { + count += p->count; + p = p->next; + } + while (p != NULL); + htab->irelifunc->size += count * sizeof_reloc; + } - /* For STT_GNU_IFUNC symbol, .got.plt has the real function addres + /* For STT_GNU_IFUNC symbol, .got.plt has the real function address and .got has the PLT entry adddress. We will load the GOT entry with the PLT entry in finish_dynamic_symbol if it is used. For branch, it uses .got.plt. For symbol value, -- 2.34.1