From 83924b3846361f2f76f9a6e7b5afa01c0eebbd4f Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Tue, 5 Feb 2019 18:45:23 -0800 Subject: [PATCH] x86-64: Restore PIC check for PCREL reloc against protected symbol commit bd7ab16b4537788ad53521c45469a1bdae84ad4a Author: H.J. Lu Date: Tue Feb 13 07:34:22 2018 -0800 x86-64: Generate branch with PLT32 relocation removed check R_X86_64_PC32 relocation against protected symbols in shared objects. Since elf_x86_64_check_relocs is called after we have seen all input files, we can check for PC-relative relocations in elf_x86_64_check_relocs. We should not allow PC-relative relocations against protected symbols since address of protected function and location of protected data may not be in the shared object. bfd/ PR ld/24151 * elf64-x86-64.c (elf_x86_64_need_pic): Check SYMBOL_DEFINED_NON_SHARED_P instead of def_regular. (elf_x86_64_relocate_section): Move PIC check for PC-relative relocations to ... (elf_x86_64_check_relocs): Here. (elf_x86_64_finish_dynamic_symbol): Use SYMBOL_DEFINED_NON_SHARED_P to check if a symbol is defined in a non-shared object. * elfxx-x86.h (SYMBOL_DEFINED_NON_SHARED_P): New. ld/ PR ld/24151 * testsuite/ld-x86-64/pr24151a-x32.d: New file. * testsuite/ld-x86-64/pr24151a.d: Likewise. * testsuite/ld-x86-64/pr24151a.s: Likewise. * testsuite/ld-x86-64/x86-64.exp: Run pr24151a and pr24151a-x32. --- bfd/ChangeLog | 12 +++ bfd/elf64-x86-64.c | 133 +++++++++++++++----------- bfd/elfxx-x86.h | 7 ++ ld/ChangeLog | 8 ++ ld/testsuite/ld-x86-64/pr24151a-x32.d | 4 + ld/testsuite/ld-x86-64/pr24151a.d | 3 + ld/testsuite/ld-x86-64/pr24151a.s | 9 ++ ld/testsuite/ld-x86-64/x86-64.exp | 2 + 8 files changed, 124 insertions(+), 54 deletions(-) create mode 100644 ld/testsuite/ld-x86-64/pr24151a-x32.d create mode 100644 ld/testsuite/ld-x86-64/pr24151a.d create mode 100644 ld/testsuite/ld-x86-64/pr24151a.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 5547cd26b9b..22eab1effb6 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,15 @@ +2019-02-05 H.J. Lu + + PR ld/24151 + * elf64-x86-64.c (elf_x86_64_need_pic): Check + SYMBOL_DEFINED_NON_SHARED_P instead of def_regular. + (elf_x86_64_relocate_section): Move PIC check for PC-relative + relocations to ... + (elf_x86_64_check_relocs): Here. + (elf_x86_64_finish_dynamic_symbol): Use SYMBOL_DEFINED_NON_SHARED_P + to check if a symbol is defined in a non-shared object. + * elfxx-x86.h (SYMBOL_DEFINED_NON_SHARED_P): New. + 2019-01-21 Sergio Durigan Junior * elf32-arm.c (elf32_arm_final_link_relocate): Use 'llabs' instead diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index c7d8bca7102..6a4b366fdda 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -1426,7 +1426,7 @@ elf_x86_64_need_pic (struct bfd_link_info *info, break; } - if (!h->def_regular && !h->def_dynamic) + if (!SYMBOL_DEFINED_NON_SHARED_P (h) && !h->def_dynamic) und = _("undefined "); } else @@ -1855,6 +1855,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, const char *name; bfd_boolean size_reloc; bfd_boolean converted_reloc; + bfd_boolean do_check_pic; r_symndx = htab->r_sym (rel->r_info); r_type = ELF32_R_TYPE (rel->r_info); @@ -2130,6 +2131,13 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, size_reloc = TRUE; goto do_size; + case R_X86_64_PC8: + case R_X86_64_PC16: + case R_X86_64_PC32: + case R_X86_64_PC32_BND: + do_check_pic = TRUE; + goto check_pic; + case R_X86_64_32: if (!ABI_64_P (abfd)) goto pointer; @@ -2153,13 +2161,11 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, &x86_64_elf_howto_table[r_type]); /* Fall through. */ - case R_X86_64_PC8: - case R_X86_64_PC16: - case R_X86_64_PC32: - case R_X86_64_PC32_BND: case R_X86_64_PC64: case R_X86_64_64: pointer: + do_check_pic = FALSE; +check_pic: if (eh != NULL && (sec->flags & SEC_CODE) != 0) eh->zero_undefweak |= 0x2; /* We are called after all symbols have been resolved. Only @@ -2223,6 +2229,67 @@ pointer: } } + if (do_check_pic) + { + /* Don't complain about -fPIC if the symbol is undefined + when building executable unless it is unresolved weak + symbol, references a dynamic definition in PIE or + -z nocopyreloc is used. */ + bfd_boolean no_copyreloc_p + = (info->nocopyreloc + || (h != NULL + && eh->def_protected + && elf_has_no_copy_on_protected (h->root.u.def.section->owner))); + if ((sec->flags & SEC_ALLOC) != 0 + && (sec->flags & SEC_READONLY) != 0 + && h != NULL + && ((bfd_link_executable (info) + && ((h->root.type == bfd_link_hash_undefweak + && (eh == NULL + || !UNDEFINED_WEAK_RESOLVED_TO_ZERO (info, + eh))) + || (bfd_link_pie (info) + && !SYMBOL_DEFINED_NON_SHARED_P (h) + && h->def_dynamic) + || (no_copyreloc_p + && h->def_dynamic + && !(h->root.u.def.section->flags & SEC_CODE)))) + || bfd_link_dll (info))) + { + bfd_boolean fail = FALSE; + if (SYMBOL_REFERENCES_LOCAL_P (info, h)) + { + /* Symbol is referenced locally. Make sure it is + defined locally. */ + fail = !SYMBOL_DEFINED_NON_SHARED_P (h); + } + else if (bfd_link_pie (info)) + { + /* We can only use PC-relative relocations in PIE + from non-code sections. */ + if (h->type == STT_FUNC + && (sec->flags & SEC_CODE) != 0) + fail = TRUE; + } + else if (no_copyreloc_p || bfd_link_dll (info)) + { + /* Symbol doesn't need copy reloc and isn't + referenced locally. Don't allow PC-relative + relocations against default and protected + symbols since address of protected function + and location of protected data may not be in + the shared object. */ + fail = (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT + || ELF_ST_VISIBILITY (h->other) == STV_PROTECTED); + } + + if (fail) + return elf_x86_64_need_pic (info, abfd, sec, h, + symtab_hdr, isym, + &x86_64_elf_howto_table[r_type]); + } + } + size_reloc = FALSE; do_size: if (NEED_DYNAMIC_RELOCATION_P (info, TRUE, h, sec, r_type, @@ -3065,56 +3132,14 @@ use_plt: case R_X86_64_PC16: case R_X86_64_PC32: case R_X86_64_PC32_BND: - /* Don't complain about -fPIC if the symbol is undefined when - building executable unless it is unresolved weak symbol, - references a dynamic definition in PIE or -z nocopyreloc - is used. */ - if ((input_section->flags & SEC_ALLOC) != 0 - && (input_section->flags & SEC_READONLY) != 0 - && h != NULL - && ((bfd_link_executable (info) - && ((h->root.type == bfd_link_hash_undefweak - && !resolved_to_zero) - || (bfd_link_pie (info) - && !h->def_regular - && h->def_dynamic) - || ((info->nocopyreloc - || (eh->def_protected - && elf_has_no_copy_on_protected (h->root.u.def.section->owner))) - && h->def_dynamic - && !(h->root.u.def.section->flags & SEC_CODE)))) - || bfd_link_dll (info))) - { - bfd_boolean fail = FALSE; - if (SYMBOL_REFERENCES_LOCAL_P (info, h)) - { - /* Symbol is referenced locally. Make sure it is - defined locally. */ - fail = !(h->def_regular || ELF_COMMON_DEF_P (h)); - } - else if (!(bfd_link_pie (info) - && (h->needs_copy || eh->needs_copy))) - { - /* Symbol doesn't need copy reloc and isn't referenced - locally. Address of protected function may not be - reachable at run-time. */ - fail = (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT - || (ELF_ST_VISIBILITY (h->other) == STV_PROTECTED - && h->type == STT_FUNC)); - } - - if (fail) - return elf_x86_64_need_pic (info, input_bfd, input_section, - h, NULL, NULL, howto); - } /* Since x86-64 has PC-relative PLT, we can use PLT in PIE as function address. */ - else if (h != NULL - && (input_section->flags & SEC_CODE) == 0 - && bfd_link_pie (info) - && h->type == STT_FUNC - && !h->def_regular - && h->def_dynamic) + if (h != NULL + && (input_section->flags & SEC_CODE) == 0 + && bfd_link_pie (info) + && h->type == STT_FUNC + && !h->def_regular + && h->def_dynamic) goto use_plt; /* Fall through. */ @@ -4271,7 +4296,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, else if (bfd_link_pic (info) && SYMBOL_REFERENCES_LOCAL_P (info, h)) { - if (!(h->def_regular || ELF_COMMON_DEF_P (h))) + if (!SYMBOL_DEFINED_NON_SHARED_P (h)) return FALSE; BFD_ASSERT((h->got.offset & 1) != 0); rela.r_info = htab->r_info (0, R_X86_64_RELATIVE); diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h index dce24dc1069..28d540b83b3 100644 --- a/bfd/elfxx-x86.h +++ b/bfd/elfxx-x86.h @@ -161,6 +161,13 @@ || (ELF_ST_VISIBILITY ((H)->other) \ && (H)->root.type == bfd_link_hash_undefweak)) +/* TRUE if this symbol isn't defined by a shared object. */ +#define SYMBOL_DEFINED_NON_SHARED_P(H) \ + ((H)->def_regular \ + || (H)->root.linker_def \ + || (H)->root.ldscript_def \ + || ELF_COMMON_DEF_P (H)) + /* TRUE if relative relocation should be generated. GOT reference to global symbol in PIC will lead to dynamic symbol. It becomes a problem when "time" or "times" is defined as a variable in an diff --git a/ld/ChangeLog b/ld/ChangeLog index 5713b0020c6..262f7bf5358 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,11 @@ +2019-02-05 H.J. Lu + + PR ld/24151 + * testsuite/ld-x86-64/pr24151a-x32.d: New file. + * testsuite/ld-x86-64/pr24151a.d: Likewise. + * testsuite/ld-x86-64/pr24151a.s: Likewise. + * testsuite/ld-x86-64/x86-64.exp: Run pr24151a and pr24151a-x32. + 2019-01-31 Alan Modra * NEWS: Mention -t change. diff --git a/ld/testsuite/ld-x86-64/pr24151a-x32.d b/ld/testsuite/ld-x86-64/pr24151a-x32.d new file mode 100644 index 00000000000..130611ddf49 --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr24151a-x32.d @@ -0,0 +1,4 @@ +#source: pr24151a.s +#as: --x32 +#ld: -shared -melf32_x86_64 +#error: .*relocation R_X86_64_PC32 against protected symbol `foo' can not be used when making a shared object diff --git a/ld/testsuite/ld-x86-64/pr24151a.d b/ld/testsuite/ld-x86-64/pr24151a.d new file mode 100644 index 00000000000..783b85a1a6f --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr24151a.d @@ -0,0 +1,3 @@ +#as: --64 +#ld: -shared -melf_x86_64 +#error: .*relocation R_X86_64_PC32 against protected symbol `foo' can not be used when making a shared object diff --git a/ld/testsuite/ld-x86-64/pr24151a.s b/ld/testsuite/ld-x86-64/pr24151a.s new file mode 100644 index 00000000000..e4ec7c8ce4b --- /dev/null +++ b/ld/testsuite/ld-x86-64/pr24151a.s @@ -0,0 +1,9 @@ + .text + .globl bar + .type bar,@function +bar: + movl $30, foo(%rip) + .size bar, .-bar + .protected foo + .type foo,@object + .comm foo,4,4 diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index 86b163fc7a2..5eb556515fa 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -424,6 +424,8 @@ run_dump_test "pr23486d-x32" run_dump_test "pr23854" run_dump_test "pr23930" run_dump_test "pr23930-x32" +run_dump_test "pr24151a" +run_dump_test "pr24151a-x32" if { ![istarget "x86_64-*-linux*"] && ![istarget "x86_64-*-nacl*"]} { return -- 2.30.2