diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2017-08-26 19:22:26 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2017-08-26 19:26:21 -0700 |
commit | a5b4ee9451dc9ffb6aa29376fc03943c53c6da0d (patch) | |
tree | 74028cae4c8a9f47eab5faa25aff8a47b0c04e77 /bfd/elf64-x86-64.c | |
parent | aecbb010f9d74b574ba89a64f45cde2407e53dab (diff) | |
download | gdb-a5b4ee9451dc9ffb6aa29376fc03943c53c6da0d.zip gdb-a5b4ee9451dc9ffb6aa29376fc03943c53c6da0d.tar.gz gdb-a5b4ee9451dc9ffb6aa29376fc03943c53c6da0d.tar.bz2 |
Disallow copy relocation against protected data symbol
We shpouldn't generate copy relocation to resolve reference to protected
data symbol defined in shared object with the NO_COPY_ON_PROTECTED
property. This patch adds a bit to elf_obj_tdata as well as
elf_i386_link_hash_entry and elf_x86_64_link_hash_entry to track the bfd
with the NO_COPY_ON_PROTECTED property as well as protected symbol
defined in shared object. extern_protected_data is set to FALSE if any
input relocatable file contains the NO_COPY_ON_PROTECTED property.
bfd/
PR ld/21997
* elf-bfd.h (elf_obj_tdata): Use ENUM_BITFIELD on object_id,
dyn_lib_class and has_gnu_symbols. Change bad_symtab to bitfield.
Add a has_no_copy_on_protected bitfield.
(elf_has_no_copy_on_protected): New.
* elf-properties.c (_bfd_elf_parse_gnu_properties): Set
elf_has_no_copy_on_protected for GNU_PROPERTY_NO_COPY_ON_PROTECTED.
(elf_merge_gnu_property_list): Likewise.
(_bfd_elf_link_setup_gnu_properties): Set extern_protected_data
to FALSE for elf_has_no_copy_on_protected.
* elf32-i386.c (SYMBOL_NO_COPYRELOC): New.
(elf_i386_link_hash_entry): Add def_protected.
(elf_i386_adjust_dynamic_symbol): Also check SYMBOL_NO_COPYRELOC
when checking info->nocopyreloc.
(elf_i386_link_setup_gnu_properties): Don't set
extern_protected_data here.
(elf_i386_merge_symbol_attribute): New function.
(elf_backend_merge_symbol_attribute): New.
* elf64-x86-64.c (SYMBOL_NO_COPYRELOC): New.
(elf_x86_64_link_hash_entry): Add def_protected.
(elf_x86_64_need_pic): Report protected symbol for def_protected.
(elf_x86_64_adjust_dynamic_symbol): Also check SYMBOL_NO_COPYRELOC
when checking info->nocopyreloc.
(elf_x86_64_relocate_section): Also check for R_X86_64_PC32
relocation run-time overflow and unresolvable R_X86_64_32S
relocation against protected data symbol defined in shared object
with GNU_PROPERTY_NO_COPY_ON_PROTECTED.
(elf_x86_64_link_setup_gnu_properties): Don't set
extern_protected_data here.
(elf_x86_64_merge_symbol_attribute): New function.
(elf_backend_merge_symbol_attribute): New.
ld/
PR ld/21997
* testsuite/ld-i386/i386.exp: Run PR ld/21997 tests.
* testsuite/ld-x86-64/x86-64.exp: Likewise.
* testsuite/ld-i386/pr21997-1a.S: New file.
* testsuite/ld-i386/pr21997-1b.c: Likewise.
* testsuite/ld-i386/pr21997-1c.S: Likewise.
* testsuite/ld-x86-64/pr21997-1a.S: Likewise.
* testsuite/ld-x86-64/pr21997-1a.err: Likewise.
* testsuite/ld-x86-64/pr21997-1b.c: Likewise.
* testsuite/ld-x86-64/pr21997-1b.err: Likewise.
* testsuite/ld-x86-64/pr21997-1c.c: Likewise.
Diffstat (limited to 'bfd/elf64-x86-64.c')
-rw-r--r-- | bfd/elf64-x86-64.c | 139 |
1 files changed, 76 insertions, 63 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 1b8d9ee..6e4c067 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -1061,6 +1061,17 @@ static const struct elf_x86_64_backend_data elf_x86_64_arch_bed = || (EH)->has_non_got_reloc \ || !(INFO)->dynamic_undefined_weak)))) +/* Should copy relocation be generated for a symbol. Don't generate + copy relocation against a protected symbol defined in a shared + object with GNU_PROPERTY_NO_COPY_ON_PROTECTED. */ +#define SYMBOL_NO_COPYRELOC(INFO, EH) \ + ((EH)->def_protected \ + && ((EH)->elf.root.type == bfd_link_hash_defined \ + || (EH)->elf.root.type == bfd_link_hash_defweak) \ + && elf_has_no_copy_on_protected ((EH)->elf.root.u.def.section->owner) \ + && ((EH)->elf.root.u.def.section->owner->flags & DYNAMIC) != 0 \ + && ((EH)->elf.root.u.def.section->flags & SEC_CODE) == 0) + /* x86-64 ELF linker hash entry. */ struct elf_x86_64_link_hash_entry @@ -1104,6 +1115,9 @@ struct elf_x86_64_link_hash_entry /* TRUE if symbol is __tls_get_addr. */ unsigned int tls_get_addr : 1; + /* TRUE if symbol is defined as a protected symbol. */ + unsigned int def_protected : 1; + /* Reference count of C/C++ function pointer relocations in read-write section which can be resolved at run-time. */ bfd_signed_vma func_pointer_refcount; @@ -1908,7 +1922,10 @@ elf_x86_64_need_pic (struct bfd_link_info *info, v = _("protected symbol "); break; default: - v = _("symbol "); + if (((struct elf_x86_64_link_hash_entry *) h)->def_protected) + v = _("protected symbol "); + else + v = _("symbol "); pic = _("; recompile with -fPIC"); break; } @@ -3043,6 +3060,8 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info, the link may change h->type. So fix it now. */ h->plt.offset = (bfd_vma) -1; + eh = (struct elf_x86_64_link_hash_entry *) h; + /* If this is a weak symbol, and there is a real definition, the processor independent code will have arranged for us to see the real definition first, and we can just use the same value. */ @@ -3052,9 +3071,10 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info, || h->u.weakdef->root.type == bfd_link_hash_defweak); h->root.u.def.section = h->u.weakdef->root.u.def.section; h->root.u.def.value = h->u.weakdef->root.u.def.value; - if (ELIMINATE_COPY_RELOCS || info->nocopyreloc) + if (ELIMINATE_COPY_RELOCS + || info->nocopyreloc + || SYMBOL_NO_COPYRELOC (info, eh)) { - eh = (struct elf_x86_64_link_hash_entry *) h; h->non_got_ref = h->u.weakdef->non_got_ref; eh->needs_copy = h->u.weakdef->needs_copy; } @@ -3077,7 +3097,7 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info, return TRUE; /* If -z nocopyreloc was given, we won't generate them either. */ - if (info->nocopyreloc) + if (info->nocopyreloc || SYMBOL_NO_COPYRELOC (info, eh)) { h->non_got_ref = 0; return TRUE; @@ -4950,7 +4970,9 @@ do_ifunc_pointer: && ((bfd_link_executable (info) && ((h->root.type == bfd_link_hash_undefweak && !resolved_to_zero) - || (info->nocopyreloc + || ((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))) @@ -5724,7 +5746,10 @@ direct: switch (r_type) { case R_X86_64_32S: - if (info->nocopyreloc + sec = h->root.u.def.section; + if ((info->nocopyreloc + || (eh->def_protected + && elf_has_no_copy_on_protected (h->root.u.def.section->owner))) && !(h->root.u.def.section->flags & SEC_CODE)) return elf_x86_64_need_pic (info, input_bfd, input_section, h, NULL, NULL, howto); @@ -7137,6 +7162,21 @@ elf_x86_64_merge_symbol (struct elf_link_hash_entry *h, return TRUE; } +static void +elf_x86_64_merge_symbol_attribute (struct elf_link_hash_entry *h, + const Elf_Internal_Sym *isym, + bfd_boolean definition, + bfd_boolean dynamic ATTRIBUTE_UNUSED) +{ + if (definition) + { + struct elf_x86_64_link_hash_entry *eh + = (struct elf_x86_64_link_hash_entry *) h; + eh->def_protected = (ELF_ST_VISIBILITY (isym->st_other) + == STV_PROTECTED); + } +} + static int elf_x86_64_additional_program_headers (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED) @@ -7349,69 +7389,40 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info) break; } - if (ebfd != NULL) + if (ebfd != NULL && features) { - if (features) + /* 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->pr_kind = property_number; + + /* Create the GNU property note section if needed. */ + if (pbfd == NULL) { - /* 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->pr_kind = property_number; - - /* 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")); + 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)) - { + 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); - } - - elf_section_type (sec) = SHT_NOTE; + info->callbacks->einfo (_("%F%A: failed to align section\n"), + sec); } - } - - /* 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; - } - } + elf_section_type (sec) = SHT_NOTE; + } } pbfd = _bfd_elf_link_setup_gnu_properties (info); @@ -7830,6 +7841,8 @@ elf_x86_64_special_sections[]= elf_x86_64_common_definition #define elf_backend_merge_symbol \ elf_x86_64_merge_symbol +#define elf_backend_merge_symbol_attribute \ + elf_x86_64_merge_symbol_attribute #define elf_backend_special_sections \ elf_x86_64_special_sections #define elf_backend_additional_program_headers \ |