diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2017-09-09 05:05:16 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2017-09-09 05:05:29 -0700 |
commit | 0a27fed72d4190cc70025c671b5133e6c58d9c09 (patch) | |
tree | 3d9d0bc8ad47eba702a00a23ebd00c8e64da165c /bfd/elfxx-x86.c | |
parent | 90d499086b5d35ac5b58c925f23513f6af2c3639 (diff) | |
download | gdb-0a27fed72d4190cc70025c671b5133e6c58d9c09.zip gdb-0a27fed72d4190cc70025c671b5133e6c58d9c09.tar.gz gdb-0a27fed72d4190cc70025c671b5133e6c58d9c09.tar.bz2 |
x86: Properly handle __ehdr_start
After _bfd_i386_elf_convert_load and _bfd_x86_64_elf_convert_load are
removed, elf_i386_convert_load_reloc and elf_x86_64_convert_load_reloc
see __ehdr_start as an undefined symbol when they are called from
check_relocs to convert GOT relocations against local symbols. But
__ehdr_start will be defined as a hidden symbol by linker at the later
stage if it is referenced. This patch marks __ehdr_start as a defined
local symbol at the start of check_relocs if it is referenced and not
defined.
bfd/
PR ld/22115
* elf32-i386.c (elf_i386_convert_load_reloc): Check linker_def.
Don't use UNDEFINED_WEAK_RESOLVED_TO_ZERO.
* elf64-x86-64.c (elf_x86_64_convert_load_reloc): Check
linker_def. Don't use UNDEFINED_WEAK_RESOLVED_TO_ZERO.
* elfxx-x86.c (_bfd_x86_elf_link_check_relocs): Set local_ref
and linker_def on __ehdr_start if it is referenced and not
defined.
(_bfd_x86_elf_link_symbol_references_local): Also set local_ref
and return TRUE when building executable, if a symbol has
non-GOT/non-PLT relocations in text section or there is no
dynamic linker.
* elfxx-x86.h (elf_x86_link_hash_entry): Add linker_def.
ld/
PR ld/22115
* ld-i386/i386.exp: Run PR ld/22115 tests,
* ld/testsuite/ld-x86-64/x86-64.exp: Likewise.
* testsuite/ld-i386/pr22115-1.s: New file.
* testsuite/ld-i386/pr22115-1a.d: Likewise.
* testsuite/ld-i386/pr22115-1b.d: Likewise.
* testsuite/ld-i386/pr22115-1c.d: Likewise.
* testsuite/ld-i386/pr22115-1d.d: Likewise.
* testsuite/ld-x86-64/pr22115-1.s: Likewise.
* testsuite/ld-x86-64/pr22115-1a-x32.d: Likewise.
* testsuite/ld-x86-64/pr22115-1a.d: Likewise.
* testsuite/ld-x86-64/pr22115-1b-x32.d: Likewise.
* testsuite/ld-x86-64/pr22115-1b.d: Likewise.
* testsuite/ld-x86-64/pr22115-1c-x32.d: Likewise.
* testsuite/ld-x86-64/pr22115-1c.d: Likewise.
* testsuite/ld-x86-64/pr22115-1d-x32.d: Likewise.
* testsuite/ld-x86-64/pr22115-1d.d: Likewise.
Diffstat (limited to 'bfd/elfxx-x86.c')
-rw-r--r-- | bfd/elfxx-x86.c | 45 |
1 files changed, 34 insertions, 11 deletions
diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index 86e26f9..e056c3c 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -845,12 +845,28 @@ _bfd_x86_elf_link_check_relocs (bfd *abfd, struct bfd_link_info *info) htab = elf_x86_hash_table (info, bed->target_id); if (htab) { - struct elf_link_hash_entry *h - = elf_link_hash_lookup (elf_hash_table (info), + struct elf_link_hash_entry *h; + + h = elf_link_hash_lookup (elf_hash_table (info), htab->tls_get_addr, FALSE, FALSE, FALSE); if (h != NULL) - ((struct elf_x86_link_hash_entry *) h)->tls_get_addr = 1; + elf_x86_hash_entry (h)->tls_get_addr = 1; + + /* "__ehdr_start" will be defined by linker as a hidden symbol + later if it is referenced and not defined. */ + h = elf_link_hash_lookup (elf_hash_table (info), + "__ehdr_start", + FALSE, FALSE, FALSE); + if (h != NULL + && (h->root.type == bfd_link_hash_new + || h->root.type == bfd_link_hash_undefined + || h->root.type == bfd_link_hash_undefweak + || h->root.type == bfd_link_hash_common)) + { + elf_x86_hash_entry (h)->local_ref = 2; + elf_x86_hash_entry (h)->linker_def = 1; + } } } @@ -1671,8 +1687,9 @@ 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; + struct elf_x86_link_hash_entry *eh = elf_x86_hash_entry (h); + struct elf_x86_link_hash_table *htab + = (struct elf_x86_link_hash_table *) info->hash; if (eh->local_ref > 1) return TRUE; @@ -1681,13 +1698,19 @@ _bfd_x86_elf_link_symbol_references_local (struct bfd_link_info *info, 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. */ + by linker version script. A weak undefined symbol is forced local + if + 1. It has non-default visibility. Or + 2. When building executable, it has non-GOT/non-PLT relocations + in text section or there is no dynamic linker. Or + 3. 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->root.type == bfd_link_hash_undefweak + && (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT + || (bfd_link_executable (info) + && (htab->interp == NULL || eh->has_non_got_reloc)) + || info->dynamic_undefined_weak == 0)) || ((h->def_regular || ELF_COMMON_DEF_P (h)) && h->versioned == unversioned && info->version_info != NULL |