forked from Imagelibrary/binutils-gdb
x86: Remove _bfd_{i386,x86_64}_elf_convert_load
Instead of converting GOT relocations when sizing dynamic sections, we convert GOT relocations during relocation check. Add a field, local_ref, to elf_x86_link_hash_entry to indicate if symbol references are always local with a new function to check if symbol references are always local, which works in check_relocs. * elf32-i386.c (elf_i386_convert_load_reloc): Add an argument, r_type_p. Remove the converted argument. Replace SYMBOL_REFERENCES_LOCAL with SYMBOL_REFERENCES_LOCAL_P. Return the new relocation type via r_type_p. (elf_i386_relocate_section): Likewise. (elf_i386_finish_dynamic_symbol): Likewise. (need_convert_load): Removed. (check_relocs_failed): Updated. (elf_i386_check_relocs): Call elf_i386_convert_load_reloc, instead of setting need_convert_load. (_bfd_i386_elf_convert_load): Removed. * elf64-x86-64.c (need_convert_load): Removed. (check_relocs_failed): Updated. (elf_x86_64_convert_load_reloc): Add an argument, r_type_p. Replace SYMBOL_REFERENCES_LOCAL with SYMBOL_REFERENCES_LOCAL_P. Return the new relocation type via r_type_p. (elf_x86_64_check_relocs): Call elf_x86_64_convert_load_reloc, instead of setting need_convert_load. (elf_x86_64_check_relocs): Don't check PIC if relocation has been converted. (_bfd_x86_64_elf_convert_load): Removed. (elf_x86_64_relocate_section): Replace SYMBOL_REFERENCES_LOCAL with SYMBOL_REFERENCES_LOCAL_P. (elf_x86_64_finish_dynamic_symbol): Likewise. * elfxx-x86.c (_bfd_x86_elf_link_hash_table_create): Don't set convert_load. (_bfd_x86_elf_size_dynamic_sections): Don't call convert_load. (_bfd_x86_elf_link_symbol_references_local): New function. * elfxx-x86.h (SYMBOL_REFERENCES_LOCAL_P): New. (UNDEFINED_WEAK_RESOLVED_TO_ZERO): Replace elf.forced_local with SYMBOL_REFERENCES_LOCAL_P. (elf_x86_link_hash_entry): Add local_ref. (elf_x86_link_hash_table): Remove convert_load. (_bfd_i386_elf_convert_load): Removed. (_bfd_x86_64_elf_convert_load): Likewise. (_bfd_x86_elf_link_symbol_references_local): New.
This commit is contained in:
@@ -1,3 +1,42 @@
|
||||
2017-09-07 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* elf32-i386.c (elf_i386_convert_load_reloc): Add an argument,
|
||||
r_type_p. Remove the converted argument. Replace
|
||||
SYMBOL_REFERENCES_LOCAL with SYMBOL_REFERENCES_LOCAL_P. Return
|
||||
the new relocation type via r_type_p.
|
||||
(elf_i386_relocate_section): Likewise.
|
||||
(elf_i386_finish_dynamic_symbol): Likewise.
|
||||
(need_convert_load): Removed.
|
||||
(check_relocs_failed): Updated.
|
||||
(elf_i386_check_relocs): Call elf_i386_convert_load_reloc,
|
||||
instead of setting need_convert_load.
|
||||
(_bfd_i386_elf_convert_load): Removed.
|
||||
* elf64-x86-64.c (need_convert_load): Removed.
|
||||
(check_relocs_failed): Updated.
|
||||
(elf_x86_64_convert_load_reloc): Add an argument, r_type_p.
|
||||
Replace SYMBOL_REFERENCES_LOCAL with SYMBOL_REFERENCES_LOCAL_P.
|
||||
Return the new relocation type via r_type_p.
|
||||
(elf_x86_64_check_relocs): Call elf_x86_64_convert_load_reloc,
|
||||
instead of setting need_convert_load.
|
||||
(elf_x86_64_check_relocs): Don't check PIC if relocation has
|
||||
been converted.
|
||||
(_bfd_x86_64_elf_convert_load): Removed.
|
||||
(elf_x86_64_relocate_section): Replace SYMBOL_REFERENCES_LOCAL
|
||||
with SYMBOL_REFERENCES_LOCAL_P.
|
||||
(elf_x86_64_finish_dynamic_symbol): Likewise.
|
||||
* elfxx-x86.c (_bfd_x86_elf_link_hash_table_create): Don't
|
||||
set convert_load.
|
||||
(_bfd_x86_elf_size_dynamic_sections): Don't call convert_load.
|
||||
(_bfd_x86_elf_link_symbol_references_local): New function.
|
||||
* elfxx-x86.h (SYMBOL_REFERENCES_LOCAL_P): New.
|
||||
(UNDEFINED_WEAK_RESOLVED_TO_ZERO): Replace elf.forced_local with
|
||||
SYMBOL_REFERENCES_LOCAL_P.
|
||||
(elf_x86_link_hash_entry): Add local_ref.
|
||||
(elf_x86_link_hash_table): Remove convert_load.
|
||||
(_bfd_i386_elf_convert_load): Removed.
|
||||
(_bfd_x86_64_elf_convert_load): Likewise.
|
||||
(_bfd_x86_elf_link_symbol_references_local): New.
|
||||
|
||||
2017-09-06 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* elf64-x86-64.c (R_X86_64_converted_reloc_bit): New.
|
||||
|
||||
168
bfd/elf32-i386.c
168
bfd/elf32-i386.c
@@ -1211,9 +1211,9 @@ static
|
||||
bfd_boolean
|
||||
elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
|
||||
bfd_byte *contents,
|
||||
unsigned int *r_type_p,
|
||||
Elf_Internal_Rela *irel,
|
||||
struct elf_link_hash_entry *h,
|
||||
bfd_boolean *converted,
|
||||
struct bfd_link_info *link_info)
|
||||
{
|
||||
struct elf_x86_link_hash_table *htab;
|
||||
@@ -1241,7 +1241,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
|
||||
htab = elf_x86_hash_table (link_info, I386_ELF_DATA);
|
||||
is_pic = bfd_link_pic (link_info);
|
||||
|
||||
r_type = ELF32_R_TYPE (irel->r_info);
|
||||
r_type = *r_type_p;
|
||||
r_symndx = ELF32_R_SYM (irel->r_info);
|
||||
|
||||
modrm = bfd_get_8 (abfd, contents + roff - 1);
|
||||
@@ -1316,7 +1316,7 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr,
|
||||
/* We have "call/jmp *foo@GOT[(%reg)]". */
|
||||
if ((h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
&& SYMBOL_REFERENCES_LOCAL (link_info, h))
|
||||
&& SYMBOL_REFERENCES_LOCAL_P (link_info, h))
|
||||
{
|
||||
/* The function is locally defined. */
|
||||
convert_branch:
|
||||
@@ -1363,8 +1363,7 @@ convert_branch:
|
||||
need to adjust addend by -4. */
|
||||
bfd_put_32 (abfd, -4, contents + irel->r_offset);
|
||||
irel->r_info = ELF32_R_INFO (r_symndx, R_386_PC32);
|
||||
|
||||
*converted = TRUE;
|
||||
*r_type_p = R_386_PC32;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1385,7 +1384,7 @@ convert_branch:
|
||||
|| ((h->def_regular
|
||||
|| h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
&& SYMBOL_REFERENCES_LOCAL (link_info, h)))
|
||||
&& SYMBOL_REFERENCES_LOCAL_P (link_info, h)))
|
||||
{
|
||||
convert_load:
|
||||
if (opcode == 0x8b)
|
||||
@@ -1435,8 +1434,7 @@ convert_load:
|
||||
|
||||
bfd_put_8 (abfd, opcode, contents + roff - 2);
|
||||
irel->r_info = ELF32_R_INFO (r_symndx, r_type);
|
||||
|
||||
*converted = TRUE;
|
||||
*r_type_p = r_type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1445,8 +1443,7 @@ convert_load:
|
||||
|
||||
/* Rename some of the generic section flags to better document how they
|
||||
are used here. */
|
||||
#define need_convert_load sec_flg0
|
||||
#define check_relocs_failed sec_flg1
|
||||
#define check_relocs_failed sec_flg0
|
||||
|
||||
/* Look through the relocs for a section during the first phase, and
|
||||
calculate needed space in the global offset table, procedure linkage
|
||||
@@ -1574,6 +1571,15 @@ elf_i386_check_relocs (bfd *abfd,
|
||||
|= elf_gnu_symbol_ifunc;
|
||||
}
|
||||
|
||||
if (r_type == R_386_GOT32X
|
||||
&& (h == NULL || h->type != STT_GNU_IFUNC))
|
||||
{
|
||||
Elf_Internal_Rela *irel = (Elf_Internal_Rela *) rel;
|
||||
if (!elf_i386_convert_load_reloc (abfd, symtab_hdr, contents,
|
||||
&r_type, irel, h, info))
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
if (! elf_i386_tls_transition (info, abfd, sec, contents,
|
||||
symtab_hdr, sym_hashes,
|
||||
&r_type, GOT_UNKNOWN,
|
||||
@@ -1921,10 +1927,6 @@ do_size:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (r_type == R_386_GOT32X
|
||||
&& (h == NULL || h->type != STT_GNU_IFUNC))
|
||||
sec->need_convert_load = 1;
|
||||
}
|
||||
|
||||
if (elf_section_data (sec)->this_hdr.contents != contents)
|
||||
@@ -1947,136 +1949,6 @@ error_return:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Convert load via the GOT slot to load immediate. */
|
||||
|
||||
bfd_boolean
|
||||
_bfd_i386_elf_convert_load (bfd *abfd, asection *sec,
|
||||
struct bfd_link_info *link_info)
|
||||
{
|
||||
struct elf_x86_link_hash_table *htab;
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
Elf_Internal_Rela *internal_relocs;
|
||||
Elf_Internal_Rela *irel, *irelend;
|
||||
bfd_byte *contents;
|
||||
bfd_boolean changed;
|
||||
bfd_signed_vma *local_got_refcounts;
|
||||
|
||||
/* Don't even try to convert non-ELF outputs. */
|
||||
if (!is_elf_hash_table (link_info->hash))
|
||||
return FALSE;
|
||||
|
||||
/* Nothing to do if there is no need or no output. */
|
||||
if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC)
|
||||
|| sec->need_convert_load == 0
|
||||
|| bfd_is_abs_section (sec->output_section))
|
||||
return TRUE;
|
||||
|
||||
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
||||
|
||||
/* Load the relocations for this section. */
|
||||
internal_relocs = (_bfd_elf_link_read_relocs
|
||||
(abfd, sec, NULL, (Elf_Internal_Rela *) NULL,
|
||||
link_info->keep_memory));
|
||||
if (internal_relocs == NULL)
|
||||
return FALSE;
|
||||
|
||||
changed = FALSE;
|
||||
htab = elf_x86_hash_table (link_info, I386_ELF_DATA);
|
||||
local_got_refcounts = elf_local_got_refcounts (abfd);
|
||||
|
||||
/* Get the section contents. */
|
||||
if (elf_section_data (sec)->this_hdr.contents != NULL)
|
||||
contents = elf_section_data (sec)->this_hdr.contents;
|
||||
else
|
||||
{
|
||||
if (!bfd_malloc_and_get_section (abfd, sec, &contents))
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
irelend = internal_relocs + sec->reloc_count;
|
||||
for (irel = internal_relocs; irel < irelend; irel++)
|
||||
{
|
||||
unsigned int r_type = ELF32_R_TYPE (irel->r_info);
|
||||
unsigned int r_symndx;
|
||||
struct elf_link_hash_entry *h;
|
||||
bfd_boolean converted;
|
||||
|
||||
/* Don't convert R_386_GOT32 since we can't tell if it is applied
|
||||
to "mov $foo@GOT, %reg" which isn't a load via GOT. */
|
||||
if (r_type != R_386_GOT32X)
|
||||
continue;
|
||||
|
||||
r_symndx = ELF32_R_SYM (irel->r_info);
|
||||
if (r_symndx < symtab_hdr->sh_info)
|
||||
h = _bfd_elf_x86_get_local_sym_hash (htab, sec->owner,
|
||||
(const Elf_Internal_Rela *) irel,
|
||||
FALSE);
|
||||
else
|
||||
{
|
||||
h = elf_sym_hashes (abfd)[r_symndx - symtab_hdr->sh_info];
|
||||
while (h->root.type == bfd_link_hash_indirect
|
||||
|| h->root.type == bfd_link_hash_warning)
|
||||
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
||||
}
|
||||
|
||||
/* STT_GNU_IFUNC must keep GOT32 relocations. */
|
||||
if (h != NULL && h->type == STT_GNU_IFUNC)
|
||||
continue;
|
||||
|
||||
converted = FALSE;
|
||||
if (!elf_i386_convert_load_reloc (abfd, symtab_hdr, contents,
|
||||
irel, h, &converted, link_info))
|
||||
goto error_return;
|
||||
|
||||
if (converted)
|
||||
{
|
||||
changed = converted;
|
||||
if (h)
|
||||
{
|
||||
if (h->got.refcount > 0)
|
||||
h->got.refcount -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (local_got_refcounts != NULL
|
||||
&& local_got_refcounts[r_symndx] > 0)
|
||||
local_got_refcounts[r_symndx] -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (contents != NULL
|
||||
&& elf_section_data (sec)->this_hdr.contents != contents)
|
||||
{
|
||||
if (!changed && !link_info->keep_memory)
|
||||
free (contents);
|
||||
else
|
||||
{
|
||||
/* Cache the section contents for elf_link_input_bfd. */
|
||||
elf_section_data (sec)->this_hdr.contents = contents;
|
||||
}
|
||||
}
|
||||
|
||||
if (elf_section_data (sec)->relocs != internal_relocs)
|
||||
{
|
||||
if (!changed)
|
||||
free (internal_relocs);
|
||||
else
|
||||
elf_section_data (sec)->relocs = internal_relocs;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
error_return:
|
||||
if (contents != NULL
|
||||
&& elf_section_data (sec)->this_hdr.contents != contents)
|
||||
free (contents);
|
||||
if (internal_relocs != NULL
|
||||
&& elf_section_data (sec)->relocs != internal_relocs)
|
||||
free (internal_relocs);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Set the correct type for an x86 ELF section. We do this by the
|
||||
section name, which is a hack, but ought to work. */
|
||||
|
||||
@@ -2672,7 +2544,7 @@ r_386_got32:
|
||||
bfd_link_pic (info),
|
||||
h)
|
||||
|| (bfd_link_pic (info)
|
||||
&& SYMBOL_REFERENCES_LOCAL (info, h))
|
||||
&& SYMBOL_REFERENCES_LOCAL_P (info, h))
|
||||
|| (ELF_ST_VISIBILITY (h->other)
|
||||
&& h->root.type == bfd_link_hash_undefweak))
|
||||
{
|
||||
@@ -2831,7 +2703,7 @@ disallow_got32:
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return FALSE;
|
||||
}
|
||||
else if (!SYMBOL_REFERENCES_LOCAL (info, h)
|
||||
else if (!SYMBOL_REFERENCES_LOCAL_P (info, h)
|
||||
&& (h->type == STT_FUNC
|
||||
|| h->type == STT_OBJECT)
|
||||
&& ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
|
||||
@@ -4045,7 +3917,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
|
||||
in static executable. */
|
||||
relgot = htab->elf.irelplt;
|
||||
}
|
||||
if (SYMBOL_REFERENCES_LOCAL (info, h))
|
||||
if (SYMBOL_REFERENCES_LOCAL_P (info, h))
|
||||
{
|
||||
info->callbacks->minfo (_("Local IFUNC function `%s' in %B\n"),
|
||||
h->root.root.string,
|
||||
@@ -4095,7 +3967,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd,
|
||||
}
|
||||
}
|
||||
else if (bfd_link_pic (info)
|
||||
&& SYMBOL_REFERENCES_LOCAL (info, h))
|
||||
&& SYMBOL_REFERENCES_LOCAL_P (info, h))
|
||||
{
|
||||
BFD_ASSERT((h->got.offset & 1) != 0);
|
||||
rel.r_info = ELF32_R_INFO (0, R_386_RELATIVE);
|
||||
|
||||
@@ -1362,8 +1362,7 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
|
||||
|
||||
/* Rename some of the generic section flags to better document how they
|
||||
are used here. */
|
||||
#define need_convert_load sec_flg0
|
||||
#define check_relocs_failed sec_flg1
|
||||
#define check_relocs_failed sec_flg0
|
||||
|
||||
static bfd_boolean
|
||||
elf_x86_64_need_pic (struct bfd_link_info *info,
|
||||
@@ -1450,6 +1449,7 @@ elf_x86_64_need_pic (struct bfd_link_info *info,
|
||||
static bfd_boolean
|
||||
elf_x86_64_convert_load_reloc (bfd *abfd,
|
||||
bfd_byte *contents,
|
||||
unsigned int *r_type_p,
|
||||
Elf_Internal_Rela *irel,
|
||||
struct elf_link_hash_entry *h,
|
||||
bfd_boolean *converted,
|
||||
@@ -1464,7 +1464,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
|
||||
bfd_signed_vma raddend;
|
||||
unsigned int opcode;
|
||||
unsigned int modrm;
|
||||
unsigned int r_type = ELF32_R_TYPE (irel->r_info);
|
||||
unsigned int r_type = *r_type_p;
|
||||
unsigned int r_symndx;
|
||||
bfd_vma roff = irel->r_offset;
|
||||
|
||||
@@ -1572,7 +1572,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd,
|
||||
|| h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
&& h != htab->elf.hdynamic
|
||||
&& SYMBOL_REFERENCES_LOCAL (link_info, h)))
|
||||
&& SYMBOL_REFERENCES_LOCAL_P (link_info, h)))
|
||||
{
|
||||
/* bfd_link_hash_new or bfd_link_hash_undefined is
|
||||
set by an assignment in a linker script in
|
||||
@@ -1749,6 +1749,7 @@ rewrite_modrm_rex:
|
||||
bfd_put_8 (abfd, opcode, contents + roff - 2);
|
||||
}
|
||||
|
||||
*r_type_p = r_type;
|
||||
irel->r_info = htab->r_info (r_symndx,
|
||||
r_type | R_X86_64_converted_reloc_bit);
|
||||
|
||||
@@ -1819,6 +1820,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
Elf_Internal_Sym *isym;
|
||||
const char *name;
|
||||
bfd_boolean size_reloc;
|
||||
bfd_boolean converted_reloc;
|
||||
|
||||
r_symndx = htab->r_sym (rel->r_info);
|
||||
r_type = ELF32_R_TYPE (rel->r_info);
|
||||
@@ -1912,6 +1914,19 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
|= elf_gnu_symbol_ifunc;
|
||||
}
|
||||
|
||||
converted_reloc = FALSE;
|
||||
if ((r_type == R_X86_64_GOTPCREL
|
||||
|| r_type == R_X86_64_GOTPCRELX
|
||||
|| r_type == R_X86_64_REX_GOTPCRELX)
|
||||
&& (h == NULL || h->type != STT_GNU_IFUNC))
|
||||
{
|
||||
Elf_Internal_Rela *irel = (Elf_Internal_Rela *) rel;
|
||||
if (!elf_x86_64_convert_load_reloc (abfd, contents, &r_type,
|
||||
irel, h, &converted_reloc,
|
||||
info))
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
if (! elf_x86_64_tls_transition (info, abfd, sec, contents,
|
||||
symtab_hdr, sym_hashes,
|
||||
&r_type, GOT_UNKNOWN,
|
||||
@@ -2087,6 +2102,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
sections we don't care about, such as debug sections or
|
||||
when relocation overflow check is disabled. */
|
||||
if (!info->no_reloc_overflow_check
|
||||
&& !converted_reloc
|
||||
&& (bfd_link_pic (info)
|
||||
|| (bfd_link_executable (info)
|
||||
&& h != NULL
|
||||
@@ -2280,12 +2296,6 @@ do_size:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ((r_type == R_X86_64_GOTPCREL
|
||||
|| r_type == R_X86_64_GOTPCRELX
|
||||
|| r_type == R_X86_64_REX_GOTPCRELX)
|
||||
&& (h == NULL || h->type != STT_GNU_IFUNC))
|
||||
sec->need_convert_load = 1;
|
||||
}
|
||||
|
||||
if (elf_section_data (sec)->this_hdr.contents != contents)
|
||||
@@ -2308,136 +2318,6 @@ error_return:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Convert load via the GOT slot to load immediate. */
|
||||
|
||||
bfd_boolean
|
||||
_bfd_x86_64_elf_convert_load (bfd *abfd, asection *sec,
|
||||
struct bfd_link_info *link_info)
|
||||
{
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
Elf_Internal_Rela *internal_relocs;
|
||||
Elf_Internal_Rela *irel, *irelend;
|
||||
bfd_byte *contents;
|
||||
struct elf_x86_link_hash_table *htab;
|
||||
bfd_boolean changed;
|
||||
bfd_signed_vma *local_got_refcounts;
|
||||
|
||||
/* Don't even try to convert non-ELF outputs. */
|
||||
if (!is_elf_hash_table (link_info->hash))
|
||||
return FALSE;
|
||||
|
||||
/* Nothing to do if there is no need or no output. */
|
||||
if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC)
|
||||
|| sec->need_convert_load == 0
|
||||
|| bfd_is_abs_section (sec->output_section))
|
||||
return TRUE;
|
||||
|
||||
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
||||
|
||||
/* Load the relocations for this section. */
|
||||
internal_relocs = (_bfd_elf_link_read_relocs
|
||||
(abfd, sec, NULL, (Elf_Internal_Rela *) NULL,
|
||||
link_info->keep_memory));
|
||||
if (internal_relocs == NULL)
|
||||
return FALSE;
|
||||
|
||||
changed = FALSE;
|
||||
htab = elf_x86_hash_table (link_info, X86_64_ELF_DATA);
|
||||
local_got_refcounts = elf_local_got_refcounts (abfd);
|
||||
|
||||
/* Get the section contents. */
|
||||
if (elf_section_data (sec)->this_hdr.contents != NULL)
|
||||
contents = elf_section_data (sec)->this_hdr.contents;
|
||||
else
|
||||
{
|
||||
if (!bfd_malloc_and_get_section (abfd, sec, &contents))
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
irelend = internal_relocs + sec->reloc_count;
|
||||
for (irel = internal_relocs; irel < irelend; irel++)
|
||||
{
|
||||
unsigned int r_type = ELF32_R_TYPE (irel->r_info);
|
||||
unsigned int r_symndx;
|
||||
struct elf_link_hash_entry *h;
|
||||
bfd_boolean converted;
|
||||
|
||||
if (r_type != R_X86_64_GOTPCRELX
|
||||
&& r_type != R_X86_64_REX_GOTPCRELX
|
||||
&& r_type != R_X86_64_GOTPCREL)
|
||||
continue;
|
||||
|
||||
r_symndx = htab->r_sym (irel->r_info);
|
||||
if (r_symndx < symtab_hdr->sh_info)
|
||||
h = _bfd_elf_x86_get_local_sym_hash (htab, sec->owner,
|
||||
(const Elf_Internal_Rela *) irel,
|
||||
FALSE);
|
||||
else
|
||||
{
|
||||
h = elf_sym_hashes (abfd)[r_symndx - symtab_hdr->sh_info];
|
||||
while (h->root.type == bfd_link_hash_indirect
|
||||
|| h->root.type == bfd_link_hash_warning)
|
||||
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
||||
}
|
||||
|
||||
/* STT_GNU_IFUNC must keep GOTPCREL relocations. */
|
||||
if (h != NULL && h->type == STT_GNU_IFUNC)
|
||||
continue;
|
||||
|
||||
converted = FALSE;
|
||||
if (!elf_x86_64_convert_load_reloc (abfd, contents, irel, h,
|
||||
&converted, link_info))
|
||||
goto error_return;
|
||||
|
||||
if (converted)
|
||||
{
|
||||
changed = converted;
|
||||
if (h)
|
||||
{
|
||||
if (h->got.refcount > 0)
|
||||
h->got.refcount -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (local_got_refcounts != NULL
|
||||
&& local_got_refcounts[r_symndx] > 0)
|
||||
local_got_refcounts[r_symndx] -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (contents != NULL
|
||||
&& elf_section_data (sec)->this_hdr.contents != contents)
|
||||
{
|
||||
if (!changed && !link_info->keep_memory)
|
||||
free (contents);
|
||||
else
|
||||
{
|
||||
/* Cache the section contents for elf_link_input_bfd. */
|
||||
elf_section_data (sec)->this_hdr.contents = contents;
|
||||
}
|
||||
}
|
||||
|
||||
if (elf_section_data (sec)->relocs != internal_relocs)
|
||||
{
|
||||
if (!changed)
|
||||
free (internal_relocs);
|
||||
else
|
||||
elf_section_data (sec)->relocs = internal_relocs;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
error_return:
|
||||
if (contents != NULL
|
||||
&& elf_section_data (sec)->this_hdr.contents != contents)
|
||||
free (contents);
|
||||
if (internal_relocs != NULL
|
||||
&& elf_section_data (sec)->relocs != internal_relocs)
|
||||
free (internal_relocs);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Return the relocation value for @tpoff relocation
|
||||
if STT_TLS virtual address is ADDRESS. */
|
||||
|
||||
@@ -2929,7 +2809,7 @@ do_ifunc_pointer:
|
||||
|
||||
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, bfd_link_pic (info), h)
|
||||
|| (bfd_link_pic (info)
|
||||
&& SYMBOL_REFERENCES_LOCAL (info, h))
|
||||
&& SYMBOL_REFERENCES_LOCAL_P (info, h))
|
||||
|| (ELF_ST_VISIBILITY (h->other)
|
||||
&& h->root.type == bfd_link_hash_undefweak))
|
||||
{
|
||||
@@ -3064,7 +2944,7 @@ do_ifunc_pointer:
|
||||
return FALSE;
|
||||
}
|
||||
else if (!bfd_link_executable (info)
|
||||
&& !SYMBOL_REFERENCES_LOCAL (info, h)
|
||||
&& !SYMBOL_REFERENCES_LOCAL_P (info, h)
|
||||
&& (h->type == STT_FUNC
|
||||
|| h->type == STT_OBJECT)
|
||||
&& ELF_ST_VISIBILITY (h->other) == STV_PROTECTED)
|
||||
@@ -3212,7 +3092,7 @@ do_ifunc_pointer:
|
||||
|| r_type == R_X86_64_PC32_BND)
|
||||
&& is_32bit_relative_branch (contents, rel->r_offset));
|
||||
|
||||
if (SYMBOL_REFERENCES_LOCAL (info, h))
|
||||
if (SYMBOL_REFERENCES_LOCAL_P (info, h))
|
||||
{
|
||||
/* Symbol is referenced locally. Make sure it is
|
||||
defined locally or for a branch. */
|
||||
@@ -4379,7 +4259,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
|
||||
in static executable. */
|
||||
relgot = htab->elf.irelplt;
|
||||
}
|
||||
if (SYMBOL_REFERENCES_LOCAL (info, h))
|
||||
if (SYMBOL_REFERENCES_LOCAL_P (info, h))
|
||||
{
|
||||
info->callbacks->minfo (_("Local IFUNC function `%s' in %B\n"),
|
||||
output_bfd,
|
||||
@@ -4429,7 +4309,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
|
||||
}
|
||||
}
|
||||
else if (bfd_link_pic (info)
|
||||
&& SYMBOL_REFERENCES_LOCAL (info, h))
|
||||
&& SYMBOL_REFERENCES_LOCAL_P (info, h))
|
||||
{
|
||||
if (!(h->def_regular || ELF_COMMON_DEF_P (h)))
|
||||
return FALSE;
|
||||
|
||||
@@ -766,7 +766,6 @@ _bfd_x86_elf_link_hash_table_create (bfd *abfd)
|
||||
/* NB: If BFD64 isn't defined, only i386 will be supported. */
|
||||
if (bed->target_id == X86_64_ELF_DATA)
|
||||
{
|
||||
ret->convert_load = _bfd_x86_64_elf_convert_load;
|
||||
ret->is_reloc_section = elf_x86_64_is_reloc_section;
|
||||
ret->dt_reloc = DT_RELA;
|
||||
ret->dt_reloc_sz = DT_RELASZ;
|
||||
@@ -798,7 +797,6 @@ _bfd_x86_elf_link_hash_table_create (bfd *abfd)
|
||||
}
|
||||
else
|
||||
{
|
||||
ret->convert_load = _bfd_i386_elf_convert_load;
|
||||
ret->is_reloc_section = elf_i386_is_reloc_section;
|
||||
ret->dt_reloc = DT_REL;
|
||||
ret->dt_reloc_sz = DT_RELSZ;
|
||||
@@ -909,9 +907,6 @@ _bfd_x86_elf_size_dynamic_sections (bfd *output_bfd,
|
||||
{
|
||||
struct elf_dyn_relocs *p;
|
||||
|
||||
if (!htab->convert_load (ibfd, s, info))
|
||||
return FALSE;
|
||||
|
||||
for (p = ((struct elf_dyn_relocs *)
|
||||
elf_section_data (s)->local_dynrel);
|
||||
p != NULL;
|
||||
@@ -1677,6 +1672,45 @@ _bfd_x86_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
|
||||
return _bfd_elf_adjust_dynamic_copy (info, h, s);
|
||||
}
|
||||
|
||||
/* Return TRUE if a symbol is referenced locally. It is similar to
|
||||
SYMBOL_REFERENCES_LOCAL, but it also checks version script. It
|
||||
works in check_relocs. */
|
||||
|
||||
bfd_boolean
|
||||
_bfd_x86_elf_link_symbol_references_local (struct bfd_link_info *info,
|
||||
struct elf_link_hash_entry *h)
|
||||
{
|
||||
struct elf_x86_link_hash_entry *eh
|
||||
= (struct elf_x86_link_hash_entry *) h;
|
||||
|
||||
if (eh->local_ref > 1)
|
||||
return TRUE;
|
||||
|
||||
if (eh->local_ref == 1)
|
||||
return FALSE;
|
||||
|
||||
/* Unversioned symbols defined in regular objects can be forced local
|
||||
by linker version script. A weak undefined symbol can fored local
|
||||
if it has non-default visibility or "-z nodynamic-undefined-weak"
|
||||
is used. */
|
||||
if (SYMBOL_REFERENCES_LOCAL (info, h)
|
||||
|| ((ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
|
||||
|| info->dynamic_undefined_weak == 0)
|
||||
&& h->root.type == bfd_link_hash_undefweak)
|
||||
|| ((h->def_regular || ELF_COMMON_DEF_P (h))
|
||||
&& h->versioned == unversioned
|
||||
&& info->version_info != NULL
|
||||
&& bfd_hide_sym_by_version (info->version_info,
|
||||
h->root.root.string)))
|
||||
{
|
||||
eh->local_ref = 2;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
eh->local_ref = 1;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Return the section that should be marked against GC for a given
|
||||
relocation. */
|
||||
|
||||
|
||||
@@ -45,6 +45,10 @@
|
||||
&& elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) == (id) \
|
||||
? ((struct elf_x86_link_hash_table *) ((p)->hash)) : NULL)
|
||||
|
||||
/* Will references to this symbol always be local in this object? */
|
||||
#define SYMBOL_REFERENCES_LOCAL_P(INFO, H) \
|
||||
_bfd_x86_elf_link_symbol_references_local ((INFO), (H))
|
||||
|
||||
/* Is a undefined weak symbol which is resolved to 0. Reference to an
|
||||
undefined weak symbol is resolved to 0 when building executable if
|
||||
it isn't dynamic and
|
||||
@@ -54,7 +58,7 @@
|
||||
*/
|
||||
#define UNDEFINED_WEAK_RESOLVED_TO_ZERO(INFO, ID, GOT_RELOC, EH) \
|
||||
((EH)->elf.root.type == bfd_link_hash_undefweak \
|
||||
&& ((EH)->elf.forced_local \
|
||||
&& (SYMBOL_REFERENCES_LOCAL_P ((INFO), &(EH)->elf) \
|
||||
|| (bfd_link_executable (INFO) \
|
||||
&& (elf_x86_hash_table ((INFO), (ID))->interp == NULL \
|
||||
|| !(GOT_RELOC) \
|
||||
@@ -98,6 +102,12 @@ struct elf_x86_link_hash_entry
|
||||
/* TRUE if symbol is defined as a protected symbol. */
|
||||
unsigned int def_protected : 1;
|
||||
|
||||
/* 0: Symbol references are unknown.
|
||||
1: Symbol references aren't local.
|
||||
2: Symbol references are local.
|
||||
*/
|
||||
unsigned int local_ref : 2;
|
||||
|
||||
/* Symbol is referenced by R_386_GOTOFF relocation. This is only used
|
||||
by i386. */
|
||||
unsigned int gotoff_ref : 1;
|
||||
@@ -320,8 +330,6 @@ struct elf_x86_link_hash_table
|
||||
|
||||
bfd_vma (*r_info) (bfd_vma, bfd_vma);
|
||||
bfd_vma (*r_sym) (bfd_vma);
|
||||
bfd_boolean (*convert_load) (bfd *, asection *,
|
||||
struct bfd_link_info *);
|
||||
bfd_boolean (*is_reloc_section) (const char *);
|
||||
enum elf_target_id target_id;
|
||||
unsigned int sizeof_reloc;
|
||||
@@ -405,12 +413,6 @@ struct elf_x86_plt
|
||||
&& elf_tdata (bfd) != NULL \
|
||||
&& elf_object_id (bfd) == (htab)->target_id)
|
||||
|
||||
extern bfd_boolean _bfd_i386_elf_convert_load
|
||||
(bfd *, asection *, struct bfd_link_info *);
|
||||
|
||||
extern bfd_boolean _bfd_x86_64_elf_convert_load
|
||||
(bfd *, asection *, struct bfd_link_info *);
|
||||
|
||||
extern bfd_boolean _bfd_x86_elf_mkobject
|
||||
(bfd *);
|
||||
|
||||
@@ -468,6 +470,9 @@ extern bfd_boolean _bfd_x86_elf_hash_symbol
|
||||
extern bfd_boolean _bfd_x86_elf_adjust_dynamic_symbol
|
||||
(struct bfd_link_info *, struct elf_link_hash_entry *);
|
||||
|
||||
extern bfd_boolean _bfd_x86_elf_link_symbol_references_local
|
||||
(struct bfd_link_info *, struct elf_link_hash_entry *);
|
||||
|
||||
extern asection * _bfd_x86_elf_gc_mark_hook
|
||||
(asection *, struct bfd_link_info *, Elf_Internal_Rela *,
|
||||
struct elf_link_hash_entry *, Elf_Internal_Sym *);
|
||||
|
||||
Reference in New Issue
Block a user