[BFD, LD, AArch64, 1/3] Add support for GNU PROPERTIES in AArch64 for BTI and PAC

This is part of the patch series to add support for BTI and
PAC in AArch64 linker.

This patch implements the following:
1) This extends in the gnu property support in the linker for
AArch64 by defining backend hooks for elf_backend_setup_gnu_properties,
elf_backend_merge_gnu_properties and elf_backend_parse_gnu_properties.
2) It defines AArch64 specific GNU property
GNU_PROPERTY_AARCH64_FEATURE_1_AND and 2 bit for BTI and PAC in it.
3) It also adds support in readelf.c to read and print these new
GNU properties in AArch64.
All these are made according to the new AArch64 ELF ABI
https://developer.arm.com/docs/ihi0056/latest/elf-for-the-arm-64-bit-architecture-aarch64-abi-2018q4

*** bfd/ChangeLog ***

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.

*** binutils/ChangeLog ***

2019-03-13  Sudakshina Das  <sudi.das@arm.com>

	* readelf.c (decode_aarch64_feature_1_and): New.
	(print_gnu_property_note): Add case for AArch64 gnu notes.

*** include/ChangeLog ***

2019-03-13  Sudakshina Das  <sudi.das@arm.com>

	* elf/common.h (GNU_PROPERTY_AARCH64_FEATURE_1_AND): New.
	(GNU_PROPERTY_AARCH64_FEATURE_1_BTI): New.
	(GNU_PROPERTY_AARCH64_FEATURE_1_PAC): New.

*** ld/ChangeLog ***

2019-03-13  Sudakshina Das  <sudi.das@arm.com>

	* NEWS: Document GNU_PROPERTY_AARCH64_FEATURE_1_BTI and
	GNU_PROPERTY_AARCH64_FEATURE_1_PAC.
	* testsuite/ld-aarch64/aarch64-elf.exp: Add run commands for new tests.
	* testsuite/ld-aarch64/property-bti-pac1.d: New test.
	* testsuite/ld-aarch64/property-bti-pac1.s: New test.
	* testsuite/ld-aarch64/property-bti-pac2.d: New test.
	* testsuite/ld-aarch64/property-bti-pac2.s: New test.
	* testsuite/ld-aarch64/property-bti-pac3.d: New test.
This commit is contained in:
Sudakshina Das 2019-03-13 10:42:27 +00:00
parent 44b27f959a
commit cd702818c6
17 changed files with 453 additions and 1 deletions

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -1,3 +1,8 @@
2019-03-13 Sudakshina Das <sudi.das@arm.com>
* readelf.c (decode_aarch64_feature_1_and): New.
(print_gnu_property_note): Add case for AArch64 gnu notes.
2019-03-12 Alan Modra <amodra@gmail.com>
* objdump.c (load_specific_debug_section): Don't compare section

View File

@ -17341,6 +17341,33 @@ decode_x86_feature_2 (unsigned int bitmask)
}
}
static void
decode_aarch64_feature_1_and (unsigned int bitmask)
{
while (bitmask)
{
unsigned int bit = bitmask & (- bitmask);
bitmask &= ~ bit;
switch (bit)
{
case GNU_PROPERTY_AARCH64_FEATURE_1_BTI:
printf ("BTI");
break;
case GNU_PROPERTY_AARCH64_FEATURE_1_PAC:
printf ("PAC");
break;
default:
printf (_("<unknown: %x>"), bit);
break;
}
if (bitmask)
printf (", ");
}
}
static void
print_gnu_property_note (Filedata * filedata, Elf_Internal_Note * pnote)
{
@ -17475,6 +17502,18 @@ print_gnu_property_note (Filedata * filedata, Elf_Internal_Note * pnote)
break;
}
}
else if (filedata->file_header.e_machine == EM_AARCH64)
{
if (type == GNU_PROPERTY_AARCH64_FEATURE_1_AND)
{
printf ("AArch64 feature: ");
if (datasz != 4)
printf (_("<corrupt length: %#x> "), datasz);
else
decode_aarch64_feature_1_and (byte_get (ptr, 4));
goto next;
}
}
}
else
{

View File

@ -1,3 +1,9 @@
2019-03-13 Sudakshina Das <sudi.das@arm.com>
* elf/common.h (GNU_PROPERTY_AARCH64_FEATURE_1_AND): New.
(GNU_PROPERTY_AARCH64_FEATURE_1_BTI): New.
(GNU_PROPERTY_AARCH64_FEATURE_1_PAC): New.
2019-02-20 Alan Hayward <alan.hayward@arm.com>
* elf/common.h (NT_ARM_PAC_MASK): Add define.

View File

@ -841,6 +841,12 @@
#define GNU_PROPERTY_X86_FEATURE_2_XSAVEOPT (1U << 8)
#define GNU_PROPERTY_X86_FEATURE_2_XSAVEC (1U << 9)
/* AArch64 specific GNU PROPERTY. */
#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1U << 0)
#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1U << 1)
/* Values used in GNU .note.ABI-tag notes (NT_GNU_ABI_TAG). */
#define GNU_ABI_TAG_LINUX 0
#define GNU_ABI_TAG_HURD 1

View File

@ -1,3 +1,14 @@
2019-03-13 Sudakshina Das <sudi.das@arm.com>
* NEWS: Document GNU_PROPERTY_AARCH64_FEATURE_1_BTI and
GNU_PROPERTY_AARCH64_FEATURE_1_PAC.
* testsuite/ld-aarch64/aarch64-elf.exp: Add run commands for new tests.
* testsuite/ld-aarch64/property-bti-pac1.d: New test.
* testsuite/ld-aarch64/property-bti-pac1.s: New test.
* testsuite/ld-aarch64/property-bti-pac2.d: New test.
* testsuite/ld-aarch64/property-bti-pac2.s: New test.
* testsuite/ld-aarch64/property-bti-pac3.d: New test.
2019-03-13 H.J. Lu <hongjiu.lu@intel.com>
PR ld/24322

10
ld/NEWS
View File

@ -1,5 +1,15 @@
-*- text -*-
Changes in 2.33:
* Add target handlers for AArch64 for ELF GNU program properties.
* Add support for GNU_PROPERTY_AARCH64_FEATURE_1_BTI in ELF GNU program
properties in the AArch64 ELF linker.
* Add support for GNU_PROPERTY_AARCH64_FEATURE_1_PAC in ELF GNU program
properties in the AArch64 ELF linker.
Changes in 2.32:
* Report property change in linker map file when merging GNU properties.

View File

@ -371,6 +371,10 @@ run_dump_test_lp64 "rela-abs-relative-opt"
run_dump_test_lp64 "pie-bind-locally"
run_dump_test "property-bti-pac1"
run_dump_test "property-bti-pac2"
run_dump_test "property-bti-pac3"
set aarch64elflinktests {
{"ld-aarch64/so with global symbol" "-shared" "" "" {copy-reloc-so.s}
{} "copy-reloc-so.so"}

View File

@ -0,0 +1,11 @@
#name: GNU Property (single input, combine section)
#source: property-bti-pac1.s
#as: -march=armv8.5-a -defsym __mult__=0
#ld: -shared
#readelf: -n
#target: *linux*
Displaying notes found in: .note.gnu.property
Owner Data size Description
GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0
Properties: AArch64 feature: BTI, PAC

View File

@ -0,0 +1,37 @@
.text
.globl _start
.type _start,@function
_start:
mov x1, #2
.ifndef __mult__
bl foo
.endif
.section ".note.gnu.property", "a"
.p2align 3
.long 1f - 0f /* name length */
.long 5f - 2f /* data length */
.long 5 /* note type */
0: .asciz "GNU" /* vendor name */
1:
.p2align 3
2: .long 0xc0000000 /* pr_type. */
.long 4f - 3f /* pr_datasz. */
3:
.long 0x2 /* PAC. */
4:
.p2align 3
5:
.p2align 3
.long 1f - 0f /* name length */
.long 5f - 2f /* data length */
.long 5 /* note type */
0: .asciz "GNU" /* vendor name */
1:
.p2align 3
2: .long 0xc0000000 /* pr_type. */
.long 4f - 3f /* pr_datasz. */
3:
.long 0x1 /* BTI. */
4:
.p2align 3
5:

View File

@ -0,0 +1,12 @@
#name: GNU Property (combine multiple with BTI)
#source: property-bti-pac1.s
#source: property-bti-pac2.s
#as: -mabi=lp64 -defsym __property_bti__=1
#ld: -e _start
#readelf: -n
#target: *linux*
Displaying notes found in: .note.gnu.property
Owner Data size Description
GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0
Properties: AArch64 feature: BTI

View File

@ -0,0 +1,50 @@
.text
.global foo
.type foo, %function
foo:
sub sp, sp, #16
mov w0, 9
str w0, [sp, 12]
ldr w0, [sp, 12]
add w0, w0, 4
str w0, [sp, 12]
nop
add sp, sp, 16
ret
.size foo, .-foo
.global bar
.type bar, %function
.ifdef __property_bti__
.section ".note.gnu.property", "a"
.p2align 3
.long 1f - 0f /* name length */
.long 5f - 2f /* data length */
.long 5 /* note type */
0: .asciz "GNU" /* vendor name */
1:
.p2align 3
2: .long 0xc0000000 /* pr_type. */
.long 4f - 3f /* pr_datasz. */
3:
.long 0x1 /* BTI. */
4:
.p2align 3
5:
.endif
.ifdef __property_pac__
.section ".note.gnu.property", "a"
.p2align 3
.long 1f - 0f /* name length */
.long 5f - 2f /* data length */
.long 5 /* note type */
0: .asciz "GNU" /* vendor name */
1:
.p2align 3
2: .long 0xc0000000 /* pr_type. */
.long 4f - 3f /* pr_datasz. */
3:
.long 0x2 /* PAC. */
4:
.p2align 3
5:
.endif

View File

@ -0,0 +1,12 @@
#name: GNU Property (combine multiple with PAC)
#source: property-bti-pac1.s
#source: property-bti-pac2.s
#as: -mabi=lp64 -defsym __property_pac__=1
#ld: -e _start
#readelf: -n
#target: *linux*
Displaying notes found in: .note.gnu.property
Owner Data size Description
GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0
Properties: AArch64 feature: PAC