diff options
-rw-r--r-- | bfd/ChangeLog | 4 | ||||
-rw-r--r-- | bfd/elf-ifunc.c | 42 |
2 files changed, 28 insertions, 18 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index afa0a44..c2c0157 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,9 @@ 2011-01-06 H.J. Lu <hongjiu.lu@intel.com> + * elf-ifunc.c (_bfd_elf_allocate_ifunc_dyn_relocs): Optimized. + +2011-01-06 H.J. Lu <hongjiu.lu@intel.com> + PR ld/12366 PR ld/12371 * elf-ifunc.c (_bfd_elf_allocate_ifunc_dyn_relocs): Properly diff --git a/bfd/elf-ifunc.c b/bfd/elf-ifunc.c index 17b23c2..81429b8 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, |