aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf-properties.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2021-06-17 14:11:28 -0700
committerH.J. Lu <hjl.tools@gmail.com>2021-07-08 18:14:31 -0700
commit6f365fda85a2e2682b197540d14adf66c4261b19 (patch)
treef746621b46e022fabe3662b04da4d5c2a36f2e1b /bfd/elf-properties.c
parent6320fd00dc374f74658c7e4b7dffbe1d71723284 (diff)
downloadgdb-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.c129
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;
}