summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2015-08-31 06:00:11 -0700
committerH.J. Lu <hjl.tools@gmail.com>2015-08-31 06:00:11 -0700
commit1ae793e0c9ea1f251d5d527c171fcf8fc84c0932 (patch)
tree16e0cfbe7d4fdd5b958d1490717b6cf67194818a
parent136765eab14d32f5fec607f755c3096eb43bf96f (diff)
downloadbinutils-gdb-1ae793e0c9ea1f251d5d527c171fcf8fc84c0932.tar.gz
Add pointer_refcount
-rw-r--r--bfd/elf64-x86-64.c51
1 files changed, 41 insertions, 10 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index f15d33ecc59..373f701d9d4 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -767,6 +767,9 @@ struct elf_x86_64_link_hash_entry
/* TRUE if symbol has at least one BND relocation. */
unsigned int has_bnd_reloc : 1;
+ /* Reference count of C/C++ pointer relocations. */
+ bfd_signed_vma pointer_refcount;
+
/* Information about the GOT PLT entry. Filled when there are both
GOT and PLT relocations against the same function. */
union gotplt_union plt_got;
@@ -906,6 +909,7 @@ elf_x86_64_link_hash_newfunc (struct bfd_hash_entry *entry,
eh->tls_type = GOT_UNKNOWN;
eh->needs_copy = 0;
eh->has_bnd_reloc = 0;
+ eh->pointer_refcount = 0;
eh->plt_bnd.offset = (bfd_vma) -1;
eh->plt_got.offset = (bfd_vma) -1;
eh->tlsdesc_got = (bfd_vma) -1;
@@ -973,6 +977,7 @@ elf_x86_64_get_local_sym_hash (struct elf_x86_64_link_hash_table *htab,
if (ret)
{
memset (ret, 0, sizeof (*ret));
+ ret->pointer_refcount = 0;
ret->elf.indx = sec->id;
ret->elf.dynstr_index = htab->r_sym (rel->r_info);
ret->elf.dynindx = -1;
@@ -1173,7 +1178,15 @@ elf_x86_64_copy_indirect_symbol (struct bfd_link_info *info,
dir->pointer_equality_needed |= ind->pointer_equality_needed;
}
else
- _bfd_elf_link_hash_copy_indirect (info, dir, ind);
+ {
+ if (eind->pointer_refcount > 0)
+ {
+ edir->pointer_refcount += eind->pointer_refcount;
+ eind->pointer_refcount = 0;
+ }
+
+ _bfd_elf_link_hash_copy_indirect (info, dir, ind);
+ }
}
static bfd_boolean
@@ -1947,10 +1960,15 @@ pointer:
/* We may need a .plt entry if the function this reloc
refers to is in a shared lib. */
h->plt.refcount += 1;
- if (r_type != R_X86_64_PC32
- && r_type != R_X86_64_PC32_BND
- && r_type != R_X86_64_PC64)
- h->pointer_equality_needed = 1;
+ if (r_type == R_X86_64_32
+ || r_type == R_X86_64_32S
+ || r_type == R_X86_64_64)
+ {
+ struct elf_x86_64_link_hash_entry *eh
+ = (struct elf_x86_64_link_hash_entry *) h;
+ eh->pointer_refcount += 1;
+ h->pointer_equality_needed = 1;
+ }
}
size_reloc = FALSE;
@@ -2177,6 +2195,7 @@ elf_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
unsigned long r_symndx;
unsigned int r_type;
struct elf_link_hash_entry *h = NULL;
+ bfd_boolean pointer_reloc;
r_symndx = htab->r_sym (rel->r_info);
if (r_symndx >= symtab_hdr->sh_info)
@@ -2228,6 +2247,7 @@ elf_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
rel, relend, h, r_symndx))
return FALSE;
+ pointer_reloc = FALSE;
switch (r_type)
{
case R_X86_64_TLSLD:
@@ -2261,11 +2281,12 @@ elf_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
}
break;
- case R_X86_64_8:
- case R_X86_64_16:
case R_X86_64_32:
case R_X86_64_64:
case R_X86_64_32S:
+ pointer_reloc = TRUE;
+ case R_X86_64_8:
+ case R_X86_64_16:
case R_X86_64_PC8:
case R_X86_64_PC16:
case R_X86_64_PC32:
@@ -2285,6 +2306,13 @@ elf_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
{
if (h->plt.refcount > 0)
h->plt.refcount -= 1;
+ if (pointer_reloc)
+ {
+ struct elf_x86_64_link_hash_entry *eh
+ = (struct elf_x86_64_link_hash_entry *) h;
+ if (eh->pointer_refcount > 0)
+ eh->pointer_refcount -= 1;
+ }
}
break;
@@ -2543,10 +2571,13 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
return FALSE;
}
else if (htab->elf.dynamic_sections_created
- && (h->plt.refcount > 0 || eh->plt_got.refcount > 0))
+ && (h->plt.refcount > eh->pointer_refcount
+ || eh->plt_got.refcount > 0))
{
bfd_boolean use_plt_got;
+ eh->pointer_refcount = 0;
+
if ((info->flags & DF_BIND_NOW) && !h->pointer_equality_needed)
{
/* Don't use the regular PLT for DF_BIND_NOW. */
@@ -2793,7 +2824,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
symbols which turn out to need copy relocs or are not
dynamic. */
- if (!h->non_got_ref
+ if ((!h->non_got_ref || eh->pointer_refcount > 0)
&& ((h->def_dynamic
&& !h->def_regular)
|| (htab->elf.dynamic_sections_created
@@ -4365,7 +4396,7 @@ direct:
&& !bfd_link_pic (info)
&& h != NULL
&& h->dynindx != -1
- && !h->non_got_ref
+ && (!h->non_got_ref || eh->pointer_refcount > 0)
&& ((h->def_dynamic
&& !h->def_regular)
|| h->root.type == bfd_link_hash_undefweak