From: H.J. Lu Date: Sat, 9 Sep 2017 12:05:16 +0000 (-0700) Subject: x86: Properly handle __ehdr_start X-Git-Tag: users/ARM/embedded-binutils-master-2017q4~1110 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0a27fed72d4190cc70025c671b5133e6c58d9c09;p=external%2Fbinutils.git 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. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 99c4503..9549e84 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,19 @@ +2017-09-09 H.J. Lu + + 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. + 2017-09-08 H.J. Lu * elfxx-x86.h: Update comments. 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) diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index cab086d..4faa78b 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -1537,11 +1537,15 @@ elf_x86_64_convert_load_reloc (bfd *abfd, GOTPCRELX relocations since we need to modify REX byte. It is OK convert mov with R_X86_64_GOTPCREL to R_X86_64_PC32. */ + bfd_boolean local_ref; + struct elf_x86_link_hash_entry *eh = elf_x86_hash_entry (h); + + /* NB: Also set linker_def via SYMBOL_REFERENCES_LOCAL_P. */ + local_ref = SYMBOL_REFERENCES_LOCAL_P (link_info, h); if ((relocx || opcode == 0x8b) - && UNDEFINED_WEAK_RESOLVED_TO_ZERO (link_info, - X86_64_ELF_DATA, - TRUE, - elf_x86_hash_entry (h))) + && (h->root.type == bfd_link_hash_undefweak + && !eh->linker_def + && local_ref)) { if (opcode == 0xff) { @@ -1568,11 +1572,12 @@ elf_x86_64_convert_load_reloc (bfd *abfd, /* Avoid optimizing GOTPCREL relocations againt _DYNAMIC since ld.so may use its link-time address. */ else if (h->start_stop + || eh->linker_def || ((h->def_regular || h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) && h != htab->elf.hdynamic - && SYMBOL_REFERENCES_LOCAL_P (link_info, h))) + && local_ref)) { /* bfd_link_hash_new or bfd_link_hash_undefined is set by an assignment in a linker script in @@ -1580,6 +1585,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd, 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_new || h->root.type == bfd_link_hash_undefined 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 diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h index ccc72da..57f7862 100644 --- a/bfd/elfxx-x86.h +++ b/bfd/elfxx-x86.h @@ -108,6 +108,9 @@ struct elf_x86_link_hash_entry */ unsigned int local_ref : 2; + /* TRUE if symbol is defined by linker. */ + unsigned int linker_def : 1; + /* Terue if symbol is referenced by R_386_GOTOFF relocation. This is only used by i386. */ unsigned int gotoff_ref : 1; diff --git a/ld/ChangeLog b/ld/ChangeLog index 98318e9..7c17868 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,23 @@ +2017-09-09 H.J. Lu + + 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. + 2017-09-06 H.J. Lu * testsuite/ld-x86-64/pr19609-2a.d: Updated. diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp index bd15610..f691c32 100644 --- a/ld/testsuite/ld-i386/i386.exp +++ b/ld/testsuite/ld-i386/i386.exp @@ -440,6 +440,10 @@ run_dump_test "pie1" run_dump_test "pie1-nacl" run_dump_test "pr21884" run_dump_test "pr21884-nacl" +run_dump_test "pr22115-1a" +run_dump_test "pr22115-1b" +run_dump_test "pr22115-1c" +run_dump_test "pr22115-1d" if { !([istarget "i?86-*-linux*"] || [istarget "i?86-*-gnu*"] diff --git a/ld/testsuite/ld-i386/pr22115-1.s b/ld/testsuite/ld-i386/pr22115-1.s new file mode 100644 index 0000000..341eede --- /dev/null +++ b/ld/testsuite/ld-i386/pr22115-1.s @@ -0,0 +1,7 @@ + .text + .globl _start + .type _start, @function +_start: + movl __ehdr_start@GOT(%eax), %eax + .size _start, .-_start + .weak __ehdr_start diff --git a/ld/testsuite/ld-i386/pr22115-1a.d b/ld/testsuite/ld-i386/pr22115-1a.d new file mode 100644 index 0000000..4857952 --- /dev/null +++ b/ld/testsuite/ld-i386/pr22115-1a.d @@ -0,0 +1,13 @@ +#source: pr22115-1.s +#as: --32 -mrelax-relocations=yes +#ld: -pie -z text -m elf_i386 +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .text: + +[a-f0-9]+ <_start>: + +[a-f0-9]+: 8d 80 ([0-9a-f]{2} ){4} * lea -?0x[a-f0-9]+\(%eax\),%eax +#pass diff --git a/ld/testsuite/ld-i386/pr22115-1b.d b/ld/testsuite/ld-i386/pr22115-1b.d new file mode 100644 index 0000000..bb05851 --- /dev/null +++ b/ld/testsuite/ld-i386/pr22115-1b.d @@ -0,0 +1,6 @@ +#source: pr22115-1.s +#as: --32 -mrelax-relocations=yes +#ld: -pie -z text -m elf_i386 +#readelf: -r + +There are no relocations in this file. diff --git a/ld/testsuite/ld-i386/pr22115-1c.d b/ld/testsuite/ld-i386/pr22115-1c.d new file mode 100644 index 0000000..ce70539 --- /dev/null +++ b/ld/testsuite/ld-i386/pr22115-1c.d @@ -0,0 +1,13 @@ +#source: pr22115-1.s +#as: --32 -mrelax-relocations=yes +#ld: -pie -z text -m elf_i386 --no-dynamic-linker +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .text: + +[a-f0-9]+ <_start>: + +[a-f0-9]+: 8d 80 ([0-9a-f]{2} ){4} * lea -?0x[a-f0-9]+\(%eax\),%eax +#pass diff --git a/ld/testsuite/ld-i386/pr22115-1d.d b/ld/testsuite/ld-i386/pr22115-1d.d new file mode 100644 index 0000000..3a0b8e3 --- /dev/null +++ b/ld/testsuite/ld-i386/pr22115-1d.d @@ -0,0 +1,6 @@ +#source: pr22115-1.s +#as: --32 -mrelax-relocations=yes +#ld: -pie -z text -m elf_i386 --no-dynamic-linker +#readelf: -r + +There are no relocations in this file. diff --git a/ld/testsuite/ld-x86-64/pr22115-1.s b/ld/testsuite/ld-x86-64/pr22115-1.s new file mode 100644 index 0000000..8c01e50 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr22115-1.s @@ -0,0 +1,7 @@ + .text + .globl _start + .type _start, @function +_start: + movq __ehdr_start@GOTPCREL(%rip), %rax + .size _start, .-_start + .weak __ehdr_start diff --git a/ld/testsuite/ld-x86-64/pr22115-1a-x32.d b/ld/testsuite/ld-x86-64/pr22115-1a-x32.d new file mode 100644 index 0000000..8232589 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr22115-1a-x32.d @@ -0,0 +1,13 @@ +#source: pr22115-1.s +#as: --x32 -mrelax-relocations=yes +#ld: -pie -z text -m elf32_x86_64 +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .text: + +[a-f0-9]+ <_start>: + +[a-f0-9]+: 48 8d 05 ([0-9a-f]{2} ){4} * lea -?0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <__ehdr_start> +#pass diff --git a/ld/testsuite/ld-x86-64/pr22115-1a.d b/ld/testsuite/ld-x86-64/pr22115-1a.d new file mode 100644 index 0000000..43dc787 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr22115-1a.d @@ -0,0 +1,13 @@ +#source: pr22115-1.s +#as: --64 -mrelax-relocations=yes +#ld: -pie -z text -m elf_x86_64 +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .text: + +[a-f0-9]+ <_start>: + +[a-f0-9]+: 48 8d 05 ([0-9a-f]{2} ){4} * lea -?0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <__ehdr_start> +#pass diff --git a/ld/testsuite/ld-x86-64/pr22115-1b-x32.d b/ld/testsuite/ld-x86-64/pr22115-1b-x32.d new file mode 100644 index 0000000..949dc5f --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr22115-1b-x32.d @@ -0,0 +1,6 @@ +#source: pr22115-1.s +#as: --x32 -mrelax-relocations=yes +#ld: -pie -z text -m elf32_x86_64 +#readelf: -r + +There are no relocations in this file. diff --git a/ld/testsuite/ld-x86-64/pr22115-1b.d b/ld/testsuite/ld-x86-64/pr22115-1b.d new file mode 100644 index 0000000..f1aaf72 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr22115-1b.d @@ -0,0 +1,6 @@ +#source: pr22115-1.s +#as: --64 -mrelax-relocations=yes +#ld: -pie -z text -m elf_x86_64 +#readelf: -r + +There are no relocations in this file. diff --git a/ld/testsuite/ld-x86-64/pr22115-1c-x32.d b/ld/testsuite/ld-x86-64/pr22115-1c-x32.d new file mode 100644 index 0000000..384f8f4 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr22115-1c-x32.d @@ -0,0 +1,13 @@ +#source: pr22115-1.s +#as: --x32 -mrelax-relocations=yes +#ld: -pie -z text -m elf32_x86_64 --no-dynamic-linker +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .text: + +[a-f0-9]+ <_start>: + +[a-f0-9]+: 48 8d 05 ([0-9a-f]{2} ){4} * lea -?0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <__ehdr_start> +#pass diff --git a/ld/testsuite/ld-x86-64/pr22115-1c.d b/ld/testsuite/ld-x86-64/pr22115-1c.d new file mode 100644 index 0000000..ac147f8 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr22115-1c.d @@ -0,0 +1,13 @@ +#source: pr22115-1.s +#as: --64 -mrelax-relocations=yes +#ld: -pie -z text -m elf_x86_64 --no-dynamic-linker +#objdump: -dw + +.*: +file format .* + + +Disassembly of section .text: + +[a-f0-9]+ <_start>: + +[a-f0-9]+: 48 8d 05 ([0-9a-f]{2} ){4} * lea -?0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <__ehdr_start> +#pass diff --git a/ld/testsuite/ld-x86-64/pr22115-1d-x32.d b/ld/testsuite/ld-x86-64/pr22115-1d-x32.d new file mode 100644 index 0000000..755c827 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr22115-1d-x32.d @@ -0,0 +1,6 @@ +#source: pr22115-1.s +#as: --x32 -mrelax-relocations=yes +#ld: -pie -z text -m elf32_x86_64 --no-dynamic-linker +#readelf: -r + +There are no relocations in this file. diff --git a/ld/testsuite/ld-x86-64/pr22115-1d.d b/ld/testsuite/ld-x86-64/pr22115-1d.d new file mode 100644 index 0000000..2cb1c65 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr22115-1d.d @@ -0,0 +1,6 @@ +#source: pr22115-1.s +#as: --64 -mrelax-relocations=yes +#ld: -pie -z text -m elf_x86_64 --no-dynamic-linker +#readelf: -r + +There are no relocations in this file. diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index 46b3ec7..edf8896 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -369,6 +369,14 @@ run_dump_test "property-x86-shstk5-x32" run_dump_test "pr21884" run_dump_test "pr21884-nacl" run_dump_test "pr22071" +run_dump_test "pr22115-1a" +run_dump_test "pr22115-1a-x32" +run_dump_test "pr22115-1b" +run_dump_test "pr22115-1b-x32" +run_dump_test "pr22115-1c" +run_dump_test "pr22115-1c-x32" +run_dump_test "pr22115-1d" +run_dump_test "pr22115-1d-x32" if { ![istarget "x86_64-*-linux*"] && ![istarget "x86_64-*-nacl*"]} { return