X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf-ifunc.c;h=7e7ec366fddc493d724b80f0c821b1257cbb9685;hb=1622ff3b43f2f15af5ac3c245428eb99ade38d1e;hp=17b23c2ffc0e7688d1cbde0bd705c276f7cb08e6;hpb=3db2e7dda697d71311d698f21d7c65b8ec1774ca;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf-ifunc.c b/bfd/elf-ifunc.c index 17b23c2ffc..7e7ec366fd 100644 --- a/bfd/elf-ifunc.c +++ b/bfd/elf-ifunc.c @@ -125,11 +125,11 @@ _bfd_elf_create_ifunc_dyn_reloc (bfd *abfd, struct bfd_link_info *info, sreloc = _bfd_elf_make_dynamic_reloc_section (sec, htab->dynobj, bed->s->log_file_align, abfd, - bed->rela_plts_and_copies_p); + bed->rela_plts_and_copies_p); if (sreloc == NULL) return NULL; } - + p = *head; if (p == NULL || p->sec != sec) { @@ -175,7 +175,7 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info, || info->export_dynamic) && h->pointer_equality_needed) { - info->callbacks->einfo + info->callbacks->einfo (_("%F%P: dynamic STT_GNU_IFUNC symbol `%s' with pointer " "equality in `%B' can not be used when making an " "executable; recompile with -fPIE and relink with -pie\n"), @@ -187,32 +187,24 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info, htab = elf_hash_table (info); - /* Support garbage collection against STT_GNU_IFUNC symbols. */ - if (h->plt.refcount <= 0 && h->got.refcount <= 0) - { - /* When building shared library, we need to handle the case - 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) + /* When building shared library, we need to handle the case where it is + marked with regular reference, but not non-GOT reference since the + non-GOT reference bit may not be set here. */ + if (info->shared && !h->non_got_ref && h->ref_regular) + for (p = *head; p != NULL; p = p->next) + if (p->count) { - for (p = *head; p != NULL; p = p->next) - count += p->count; - if (count != 0) - h->non_got_ref = 1; + 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; - } + /* Support garbage collection against STT_GNU_IFUNC symbols. */ + if (h->plt.refcount <= 0 && h->got.refcount <= 0) + { + 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 +220,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; @@ -255,7 +248,7 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info, } /* Don't update value of STT_GNU_IFUNC symbol to PLT. We need - the original value for R_*_IRELATIVE. */ + the original value for R_*_IRELATIVE. */ h->plt.offset = plt->size; /* Make room for this entry in the .plt/.iplt section. */ @@ -277,10 +270,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, @@ -293,9 +296,10 @@ _bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info, 5. Otherwise use .got so that it can be shared among different objects at run-time. We only need to relocate .got entry in shared object. */ - if ((info->shared - && (h->dynindx == -1 - || h->forced_local)) + if (h->got.refcount <= 0 + || (info->shared + && (h->dynindx == -1 + || h->forced_local)) || (!info->shared && !h->pointer_equality_needed) || (info->executable && info->shared)