diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 18 | ||||
-rw-r--r-- | bfd/elf-properties.c | 2 | ||||
-rw-r--r-- | bfd/elfnn-aarch64.c | 35 | ||||
-rw-r--r-- | bfd/elfxx-aarch64.c | 180 | ||||
-rw-r--r-- | bfd/elfxx-aarch64.h | 16 |
5 files changed, 250 insertions, 1 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 39b5500..3e5c7c2 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,21 @@ +2019-03-13 Sudakshina Das <sudi.das@arm.com> + + * elf-properties.c (_bfd_elf_link_setup_gnu_properties): Exclude + linker created inputs from merge. + * elfnn-aarch64.c (struct elf_aarch64_obj_tdata): Add field for + GNU_PROPERTY_AARCH64_FEATURE_1_AND properties. + (elfNN_aarch64_link_setup_gnu_properties): New. + (elfNN_aarch64_merge_gnu_properties): New. + (elf_backend_setup_gnu_properties): Define for AArch64. + (elf_backend_merge_gnu_properties): Likewise. + * elfxx-aarch64.c (_bfd_aarch64_elf_link_setup_gnu_properties): Define. + (_bfd_aarch64_elf_parse_gnu_properties): Define. + (_bfd_aarch64_elf_merge_gnu_properties): Define. + * elfxx-aarch64.h (_bfd_aarch64_elf_link_setup_gnu_properties): Declare. + (_bfd_aarch64_elf_parse_gnu_properties): Declare. + (_bfd_aarch64_elf_merge_gnu_properties): Declare. + (elf_backend_parse_gnu_properties): Define for AArch64. + 2019-03-13 H.J. Lu <hongjiu.lu@intel.com> PR ld/24322 diff --git a/bfd/elf-properties.c b/bfd/elf-properties.c index 5e48d75..0c3f19c 100644 --- a/bfd/elf-properties.c +++ b/bfd/elf-properties.c @@ -555,7 +555,7 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info) for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link.next) if (abfd != first_pbfd - && (abfd->flags & (DYNAMIC | BFD_PLUGIN)) == 0) + && (abfd->flags & (DYNAMIC | BFD_PLUGIN | BFD_LINKER_CREATED)) == 0) { elf_property_list *null_ptr = NULL; elf_property_list **listp = &null_ptr; diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index faa2761..5b8cc4c 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -2435,6 +2435,9 @@ struct elf_aarch64_obj_tdata /* Zero to warn when linking objects with incompatible wchar_t sizes. */ int no_wchar_size_warning; + + /* All GNU_PROPERTY_AARCH64_FEATURE_1_AND properties. */ + uint32_t gnu_and_prop; }; #define elf_aarch64_tdata(bfd) \ @@ -9615,6 +9618,32 @@ elfNN_aarch64_backend_symbol_processing (bfd *abfd, asymbol *sym) sym->flags |= BSF_KEEP; } +/* Implement elf_backend_setup_gnu_properties for AArch64. It serves as a + wrapper function for _bfd_aarch64_elf_link_setup_gnu_properties to account + for the effect of GNU properties of the output_bfd. */ +static bfd * +elfNN_aarch64_link_setup_gnu_properties (struct bfd_link_info *info) +{ + uint32_t prop = elf_aarch64_tdata (info->output_bfd)->gnu_and_prop; + bfd *pbfd = _bfd_aarch64_elf_link_setup_gnu_properties (info, &prop); + elf_aarch64_tdata (info->output_bfd)->gnu_and_prop = prop; + return pbfd; +} + +/* Implement elf_backend_merge_gnu_properties for AArch64. It serves as a + wrapper function for _bfd_aarch64_elf_merge_gnu_properties to account + for the effect of GNU properties of the output_bfd. */ +static bfd_boolean +elfNN_aarch64_merge_gnu_properties (struct bfd_link_info *info, + bfd *abfd, + elf_property *aprop, + elf_property *bprop) +{ + uint32_t prop + = elf_aarch64_tdata (info->output_bfd)->gnu_and_prop; + return _bfd_aarch64_elf_merge_gnu_properties (info, abfd, aprop, + bprop, prop); +} /* We use this so we can override certain functions (though currently we don't). */ @@ -9754,6 +9783,12 @@ const struct elf_size_info elfNN_aarch64_size_info = #define elf_backend_symbol_processing \ elfNN_aarch64_backend_symbol_processing +#define elf_backend_setup_gnu_properties \ + elfNN_aarch64_link_setup_gnu_properties + +#define elf_backend_merge_gnu_properties \ + elfNN_aarch64_merge_gnu_properties + #define elf_backend_can_refcount 1 #define elf_backend_can_gc_sections 1 #define elf_backend_plt_readonly 1 diff --git a/bfd/elfxx-aarch64.c b/bfd/elfxx-aarch64.c index 32a9d97..cae94d0 100644 --- a/bfd/elfxx-aarch64.c +++ b/bfd/elfxx-aarch64.c @@ -683,3 +683,183 @@ _bfd_aarch64_elf_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_ty } } } + +/* Find the first input bfd with GNU property and merge it with GPROP. If no + such input is found, add it to a new section at the last input. Update + GPROP accordingly. */ +bfd * +_bfd_aarch64_elf_link_setup_gnu_properties (struct bfd_link_info *info, + uint32_t *gprop) +{ + asection *sec; + bfd *pbfd; + bfd *ebfd = NULL; + elf_property *prop; + + uint32_t gnu_prop = *gprop; + + /* 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 ebfd != NULL it is either an input with property note or the last + input. Either way if we have gnu_prop, we should add it (by creating + a section if needed). */ + if (ebfd != NULL && gnu_prop) + { + prop = _bfd_elf_get_property (ebfd, + GNU_PROPERTY_AARCH64_FEATURE_1_AND, + 4); + prop->u.number |= gnu_prop; + prop->pr_kind = property_number; + + /* pbfd being NULL implies ebfd is the last input. Create the GNU + property note section. */ + 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%P: failed to create GNU property section\n")); + + elf_section_type (sec) = SHT_NOTE; + } + } + + pbfd = _bfd_elf_link_setup_gnu_properties (info); + + if (bfd_link_relocatable (info)) + return pbfd; + + /* If pbfd has any GNU_PROPERTY_AARCH64_FEATURE_1_AND properties, update + gnu_prop accordingly. */ + if (pbfd != NULL) + { + elf_property_list *p; + + /* The property list is sorted in order of type. */ + for (p = elf_properties (pbfd); p; p = p->next) + { + /* Check for all GNU_PROPERTY_AARCH64_FEATURE_1_AND. */ + if (GNU_PROPERTY_AARCH64_FEATURE_1_AND == p->property.pr_type) + { + gnu_prop = (p->property.u.number + & (GNU_PROPERTY_AARCH64_FEATURE_1_PAC + | GNU_PROPERTY_AARCH64_FEATURE_1_BTI)); + break; + } + else if (GNU_PROPERTY_AARCH64_FEATURE_1_AND < p->property.pr_type) + break; + } + } + *gprop = gnu_prop; + return pbfd; +} + +/* Define elf_backend_parse_gnu_properties for AArch64. */ +enum elf_property_kind +_bfd_aarch64_elf_parse_gnu_properties (bfd *abfd, unsigned int type, + bfd_byte *ptr, unsigned int datasz) +{ + elf_property *prop; + + switch (type) + { + case GNU_PROPERTY_AARCH64_FEATURE_1_AND: + if (datasz != 4) + { + _bfd_error_handler + ( _("error: %pB: <corrupt AArch64 used size: 0x%x>"), + abfd, datasz); + return property_corrupt; + } + prop = _bfd_elf_get_property (abfd, type, datasz); + /* Combine properties of the same type. */ + prop->u.number |= bfd_h_get_32 (abfd, ptr); + prop->pr_kind = property_number; + break; + + default: + return property_ignored; + } + + return property_number; +} + +/* Merge AArch64 GNU property BPROP with APROP also accounting for PROP. + If APROP isn't NULL, merge it with BPROP and/or PROP. Vice-versa if BROP + isn't NULL. Return TRUE if there is any update to APROP or if BPROP should + be merge with ABFD. */ +bfd_boolean +_bfd_aarch64_elf_merge_gnu_properties (struct bfd_link_info *info + ATTRIBUTE_UNUSED, + bfd *abfd ATTRIBUTE_UNUSED, + elf_property *aprop, + elf_property *bprop, + uint32_t prop) +{ + unsigned int orig_number; + bfd_boolean updated = FALSE; + unsigned int pr_type = aprop != NULL ? aprop->pr_type : bprop->pr_type; + + switch (pr_type) + { + case GNU_PROPERTY_AARCH64_FEATURE_1_AND: + { + if (aprop != NULL && bprop != NULL) + { + orig_number = aprop->u.number; + aprop->u.number = (orig_number & bprop->u.number) | prop; + updated = orig_number != aprop->u.number; + /* Remove the property if all feature bits are cleared. */ + if (aprop->u.number == 0) + aprop->pr_kind = property_remove; + break; + } + /* If either is NULL, the AND would be 0 so, if there is + any PROP, asign it to the input that is not NULL. */ + if (prop) + { + if (aprop != NULL) + { + orig_number = aprop->u.number; + aprop->u.number = prop; + updated = orig_number != aprop->u.number; + } + else + { + bprop->u.number = prop; + updated = TRUE; + } + } + /* No PROP and BPROP is NULL, so remove APROP. */ + else if (aprop != NULL) + { + aprop->pr_kind = property_remove; + updated = TRUE; + } + } + break; + + default: + abort (); + } + + return updated; +} diff --git a/bfd/elfxx-aarch64.h b/bfd/elfxx-aarch64.h index 1f9ce09..a6d1792 100644 --- a/bfd/elfxx-aarch64.h +++ b/bfd/elfxx-aarch64.h @@ -55,3 +55,19 @@ _bfd_aarch64_elf_write_core_note (bfd *, char *, int *, int, ...); #define elf_backend_grok_prstatus _bfd_aarch64_elf_grok_prstatus #define elf_backend_grok_psinfo _bfd_aarch64_elf_grok_psinfo #define elf_backend_write_core_note _bfd_aarch64_elf_write_core_note + +extern bfd * +_bfd_aarch64_elf_link_setup_gnu_properties (struct bfd_link_info *, + uint32_t *); + +extern enum elf_property_kind +_bfd_aarch64_elf_parse_gnu_properties (bfd *, unsigned int, + bfd_byte *, unsigned int); + +extern bfd_boolean +_bfd_aarch64_elf_merge_gnu_properties (struct bfd_link_info *, bfd *, + elf_property *, elf_property *, + uint32_t); + +#define elf_backend_parse_gnu_properties \ + _bfd_aarch64_elf_parse_gnu_properties |