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/elf32-i386.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/elf32-i386.c')
-rw-r--r-- | bfd/elf32-i386.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index dcf07d9..0100662 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -1229,6 +1229,8 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, unsigned int r_type; unsigned int r_symndx; bfd_vma roff = irel->r_offset; + bfd_boolean local_ref; + struct elf_x86_link_hash_entry *eh; if (roff < 2) return TRUE; @@ -1276,6 +1278,8 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, register. */ to_reloc_32 = !is_pic || baseless; + eh = elf_x86_hash_entry (h); + /* Try to convert R_386_GOT32X. Get the symbol referred to by the reloc. */ if (h == NULL) @@ -1290,10 +1294,14 @@ elf_i386_convert_load_reloc (bfd *abfd, Elf_Internal_Shdr *symtab_hdr, goto convert_load; } + /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P. */ + local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h); + /* Undefined weak symbol is only bound locally in executable and its reference is resolved as 0. */ - if (UNDEFINED_WEAK_RESOLVED_TO_ZERO (link_info, I386_ELF_DATA, TRUE, - elf_x86_hash_entry (h))) + if (h->root.type == bfd_link_hash_undefweak + && !eh->linker_def + && local_ref) { if (opcode == 0xff) { @@ -1316,16 +1324,13 @@ 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_P (link_info, h)) + && local_ref) { /* The function is locally defined. */ convert_branch: /* Convert R_386_GOT32X to R_386_PC32. */ if (modrm == 0x15 || (modrm & 0xf8) == 0x90) { - struct elf_x86_link_hash_entry *eh - = (struct elf_x86_link_hash_entry *) h; - /* Convert to "nop call foo". ADDR_PREFIX_OPCODE is a nop prefix. */ modrm = 0xe8; @@ -1381,10 +1386,11 @@ convert_branch: bfd_elf_record_link_assignment. start_stop is set on __start_SECNAME/__stop_SECNAME which mark section SECNAME. */ if (h->start_stop + || eh->linker_def || ((h->def_regular || h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) - && SYMBOL_REFERENCES_LOCAL_P (link_info, h))) + && local_ref)) { convert_load: if (opcode == 0x8b) |