From 6999821f8b1e898f02d0c1196c4c83337c3b565e Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Thu, 7 Sep 2017 04:03:15 -0700 Subject: [PATCH] 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. --- bfd/ChangeLog | 39 ++++++++++++ bfd/elf32-i386.c | 168 +++++++--------------------------------------------- bfd/elf64-x86-64.c | 170 ++++++++--------------------------------------------- bfd/elfxx-x86.c | 44 ++++++++++++-- bfd/elfxx-x86.h | 23 +++++--- 5 files changed, 137 insertions(+), 307 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9622383..a8db91a 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,42 @@ +2017-09-07 H.J. Lu + + * 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 * elf64-x86-64.c (R_X86_64_converted_reloc_bit): New. diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index 78a5dc4..cee5182 100644 --- a/bfd/elf32-i386.c +++ b/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); diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 8f1ac1a..a2a4be8 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -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; diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index a7e9eda..4f6b09e 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -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. */ diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h index 9c0dcbbe..5d0a28a 100644 --- a/bfd/elfxx-x86.h +++ b/bfd/elfxx-x86.h @@ -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 *); -- 2.7.4