x86: Remove func_pointer_refcount

Since check_reloc is running after gc_sections, there is no need for
reference count.  If a function pointer relocation can be resolved at
run-time, there is no need for PLT and it doesn't count as non-GOT/PLT
relocation.  func_pointer_refcount can be removed.

	* elf32-i386.c (elf_i386_check_relocs): Set plt.refcount to 1.
	Don't use func_pointer_refcount.  Don't set plt.refcount nor
	non_got_ref for function pointer reference.
	* elf64-x86-64.c (elf_x86_64_check_relocs): Likewise.
	* elfxx-x86.c (elf_x86_allocate_dynrelocs): Don't use
	func_pointer_refcount.
	(_bfd_x86_elf_copy_indirect_symbol): Don't copy
	func_pointer_refcount.
	(_bfd_x86_elf_hide_symbol): Don't use func_pointer_refcount.
	* elfxx-x86.h (GENERATE_DYNAMIC_RELOCATION_P): Likewise.
	(elf_x86_link_hash_entry): Remove func_pointer_refcount.
This commit is contained in:
H.J. Lu
2017-11-03 11:14:56 -07:00
parent 67fa57cfa5
commit 79b0c981b8
5 changed files with 60 additions and 60 deletions

View File

@ -1,3 +1,17 @@
2017-11-03 H.J. Lu <hongjiu.lu@intel.com>
* elf32-i386.c (elf_i386_check_relocs): Set plt.refcount to 1.
Don't use func_pointer_refcount. Don't set plt.refcount nor
non_got_ref for function pointer reference.
* elf64-x86-64.c (elf_x86_64_check_relocs): Likewise.
* elfxx-x86.c (elf_x86_allocate_dynrelocs): Don't use
func_pointer_refcount.
(_bfd_x86_elf_copy_indirect_symbol): Don't copy
func_pointer_refcount.
(_bfd_x86_elf_hide_symbol): Don't use func_pointer_refcount.
* elfxx-x86.h (GENERATE_DYNAMIC_RELOCATION_P): Likewise.
(elf_x86_link_hash_entry): Remove func_pointer_refcount.
2017-11-03 Mingi Cho <mgcho.minic@gmail.com> 2017-11-03 Mingi Cho <mgcho.minic@gmail.com>
Nick Clifton <nickc@redhat.com> Nick Clifton <nickc@redhat.com>

View File

@ -1600,7 +1600,7 @@ elf_i386_check_relocs (bfd *abfd,
eh->zero_undefweak &= 0x2; eh->zero_undefweak &= 0x2;
h->needs_plt = 1; h->needs_plt = 1;
h->plt.refcount += 1; h->plt.refcount = 1;
break; break;
case R_386_SIZE32: case R_386_SIZE32:
@ -1751,20 +1751,7 @@ do_relocation:
&& (bfd_link_executable (info) && (bfd_link_executable (info)
|| h->type == STT_GNU_IFUNC)) || h->type == STT_GNU_IFUNC))
{ {
/* If this reloc is in a read-only section, we might bfd_boolean func_pointer_ref = FALSE;
need a copy reloc. We can't check reliably at this
stage whether the section is read-only, as input
sections have not yet been mapped to output sections.
Tentatively set the flag for now, and correct in
adjust_dynamic_symbol. */
h->non_got_ref = 1;
/* We may need a .plt entry if the symbol is a function
defined in a shared lib or is a STT_GNU_IFUNC function
referenced from the code or read-only section. */
if (!h->def_regular
|| (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
h->plt.refcount += 1;
if (r_type == R_386_PC32) if (r_type == R_386_PC32)
{ {
@ -1790,7 +1777,25 @@ do_relocation:
/* R_386_32 can be resolved at run-time. */ /* R_386_32 can be resolved at run-time. */
if (r_type == R_386_32 if (r_type == R_386_32
&& (sec->flags & SEC_READONLY) == 0) && (sec->flags & SEC_READONLY) == 0)
eh->func_pointer_refcount += 1; func_pointer_ref = TRUE;
}
if (!func_pointer_ref)
{
/* If this reloc is in a read-only section, we might
need a copy reloc. We can't check reliably at this
stage whether the section is read-only, as input
sections have not yet been mapped to output sections.
Tentatively set the flag for now, and correct in
adjust_dynamic_symbol. */
h->non_got_ref = 1;
/* We may need a .plt entry if the symbol is a function
defined in a shared lib or is a function referenced
from the code or read-only section. */
if (!h->def_regular
|| (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
h->plt.refcount = 1;
} }
} }

View File

@ -2067,7 +2067,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
eh->zero_undefweak &= 0x2; eh->zero_undefweak &= 0x2;
h->needs_plt = 1; h->needs_plt = 1;
h->plt.refcount += 1; h->plt.refcount = 1;
break; break;
case R_X86_64_PLTOFF64: case R_X86_64_PLTOFF64:
@ -2076,7 +2076,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
if (h != NULL) if (h != NULL)
{ {
h->needs_plt = 1; h->needs_plt = 1;
h->plt.refcount += 1; h->plt.refcount = 1;
} }
goto create_got; goto create_got;
@ -2124,20 +2124,7 @@ pointer:
&& (bfd_link_executable (info) && (bfd_link_executable (info)
|| h->type == STT_GNU_IFUNC)) || h->type == STT_GNU_IFUNC))
{ {
/* If this reloc is in a read-only section, we might bfd_boolean func_pointer_ref = FALSE;
need a copy reloc. We can't check reliably at this
stage whether the section is read-only, as input
sections have not yet been mapped to output sections.
Tentatively set the flag for now, and correct in
adjust_dynamic_symbol. */
h->non_got_ref = 1;
/* We may need a .plt entry if the symbol is a function
defined in a shared lib or is a STT_GNU_IFUNC function
referenced from the code or read-only section. */
if (!h->def_regular
|| (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
h->plt.refcount += 1;
if (r_type == R_X86_64_PC32) if (r_type == R_X86_64_PC32)
{ {
@ -2159,7 +2146,25 @@ pointer:
|| (!ABI_64_P (abfd) || (!ABI_64_P (abfd)
&& (r_type == R_X86_64_32 && (r_type == R_X86_64_32
|| r_type == R_X86_64_32S)))) || r_type == R_X86_64_32S))))
eh->func_pointer_refcount += 1; func_pointer_ref = TRUE;
}
if (!func_pointer_ref)
{
/* If this reloc is in a read-only section, we might
need a copy reloc. We can't check reliably at this
stage whether the section is read-only, as input
sections have not yet been mapped to output sections.
Tentatively set the flag for now, and correct in
adjust_dynamic_symbol. */
h->non_got_ref = 1;
/* We may need a .plt entry if the symbol is a function
defined in a shared lib or is a function referenced
from the code or read-only section. */
if (!h->def_regular
|| (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
h->plt.refcount = 1;
} }
} }

View File

@ -108,11 +108,6 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
resolved_to_zero = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh); resolved_to_zero = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, eh);
/* Clear the reference count of function pointer relocations if
symbol isn't a normal function. */
if (h->type != STT_FUNC)
eh->func_pointer_refcount = 0;
/* We can't use the GOT PLT if pointer equality is needed since /* We can't use the GOT PLT if pointer equality is needed since
finish_dynamic_symbol won't clear symbol value and the dynamic finish_dynamic_symbol won't clear symbol value and the dynamic
linker won't update the GOT slot. We will get into an infinite linker won't update the GOT slot. We will get into an infinite
@ -162,15 +157,11 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
/* Don't create the PLT entry if there are only function pointer /* Don't create the PLT entry if there are only function pointer
relocations which can be resolved at run-time. */ relocations which can be resolved at run-time. */
else if (htab->elf.dynamic_sections_created else if (htab->elf.dynamic_sections_created
&& (h->plt.refcount > eh->func_pointer_refcount && (h->plt.refcount > 0
|| eh->plt_got.refcount > 0)) || eh->plt_got.refcount > 0))
{ {
bfd_boolean use_plt_got = eh->plt_got.refcount > 0; bfd_boolean use_plt_got = eh->plt_got.refcount > 0;
/* Clear the reference count of function pointer relocations
if PLT is used. */
eh->func_pointer_refcount = 0;
/* Make sure this symbol is output as a dynamic symbol. /* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */ Undefined weak syms won't yet be marked as dynamic. */
if (h->dynindx == -1 if (h->dynindx == -1
@ -488,7 +479,6 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
pointer initialization. */ pointer initialization. */
if ((!h->non_got_ref if ((!h->non_got_ref
|| eh->func_pointer_refcount > 0
|| (h->root.type == bfd_link_hash_undefweak || (h->root.type == bfd_link_hash_undefweak
&& !resolved_to_zero)) && !resolved_to_zero))
&& ((h->def_dynamic && ((h->def_dynamic
@ -513,7 +503,6 @@ elf_x86_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
} }
eh->dyn_relocs = NULL; eh->dyn_relocs = NULL;
eh->func_pointer_refcount = 0;
keep: ; keep: ;
} }
@ -1643,15 +1632,7 @@ _bfd_x86_elf_copy_indirect_symbol (struct bfd_link_info *info,
dir->pointer_equality_needed |= ind->pointer_equality_needed; dir->pointer_equality_needed |= ind->pointer_equality_needed;
} }
else else
{ _bfd_elf_link_hash_copy_indirect (info, dir, ind);
if (eind->func_pointer_refcount > 0)
{
edir->func_pointer_refcount += eind->func_pointer_refcount;
eind->func_pointer_refcount = 0;
}
_bfd_elf_link_hash_copy_indirect (info, dir, ind);
}
} }
/* Remove undefined weak symbol from the dynamic symbol table if it /* Remove undefined weak symbol from the dynamic symbol table if it
@ -1900,7 +1881,7 @@ _bfd_x86_elf_hide_symbol (struct bfd_link_info *info,
weak symbol dynamic so that PC relative branch to the undefined weak symbol dynamic so that PC relative branch to the undefined
weak symbol will land to address 0. */ weak symbol will land to address 0. */
struct elf_x86_link_hash_entry *eh = elf_x86_hash_entry (h); struct elf_x86_link_hash_entry *eh = elf_x86_hash_entry (h);
if (h->plt.refcount > eh->func_pointer_refcount if (h->plt.refcount > 0
|| eh->plt_got.refcount > 0) || eh->plt_got.refcount > 0)
return; return;
} }

View File

@ -133,7 +133,6 @@
&& (EH) != NULL \ && (EH) != NULL \
&& (EH)->elf.dynindx != -1 \ && (EH)->elf.dynindx != -1 \
&& (!(EH)->elf.non_got_ref \ && (!(EH)->elf.non_got_ref \
|| (EH)->func_pointer_refcount > 0 \
|| ((EH)->elf.root.type == bfd_link_hash_undefweak \ || ((EH)->elf.root.type == bfd_link_hash_undefweak \
&& !(RESOLVED_TO_ZERO))) \ && !(RESOLVED_TO_ZERO))) \
&& (((EH)->elf.def_dynamic && !(EH)->elf.def_regular) \ && (((EH)->elf.def_dynamic && !(EH)->elf.def_regular) \
@ -268,10 +267,6 @@ struct elf_x86_link_hash_entry
is only used by x86-64. */ is only used by x86-64. */
unsigned int needs_copy : 1; unsigned int needs_copy : 1;
/* Reference count of C/C++ function pointer relocations in read-write
section which can be resolved at run-time. */
bfd_signed_vma func_pointer_refcount;
/* Information about the GOT PLT entry. Filled when there are both /* Information about the GOT PLT entry. Filled when there are both
GOT and PLT relocations against the same function. */ GOT and PLT relocations against the same function. */
union gotplt_union plt_got; union gotplt_union plt_got;