aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog18
-rw-r--r--bfd/elf-properties.c2
-rw-r--r--bfd/elfnn-aarch64.c35
-rw-r--r--bfd/elfxx-aarch64.c180
-rw-r--r--bfd/elfxx-aarch64.h16
-rw-r--r--binutils/ChangeLog5
-rw-r--r--binutils/readelf.c39
-rw-r--r--include/ChangeLog6
-rw-r--r--include/elf/common.h6
-rw-r--r--ld/ChangeLog11
-rw-r--r--ld/NEWS10
-rw-r--r--ld/testsuite/ld-aarch64/aarch64-elf.exp4
-rw-r--r--ld/testsuite/ld-aarch64/property-bti-pac1.d11
-rw-r--r--ld/testsuite/ld-aarch64/property-bti-pac1.s37
-rw-r--r--ld/testsuite/ld-aarch64/property-bti-pac2.d12
-rw-r--r--ld/testsuite/ld-aarch64/property-bti-pac2.s50
-rw-r--r--ld/testsuite/ld-aarch64/property-bti-pac3.d12
17 files changed, 453 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
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index d62f94a..894eb55 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -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
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 38e9f1b..7446ffe 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -17342,6 +17342,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)
{
unsigned char * ptr = (unsigned char *) pnote->descdata;
@@ -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
{
diff --git a/include/ChangeLog b/include/ChangeLog
index 6d6ec66..cf4353c 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -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.
diff --git a/include/elf/common.h b/include/elf/common.h
index e8faf67..ebdb821 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -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
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 3722d4f..32b5387 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -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
diff --git a/ld/NEWS b/ld/NEWS
index d737af7..dcf1185 100644
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -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.
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index 2b9fad5..c6fefbb 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -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"}
diff --git a/ld/testsuite/ld-aarch64/property-bti-pac1.d b/ld/testsuite/ld-aarch64/property-bti-pac1.d
new file mode 100644
index 0000000..a681ad9
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/property-bti-pac1.d
@@ -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
diff --git a/ld/testsuite/ld-aarch64/property-bti-pac1.s b/ld/testsuite/ld-aarch64/property-bti-pac1.s
new file mode 100644
index 0000000..414c927
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/property-bti-pac1.s
@@ -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:
diff --git a/ld/testsuite/ld-aarch64/property-bti-pac2.d b/ld/testsuite/ld-aarch64/property-bti-pac2.d
new file mode 100644
index 0000000..bc2eaad
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/property-bti-pac2.d
@@ -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
diff --git a/ld/testsuite/ld-aarch64/property-bti-pac2.s b/ld/testsuite/ld-aarch64/property-bti-pac2.s
new file mode 100644
index 0000000..cdec8d9
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/property-bti-pac2.s
@@ -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
diff --git a/ld/testsuite/ld-aarch64/property-bti-pac3.d b/ld/testsuite/ld-aarch64/property-bti-pac3.d
new file mode 100644
index 0000000..5290f4b
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/property-bti-pac3.d
@@ -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