diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2021-06-17 14:11:28 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2021-07-08 18:14:31 -0700 |
commit | 6f365fda85a2e2682b197540d14adf66c4261b19 (patch) | |
tree | f746621b46e022fabe3662b04da4d5c2a36f2e1b /bfd/elf-properties.c | |
parent | 6320fd00dc374f74658c7e4b7dffbe1d71723284 (diff) | |
download | gdb-6f365fda85a2e2682b197540d14adf66c4261b19.zip gdb-6f365fda85a2e2682b197540d14adf66c4261b19.tar.gz gdb-6f365fda85a2e2682b197540d14adf66c4261b19.tar.bz2 |
elf: Add GNU_PROPERTY_1_NEEDED check
If GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS is set on any input
relocatable files:
1. Don't generate copy relocations.
2. Turn off extern_protected_data since it implies
GNU_PROPERTY_NO_COPY_ON_PROTECTED.
3. Treate reference to protected symbols with indirect external access
as local.
4. Set GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS on output.
5. When generating executable, clear this bit when there are non-GOT or
non-PLT relocations in input relocatable files without the bit set.
6. Add -z [no]indirect-extern-access to control indirect external access.
bfd/
* elf-bfd (elf_obj_tdata): Add has_indirect_extern_access.
(elf_has_indirect_extern_access): New.
* elf-properties.c (_bfd_elf_parse_gnu_properties): Set
elf_has_indirect_extern_access and elf_has_no_copy_on_protected
when seeing GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS.
(elf_write_gnu_propertie): Add an argument to pass link_info.
Set needed_1_p for GNU_PROPERTY_1_NEEDED in memory.
(_bfd_elf_link_setup_gnu_properties): Handle
GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS for
-z indirect-extern-access. Set nocopyreloc to true and
extern_protected_data to false for indirect external access.
(_bfd_elf_convert_gnu_properties): Updated.
* elf32-i386.c (elf_i386_check_relocs): Set
non_got_ref_without_indirect_extern_access on legacy non-GOT or
non-PLT references.
* elf64-x86-64.c (elf_x86_64_check_relocs): Likewise.
* elflink.c (_bfd_elf_symbol_refs_local_p): Return true for
STV_PROTECTED symbols with indirect external access.
* elfxx-x86.c (_bfd_x86_elf_adjust_dynamic_symbol): Clear
indirect_extern_access for legacy non-GOT/non-PLT references.
* elfxx-x86.h (elf_x86_link_hash_entry): Add
non_got_ref_without_indirect_extern_access.
include/
* bfdlink.h (bfd_link_info): Add indirect_extern_access and
needed_1_p. Change nocopyreloc to int.
ld/
* NEWS: Mention -z [no]indirect-extern-access
* ld.texi: Document -z [no]indirect-extern-access
* ldmain.c (main): Initialize link_info.indirect_extern_access
to -1.
* emulparams/extern_protected_data.sh: Support
-z [no]indirect-extern-access.
* testsuite/ld-elf/indirect-extern-access-1.rd: New file
* testsuite/ld-elf/indirect-extern-access-1a.c: Likewise.
* testsuite/ld-elf/indirect-extern-access-1b.c: Likewise.
* testsuite/ld-elf/indirect-extern-access-2.rd: Likewise.
* testsuite/ld-elf/indirect-extern-access-2a.c: Likewise.
* testsuite/ld-elf/indirect-extern-access-2b.c: Likewise.
* testsuite/ld-elf/indirect-extern-access-3.rd: Likewise.
* testsuite/ld-elf/indirect-extern-access.S: Likewise.
* testsuite/ld-elf/property-1_needed-1b.d: Likewise.
* testsuite/ld-elf/property-1_needed-1c.d: Likewise.
* testsuite/ld-x86-64/indirect-extern-access.rd: Likewise.
* testsuite/ld-x86-64/protected-data-1.h: Likewise.
* testsuite/ld-x86-64/protected-data-1a.c: Likewise.
* testsuite/ld-x86-64/protected-data-1b.c: Likewise.
* testsuite/ld-x86-64/protected-data-2a.S: Likewise.
* testsuite/ld-x86-64/protected-data-2b.S: Likewise.
* testsuite/ld-x86-64/protected-func-2a.S: Likewise.
* testsuite/ld-x86-64/protected-func-2b.S: Likewise.
* testsuite/ld-x86-64/protected-func-2c.c: Likewise.
* testsuite/ld-elf/linux-x86.exp: Run test with
GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS.
* testsuite/ld-x86-64/x86-64.exp: Run tests for protected
function and data with indirect external access.
Diffstat (limited to 'bfd/elf-properties.c')
-rw-r--r-- | bfd/elf-properties.c | 129 |
1 files changed, 111 insertions, 18 deletions
diff --git a/bfd/elf-properties.c b/bfd/elf-properties.c index 56ee91d..aae0288 100644 --- a/bfd/elf-properties.c +++ b/bfd/elf-properties.c @@ -195,6 +195,18 @@ _bfd_elf_parse_gnu_properties (bfd *abfd, Elf_Internal_Note *note) prop = _bfd_elf_get_property (abfd, type, datasz); prop->u.number |= bfd_h_get_32 (abfd, ptr); prop->pr_kind = property_number; + if ((abfd->flags & DYNAMIC) == 0 + && type == GNU_PROPERTY_1_NEEDED + && ((prop->u.number + & GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS) + != 0)) + { + /* NB: Skip the shared library since it may not be + the same at run-time. */ + elf_has_indirect_extern_access (abfd) = true; + /* GNU_PROPERTY_NO_COPY_ON_PROTECTED is implied. */ + elf_has_no_copy_on_protected (abfd) = true; + } goto next; } break; @@ -525,7 +537,8 @@ elf_get_gnu_property_section_size (elf_property_list *list, /* Write GNU properties. */ static void -elf_write_gnu_properties (bfd *abfd, bfd_byte *contents, +elf_write_gnu_properties (struct bfd_link_info *info, + bfd *abfd, bfd_byte *contents, elf_property_list *list, unsigned int size, unsigned int align_size) { @@ -570,6 +583,11 @@ elf_write_gnu_properties (bfd *abfd, bfd_byte *contents, break; case 4: + /* Save the pointer to GNU_PROPERTY_1_NEEDED so that it + can be updated later if needed. */ + if (info != NULL + && list->property.pr_type == GNU_PROPERTY_1_NEEDED) + info->needed_1_p = contents + size; bfd_h_put_32 (abfd, list->property.u.number, contents + size); break; @@ -598,7 +616,7 @@ elf_write_gnu_properties (bfd *abfd, bfd_byte *contents, bfd * _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info) { - bfd *abfd, *first_pbfd = NULL; + bfd *abfd, *first_pbfd = NULL, *elf_bfd = NULL; elf_property_list *list; asection *sec; bool has_properties = false; @@ -606,32 +624,75 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info) = get_elf_backend_data (info->output_bfd); unsigned int elfclass = bed->s->elfclass; int elf_machine_code = bed->elf_machine_code; + elf_property *p; /* Find the first relocatable ELF input with GNU properties. */ for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next) if (bfd_get_flavour (abfd) == bfd_target_elf_flavour && (abfd->flags & DYNAMIC) == 0 - && elf_properties (abfd) != NULL) + && (elf_machine_code + == get_elf_backend_data (abfd)->elf_machine_code) + && (elfclass == get_elf_backend_data (abfd)->s->elfclass)) { - has_properties = true; - /* Ignore GNU properties from ELF objects with different machine code or class. Also skip objects without a GNU_PROPERTY note section. */ - if ((elf_machine_code - == get_elf_backend_data (abfd)->elf_machine_code) - && (elfclass - == get_elf_backend_data (abfd)->s->elfclass) - && bfd_get_section_by_name (abfd, - NOTE_GNU_PROPERTY_SECTION_NAME) != NULL - ) + elf_bfd = abfd; + + if (elf_properties (abfd) != NULL) { - /* Keep .note.gnu.property section in FIRST_PBFD. */ - first_pbfd = abfd; - break; + has_properties = true; + + if (bfd_get_section_by_name (abfd, + NOTE_GNU_PROPERTY_SECTION_NAME) + != NULL) + { + /* Keep .note.gnu.property section in FIRST_PBFD. */ + first_pbfd = abfd; + break; + } } } + if (info->indirect_extern_access > 0 && elf_bfd != NULL) + { + /* Support -z indirect-extern-access. */ + if (first_pbfd == NULL) + { + sec = bfd_make_section_with_flags (elf_bfd, + 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%P: failed to create GNU property section\n")); + + if (!bfd_set_section_alignment (sec, + elfclass == ELFCLASS64 ? 3 : 2)) + info->callbacks->einfo (_("%F%pA: failed to align section\n"), + sec); + + elf_section_type (sec) = SHT_NOTE; + first_pbfd = elf_bfd; + has_properties = true; + } + + p = _bfd_elf_get_property (first_pbfd, GNU_PROPERTY_1_NEEDED, 4); + if (p->pr_kind == property_unknown) + { + /* Create GNU_PROPERTY_1_NEEDED. */ + p->u.number + = GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS; + p->pr_kind = property_number; + } + else + p->u.number + |= GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS; + } + /* Do nothing if there is no .note.gnu.property section. */ if (!has_properties) return NULL; @@ -695,7 +756,6 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info) if N > 0. */ if (info->stacksize > 0) { - elf_property *p; bfd_vma stacksize = info->stacksize; p = _bfd_elf_get_property (first_pbfd, GNU_PROPERTY_STACK_SIZE, @@ -737,7 +797,30 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info) sec->size = size; contents = (bfd_byte *) bfd_zalloc (first_pbfd, size); - elf_write_gnu_properties (first_pbfd, contents, list, size, + if (info->indirect_extern_access <= 0) + { + /* Get GNU_PROPERTY_1_NEEDED properties. */ + p = elf_find_and_remove_property (&elf_properties (first_pbfd), + GNU_PROPERTY_1_NEEDED, false); + if (p != NULL) + { + if (info->indirect_extern_access < 0) + { + /* Set indirect_extern_access to 1 to indicate that + it is turned on by input properties. */ + if ((p->u.number + & GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS) + != 0) + info->indirect_extern_access = 1; + } + else + /* Turn off indirect external access. */ + p->u.number + &= ~GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS; + } + } + + elf_write_gnu_properties (info, first_pbfd, contents, list, size, align_size); /* Cache the section contents for elf_link_input_bfd. */ @@ -747,6 +830,15 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info) symbol is defined in the shared object. */ if (elf_has_no_copy_on_protected (first_pbfd)) info->extern_protected_data = false; + + if (info->indirect_extern_access > 0) + { + /* For indirect external access, don't generate copy + relocations. NB: Set to nocopyreloc to 2 to indicate + that it is implied by indirect_extern_access. */ + info->nocopyreloc = 2; + info->extern_protected_data = false; + } } return first_pbfd; @@ -804,7 +896,8 @@ _bfd_elf_convert_gnu_properties (bfd *ibfd, asection *isec, *ptr_size = size; /* Generate the output .note.gnu.property section. */ - elf_write_gnu_properties (ibfd, contents, list, size, 1 << align_shift); + elf_write_gnu_properties (NULL, ibfd, contents, list, size, + 1 << align_shift); return true; } |