From 73784fa565bd66f1ac165816c03e5217b7d67bbc Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 23 Aug 2017 10:15:39 -0700 Subject: [PATCH] x86: Clear extern_protected_data for GNU_PROPERTY_NO_COPY_ON_PROTECTED When GNU_PROPERTY_NO_COPY_ON_PROTECTED is set, it indicates that there are no copy relocations against protected data symbols. When linker sees GNU_PROPERTY_NO_COPY_ON_PROTECTED on any input relocatable file, it sets extern_protected_data to FALSE. bfd/ * elf32-i386.c (elf_i386_link_setup_gnu_properties): Set extern_protected_data to FALSE if GNU_PROPERTY_NO_COPY_ON_PROTECTED is set on any input relocatable file. * elf64-x86-64.c (elf_x86_64_link_setup_gnu_properties): Likewise. ld/ * testsuite/ld-i386/i386.exp: Run protected7. * testsuite/ld-i386/protected7.d: New file. * testsuite/ld-i386/protected7.s: Likewise. * testsuite/ld-x86-64/protected8.d: Likewise. * testsuite/ld-x86-64/protected8.s: Likewise. * testsuite/ld-x86-64/x86-64.exp: Run protected8. --- bfd/ChangeLog | 7 ++ bfd/elf32-i386.c | 116 ++++++++++++++++------------ bfd/elf64-x86-64.c | 114 ++++++++++++++++----------- ld/ChangeLog | 9 +++ ld/testsuite/ld-i386/i386.exp | 1 + ld/testsuite/ld-i386/protected7.d | 13 ++++ ld/testsuite/ld-i386/protected7.s | 31 ++++++++ ld/testsuite/ld-x86-64/protected8.d | 13 ++++ ld/testsuite/ld-x86-64/protected8.s | 31 ++++++++ ld/testsuite/ld-x86-64/x86-64.exp | 1 + 10 files changed, 241 insertions(+), 95 deletions(-) create mode 100644 ld/testsuite/ld-i386/protected7.d create mode 100644 ld/testsuite/ld-i386/protected7.s create mode 100644 ld/testsuite/ld-x86-64/protected8.d create mode 100644 ld/testsuite/ld-x86-64/protected8.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 3d09aa4c94f..c7ce75d379b 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2017-08-23 H.J. Lu + + * elf32-i386.c (elf_i386_link_setup_gnu_properties): Set + extern_protected_data to FALSE if GNU_PROPERTY_NO_COPY_ON_PROTECTED + is set on any input relocatable file. + * elf64-x86-64.c (elf_x86_64_link_setup_gnu_properties): Likewise. + 2017-08-23 Alan Modra PR 21988 diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c index d5477c42153..1009c17ff21 100644 --- a/bfd/elf32-i386.c +++ b/bfd/elf32-i386.c @@ -6780,66 +6780,90 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info) unsigned int plt_alignment, features; struct elf_i386_link_hash_table *htab; bfd *pbfd; + bfd *ebfd = NULL; + elf_property *prop; features = 0; if (info->ibt) features = GNU_PROPERTY_X86_FEATURE_1_IBT; if (info->shstk) features |= GNU_PROPERTY_X86_FEATURE_1_SHSTK; - if (features) - { - /* Turn on GNU_PROPERTY_X86_FEATURE_1_IBT and - GNU_PROPERTY_X86_FEATURE_1_SHSTK. */ - bfd *ebfd = NULL; - elf_property *prop; - - for (pbfd = info->input_bfds; - pbfd != NULL; - pbfd = pbfd->link.next) - if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour - && bfd_count_sections (pbfd) != 0) - { - ebfd = pbfd; - if (elf_properties (pbfd) != NULL) - { - /* Find a normal input file with GNU property note. */ - prop = _bfd_elf_get_property (pbfd, - GNU_PROPERTY_X86_FEATURE_1_AND, - 4); - /* Add GNU_PROPERTY_X86_FEATURE_1_IBT and - GNU_PROPERTY_X86_FEATURE_1_SHSTK. */ - prop->u.number |= features; - prop->pr_kind = property_number; - break; - } - } + /* Find a normal input file with GNU property note. */ + for (pbfd = info->input_bfds; + pbfd != NULL; + pbfd = pbfd->link.next) + if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour + && bfd_count_sections (pbfd) != 0) + { + ebfd = pbfd; - if (pbfd == NULL && ebfd != NULL) + if (elf_properties (pbfd) != NULL) + break; + } + + if (ebfd != NULL) + { + if (features) { - /* Create GNU_PROPERTY_X86_FEATURE_1_IBT if needed. */ + /* If features is set, add GNU_PROPERTY_X86_FEATURE_1_IBT and + GNU_PROPERTY_X86_FEATURE_1_SHSTK. */ prop = _bfd_elf_get_property (ebfd, GNU_PROPERTY_X86_FEATURE_1_AND, 4); - prop->u.number = features; + prop->u.number |= features; prop->pr_kind = property_number; - sec = bfd_make_section_with_flags (ebfd, - NOTE_GNU_PROPERTY_SECTION_NAME, - (SEC_ALLOC - | SEC_LOAD - | SEC_IN_MEMORY - | SEC_READONLY - | SEC_HAS_CONTENTS - | SEC_DATA)); - if (sec == NULL) - info->callbacks->einfo (_("%F: failed to create GNU property section\n")); + /* Create the GNU property note section if needed. */ + if (pbfd == NULL) + { + sec = bfd_make_section_with_flags (ebfd, + NOTE_GNU_PROPERTY_SECTION_NAME, + (SEC_ALLOC + | SEC_LOAD + | SEC_IN_MEMORY + | SEC_READONLY + | SEC_HAS_CONTENTS + | SEC_DATA)); + if (sec == NULL) + info->callbacks->einfo (_("%F: failed to create GNU property section\n")); - if (!bfd_set_section_alignment (ebfd, sec, 2)) - goto error_alignment; + if (!bfd_set_section_alignment (ebfd, sec, 2)) + { +error_alignment: + info->callbacks->einfo (_("%F%A: failed to align section\n"), + sec); + } - elf_section_type (sec) = SHT_NOTE; + elf_section_type (sec) = SHT_NOTE; + } } + + /* Check GNU_PROPERTY_NO_COPY_ON_PROTECTED. */ + for (; pbfd != NULL; pbfd = pbfd->link.next) + if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour + && (pbfd->flags + & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0) + { + elf_property_list *p; + + /* The property list is sorted in order of type. */ + for (p = elf_properties (pbfd); p != NULL; p = p->next) + { + if (GNU_PROPERTY_NO_COPY_ON_PROTECTED + == p->property.pr_type) + { + /* Clear extern_protected_data if + GNU_PROPERTY_NO_COPY_ON_PROTECTED is + set on any input relocatable file. */ + info->extern_protected_data = FALSE; + break; + } + else if (GNU_PROPERTY_NO_COPY_ON_PROTECTED + < p->property.pr_type) + break; + } + } } pbfd = _bfd_elf_link_setup_gnu_properties (info); @@ -7116,11 +7140,7 @@ elf_i386_link_setup_gnu_properties (struct bfd_link_info *info) if (sec != NULL && !bfd_set_section_alignment (sec->owner, sec, plt_alignment)) - { -error_alignment: - info->callbacks->einfo (_("%F%A: failed to align section\n"), - sec); - } + goto error_alignment; } return pbfd; diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 8a6bd6285c8..244db80ed61 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -7302,71 +7302,91 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info) unsigned int plt_alignment, features; struct elf_x86_64_link_hash_table *htab; bfd *pbfd; + bfd *ebfd = NULL; + elf_property *prop; features = 0; if (info->ibt) features = GNU_PROPERTY_X86_FEATURE_1_IBT; if (info->shstk) features |= GNU_PROPERTY_X86_FEATURE_1_SHSTK; - if (features) - { - /* Turn on GNU_PROPERTY_X86_FEATURE_1_IBT and - GNU_PROPERTY_X86_FEATURE_1_SHSTK. */ - bfd *ebfd = NULL; - elf_property *prop; - - for (pbfd = info->input_bfds; - pbfd != NULL; - pbfd = pbfd->link.next) - if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour - && bfd_count_sections (pbfd) != 0) - { - ebfd = pbfd; - if (elf_properties (pbfd) != NULL) - { - /* Find a normal input file with GNU property note. */ - prop = _bfd_elf_get_property (pbfd, - GNU_PROPERTY_X86_FEATURE_1_AND, - 4); - /* Add GNU_PROPERTY_X86_FEATURE_1_IBT and - GNU_PROPERTY_X86_FEATURE_1_SHSTK. */ - prop->u.number |= features; - prop->pr_kind = property_number; - break; - } - } + /* Find a normal input file with GNU property note. */ + for (pbfd = info->input_bfds; + pbfd != NULL; + pbfd = pbfd->link.next) + if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour + && bfd_count_sections (pbfd) != 0) + { + ebfd = pbfd; + + if (elf_properties (pbfd) != NULL) + break; + } - if (pbfd == NULL && ebfd != NULL) + if (ebfd != NULL) + { + if (features) { - /* Create GNU_PROPERTY_X86_FEATURE_1_IBT if needed. */ + /* If features is set, add GNU_PROPERTY_X86_FEATURE_1_IBT and + GNU_PROPERTY_X86_FEATURE_1_SHSTK. */ prop = _bfd_elf_get_property (ebfd, GNU_PROPERTY_X86_FEATURE_1_AND, 4); - prop->u.number = features; + prop->u.number |= features; prop->pr_kind = property_number; - sec = bfd_make_section_with_flags (ebfd, - NOTE_GNU_PROPERTY_SECTION_NAME, - (SEC_ALLOC - | SEC_LOAD - | SEC_IN_MEMORY - | SEC_READONLY - | SEC_HAS_CONTENTS - | SEC_DATA)); - if (sec == NULL) - info->callbacks->einfo (_("%F: failed to create GNU property section\n")); - - if (!bfd_set_section_alignment (ebfd, sec, - ABI_64_P (ebfd) ? 3 : 2)) + /* Create the GNU property note section if needed. */ + if (pbfd == NULL) { + sec = bfd_make_section_with_flags (ebfd, + NOTE_GNU_PROPERTY_SECTION_NAME, + (SEC_ALLOC + | SEC_LOAD + | SEC_IN_MEMORY + | SEC_READONLY + | SEC_HAS_CONTENTS + | SEC_DATA)); + if (sec == NULL) + info->callbacks->einfo (_("%F: failed to create GNU property section\n")); + + if (!bfd_set_section_alignment (ebfd, sec, + ABI_64_P (ebfd) ? 3 : 2)) + { error_alignment: - info->callbacks->einfo (_("%F%A: failed to align section\n"), - sec); - } + info->callbacks->einfo (_("%F%A: failed to align section\n"), + sec); + } - elf_section_type (sec) = SHT_NOTE; + elf_section_type (sec) = SHT_NOTE; + } } + + /* Check GNU_PROPERTY_NO_COPY_ON_PROTECTED. */ + for (; pbfd != NULL; pbfd = pbfd->link.next) + if (bfd_get_flavour (pbfd) == bfd_target_elf_flavour + && (pbfd->flags + & (DYNAMIC | BFD_LINKER_CREATED | BFD_PLUGIN)) == 0) + { + elf_property_list *p; + + /* The property list is sorted in order of type. */ + for (p = elf_properties (pbfd); p != NULL; p = p->next) + { + if (GNU_PROPERTY_NO_COPY_ON_PROTECTED + == p->property.pr_type) + { + /* Clear extern_protected_data if + GNU_PROPERTY_NO_COPY_ON_PROTECTED is + set on any input relocatable file. */ + info->extern_protected_data = FALSE; + break; + } + else if (GNU_PROPERTY_NO_COPY_ON_PROTECTED + < p->property.pr_type) + break; + } + } } pbfd = _bfd_elf_link_setup_gnu_properties (info); diff --git a/ld/ChangeLog b/ld/ChangeLog index 0859f70cbe8..c499de7cd86 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,12 @@ +2017-08-23 H.J. Lu + + * testsuite/ld-i386/i386.exp: Run protected7. + * testsuite/ld-i386/protected7.d: New file. + * testsuite/ld-i386/protected7.s: Likewise. + * testsuite/ld-x86-64/protected8.d: Likewise. + * testsuite/ld-x86-64/protected8.s: Likewise. + * testsuite/ld-x86-64/x86-64.exp: Run protected8. + 2017-08-23 Alan Modra * testsuite/ld-gc/pr19161.d: Don't xfail hppa. diff --git a/ld/testsuite/ld-i386/i386.exp b/ld/testsuite/ld-i386/i386.exp index 27d622eab42..3c5de021b2b 100644 --- a/ld/testsuite/ld-i386/i386.exp +++ b/ld/testsuite/ld-i386/i386.exp @@ -308,6 +308,7 @@ run_dump_test "protected4" run_dump_test "protected5" run_dump_test "protected6a" run_dump_test "protected6b" +run_dump_test "protected7" run_dump_test "tlspie1" run_dump_test "tlspie2" run_dump_test "tlspie3a" diff --git a/ld/testsuite/ld-i386/protected7.d b/ld/testsuite/ld-i386/protected7.d new file mode 100644 index 00000000000..aafa2d81b35 --- /dev/null +++ b/ld/testsuite/ld-i386/protected7.d @@ -0,0 +1,13 @@ +#as: --32 +#ld: -shared -melf_i386 +#objdump: -drw + +.*: +file format .* + + +Disassembly of section .text: + +0+[a-f0-9]+ : +[ ]*[a-f0-9]+: 8b 81 [a-f0-9][a-f0-9] [a-f0-9][a-f0-9] 00 00 mov 0x[a-f0-9]+\(%ecx\),%eax +[ ]*[a-f0-9]+: c3 ret +#pass diff --git a/ld/testsuite/ld-i386/protected7.s b/ld/testsuite/ld-i386/protected7.s new file mode 100644 index 00000000000..bc2bc919584 --- /dev/null +++ b/ld/testsuite/ld-i386/protected7.s @@ -0,0 +1,31 @@ + .protected foo +.globl foo + .data + .align 4 + .type foo, @object + .size foo, 4 +foo: + .long 1 + .text +.globl bar + .type bar, @function +bar: + movl foo@GOTOFF(%ecx), %eax + ret + .size bar, .-bar + + .section ".note.gnu.property", "a" + .p2align 2 + .long 1f - 0f /* name length. */ + .long 3f - 1f /* data length. */ + /* NT_GNU_PROPERTY_TYPE_0 */ + .long 5 /* note type. */ +0: + .asciz "GNU" /* vendor name. */ +1: + .p2align 2 + /* GNU_PROPERTY_NO_COPY_ON_PROTECTED */ + .long 2 /* pr_type. */ + .long 0 /* pr_datasz. */ + .p2align 2 +3: diff --git a/ld/testsuite/ld-x86-64/protected8.d b/ld/testsuite/ld-x86-64/protected8.d new file mode 100644 index 00000000000..22a36ac4c8f --- /dev/null +++ b/ld/testsuite/ld-x86-64/protected8.d @@ -0,0 +1,13 @@ +#as: --64 +#ld: -shared -melf_x86_64 +#objdump: -drw + +.*: +file format .* + + +Disassembly of section .text: + +0+[a-f0-9]+ : +[ ]*[a-f0-9]+: 8b 05 ([0-9a-f]{2} ){4} * mov 0x[a-f0-9]+\(%rip\),%eax # [a-f0-9]+ +[ ]*[a-f0-9]+: c3 retq * +#pass diff --git a/ld/testsuite/ld-x86-64/protected8.s b/ld/testsuite/ld-x86-64/protected8.s new file mode 100644 index 00000000000..314433d0d19 --- /dev/null +++ b/ld/testsuite/ld-x86-64/protected8.s @@ -0,0 +1,31 @@ + .protected foo +.globl foo + .data + .align 4 + .type foo, @object + .size foo, 4 +foo: + .long 1 + .text +.globl bar + .type bar, @function +bar: + movl foo(%rip), %eax + ret + .size bar, .-bar + + .section ".note.gnu.property", "a" + .p2align 3 + .long 1f - 0f /* name length. */ + .long 3f - 2f /* data length. */ + /* NT_GNU_PROPERTY_TYPE_0 */ + .long 5 /* note type. */ +0: .asciz "GNU" /* vendor name. */ +1: + .p2align 3 +2: + /* GNU_PROPERTY_NO_COPY_ON_PROTECTED */ + .long 2 /* pr_type. */ + .long 0 /* pr_datasz. */ + .p2align 3 +3: diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp index 46311577e4b..0b795df60bb 100644 --- a/ld/testsuite/ld-x86-64/x86-64.exp +++ b/ld/testsuite/ld-x86-64/x86-64.exp @@ -291,6 +291,7 @@ run_dump_test "protected6a" run_dump_test "protected6b" run_dump_test "protected7a" run_dump_test "protected7b" +run_dump_test "protected8" run_dump_test "tlsle1" run_dump_test "tlspie1" run_dump_test "tlspie2a" -- 2.30.2