[BFD, LD, AArch64, 2/3] Add --force-bti to enable BTI and to select BTI enabled PLTs
authorSudakshina Das <sudi.das@arm.com>
Wed, 13 Mar 2019 10:54:30 +0000 (10:54 +0000)
committerSudakshina Das <sudi.das@arm.com>
Wed, 13 Mar 2019 11:47:07 +0000 (11:47 +0000)
This is part of the patch series to add support for BTI and
PAC in AArch64 linker.

1) This patch adds a new ld command line option: --force-bti.
In the presence of this option, the linker enables BTI with the
GNU_PROPERTY_AARCH64_FEATURE_1_BTI feature. This gives out warning
in case of missing gnu notes for BTI in inputs.
2) It also defines a new set of BTI enabled PLTs. These are used either
when all the inputs are marked with GNU_PROPERTY_AARCH64_FEATURE_1_BTI
or when the new --force-bti option is used. This required adding new
fields in elf_aarch64_link_hash_table so that we could make the PLT
related information more generic.
3) It also defines a dynamic tag DT_AARCH64_BTI_PLT. The linker uses
this whenever it picks BTI enabled PLTs.
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>
    Szabolcs Nagy  <szabolcs.nagy@arm.com>

* bfd-in.h (aarch64_plt_type, aarch64_enable_bti_type): New.
(aarch64_bti_pac_info): New.
(bfd_elf64_aarch64_set_options): Add aarch64_bti_pac_info argument.
(bfd_elf32_aarch64_set_options): Likewise.
* bfd-in2.h: Regenerate
* elfnn-aarch64.c (PLT_BTI_ENTRY_SIZE): New.
(PLT_BTI_SMALL_ENTRY_SIZE, PLT_BTI_TLSDESC_ENTRY_SIZE): New.
(elfNN_aarch64_small_plt0_bti_entry): New.
(elfNN_aarch64_small_plt_bti_entry): New.
(elfNN_aarch64_tlsdesc_small_plt_bti_entry): New.
(elf_aarch64_obj_tdata): Add no_bti_warn and plt_type fields.
(elf_aarch64_link_hash_table): Add plt0_entry, plt_entry and
tlsdesc_plt_entry_size fields.
(elfNN_aarch64_link_hash_table_create): Initialise the new fields.
(setup_plt_values): New helper function.
(bfd_elfNN_aarch64_set_options): Use new bp_info to set plt sizes and
bti enable type.
(elfNN_aarch64_allocate_dynrelocs): Use new size members instead of
fixed macros.
(elfNN_aarch64_size_dynamic_sections): Likewise and add checks.
(elfNN_aarch64_create_small_pltn_entry): Use new generic pointers
to plt stubs instead of fixed ones and update filling them according
to the need for bti.
(elfNN_aarch64_init_small_plt0_entry): Likewise.
(elfNN_aarch64_finish_dynamic_sections): Likewise.
(get_plt_type, elfNN_aarch64_get_synthetic_symtab): New.
(elfNN_aarch64_plt_sym_val): Update size accordingly.
(elfNN_aarch64_link_setup_gnu_properties): Set up plts if BTI GNU NOTE
is set.
(bfd_elfNN_get_synthetic_symtab): Define.
(elfNN_aarch64_merge_gnu_properties): Give out warning with --force-bti
and mising BTI NOTE SECTION.

*** binutils/ChangeLog ***

2019-03-13  Sudakshina Das  <sudi.das@arm.com>
    Szabolcs Nagy  <szabolcs.nagy@arm.com>

* readelf.c (get_aarch64_dynamic_type): New.
(get_dynamic_type): Use above for EM_AARCH64.
(dynamic_section_aarch64_val): New.
(process_dynamic_section): Use above for EM_AARCH64.

*** include/ChangeLog ***

2019-03-13  Sudakshina Das  <sudi.das@arm.com>
    Szabolcs Nagy  <szabolcs.nagy@arm.com>

* elf/aarch64.h (DT_AARCH64_BTI_PLT): New.

*** ld/ChangeLog ***

2019-03-13  Sudakshina Das  <sudi.das@arm.com>
    Szabolcs Nagy  <szabolcs.nagy@arm.com>

* NEWS: Document --force-bti.
* emultempl/aarch64elf.em (plt_type, bti_type, OPTION_FORCE_BTI): New.
(PARSE_AND_LIST_SHORTOPTS, PARSE_AND_LIST_OPTIONS): Add force-bti.
(PARSE_AND_LIST_ARGS_CASES): Handle OPTION_FORCE_BTI.
* testsuite/ld-aarch64/aarch64-elf.exp: Add all the tests below.
* testsuite/ld-aarch64/bti-plt-1.d: New test.
* testsuite/ld-aarch64/bti-plt-1.s: New test.
* testsuite/ld-aarch64/bti-plt-2.s: New test.
* testsuite/ld-aarch64/bti-plt-2.d: New test.
* testsuite/ld-aarch64/bti-plt-3.d: New test.
* testsuite/ld-aarch64/bti-plt-4.d: New test.
* testsuite/ld-aarch64/bti-plt-5.d: New test.
* testsuite/ld-aarch64/bti-plt-6.d: New test.
* testsuite/ld-aarch64/bti-plt-7.d: New test.
* testsuite/ld-aarch64/bti-plt-so.s: New test.
* testsuite/ld-aarch64/bti-plt.ld: New test.

23 files changed:
bfd/ChangeLog
bfd/bfd-in.h
bfd/bfd-in2.h
bfd/elfnn-aarch64.c
binutils/ChangeLog
binutils/readelf.c
include/ChangeLog
include/elf/aarch64.h
ld/ChangeLog
ld/NEWS
ld/emultempl/aarch64elf.em
ld/testsuite/ld-aarch64/aarch64-elf.exp
ld/testsuite/ld-aarch64/bti-plt-1.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/bti-plt-1.s [new file with mode: 0644]
ld/testsuite/ld-aarch64/bti-plt-2.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/bti-plt-2.s [new file with mode: 0644]
ld/testsuite/ld-aarch64/bti-plt-3.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/bti-plt-4.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/bti-plt-5.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/bti-plt-6.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/bti-plt-7.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/bti-plt-so.s [new file with mode: 0644]
ld/testsuite/ld-aarch64/bti-plt.ld [new file with mode: 0644]

index 3e5c7c25c5687c4632567e5f39533ef991b896a3..6e7748ea9507607dfe5c8ec667922e83e8453248 100644 (file)
@@ -1,3 +1,40 @@
+2019-03-13  Sudakshina Das  <sudi.das@arm.com>
+           Szabolcs Nagy  <szabolcs.nagy@arm.com>
+
+       * bfd-in.h (aarch64_plt_type, aarch64_enable_bti_type): New.
+       (aarch64_bti_pac_info): New.
+       (bfd_elf64_aarch64_set_options): Add aarch64_bti_pac_info argument.
+       (bfd_elf32_aarch64_set_options): Likewise.
+       * bfd-in2.h: Regenerate
+       * elfnn-aarch64.c (PLT_BTI_ENTRY_SIZE): New.
+       (PLT_BTI_SMALL_ENTRY_SIZE, PLT_BTI_TLSDESC_ENTRY_SIZE): New.
+       (elfNN_aarch64_small_plt0_bti_entry): New.
+       (elfNN_aarch64_small_plt_bti_entry): New.
+       (elfNN_aarch64_tlsdesc_small_plt_bti_entry): New.
+       (elf_aarch64_obj_tdata): Add no_bti_warn and plt_type fields.
+       (elf_aarch64_link_hash_table): Add plt0_entry, plt_entry and
+       tlsdesc_plt_entry_size fields.
+       (elfNN_aarch64_link_hash_table_create): Initialise the new fields.
+       (setup_plt_values): New helper function.
+       (bfd_elfNN_aarch64_set_options): Use new bp_info to set plt sizes and
+       bti enable type.
+       (elfNN_aarch64_allocate_dynrelocs): Use new size members instead of
+       fixed macros.
+       (elfNN_aarch64_size_dynamic_sections): Likewise and add checks.
+       (elfNN_aarch64_create_small_pltn_entry): Use new generic pointers
+       to plt stubs instead of fixed ones and update filling them according
+       to the need for bti.
+       (elfNN_aarch64_init_small_plt0_entry): Likewise.
+       (elfNN_aarch64_finish_dynamic_sections): Likewise.
+       (get_plt_type, elfNN_aarch64_get_synthetic_symtab): New.
+       (elfNN_aarch64_plt_sym_val): Update size accordingly.
+       (elfNN_aarch64_link_setup_gnu_properties): Set up plts if BTI GNU NOTE
+       is set.
+       (bfd_elfNN_get_synthetic_symtab): Define.
+       (elfNN_aarch64_merge_gnu_properties): Give out warning with --force-bti
+       and mising BTI NOTE SECTION.
+
+
 2019-03-13  Sudakshina Das  <sudi.das@arm.com>
 
        * elf-properties.c (_bfd_elf_link_setup_gnu_properties): Exclude
index e7c2eaa93591ca2fc2cfd6f2c5a161ba0c2928a1..b753a9e57c11049a519cbb2b4ab9ef16473db52c 100644 (file)
@@ -995,11 +995,45 @@ extern void bfd_elf64_aarch64_init_maps
 extern void bfd_elf32_aarch64_init_maps
   (bfd *);
 
+/* Types of PLTs based on the level of security.  This would be a
+   bit-mask to denote which of the combinations of security features
+   are enabled:
+   - No security feature PLTs
+   - PLTs with BTI instruction
+   - PLTs with PAC instruction
+*/
+typedef enum
+{
+  PLT_NORMAL   = 0x0,  /* Normal plts.  */
+  PLT_BTI      = 0x1,  /* plts with bti.  */
+  PLT_PAC      = 0x2,  /* plts with pointer authentication.  */
+  PLT_BTI_PAC  = PLT_BTI | PLT_PAC
+} aarch64_plt_type;
+
+/* To indicate if BTI is enabled with/without warning.  */
+typedef enum
+{
+  BTI_NONE     = 0,  /* BTI is not enabled.  */
+  BTI_WARN     = 1,  /* BTI is enabled with --force-bti.  */
+} aarch64_enable_bti_type;
+
+/* A structure to encompass all information coming from BTI or PAC
+   related command line options.  This involves the "PLT_TYPE" to determine
+   which version of PLTs to pick and "BTI_TYPE" to determine if
+   BTI should be turned on with any warnings.   */
+typedef struct
+{
+  aarch64_plt_type plt_type;
+  aarch64_enable_bti_type bti_type;
+} aarch64_bti_pac_info;
+
 extern void bfd_elf64_aarch64_set_options
-  (bfd *, struct bfd_link_info *, int, int, int, int, int, int);
+  (bfd *, struct bfd_link_info *, int, int, int, int, int, int,
+   aarch64_bti_pac_info);
 
 extern void bfd_elf32_aarch64_set_options
-  (bfd *, struct bfd_link_info *, int, int, int, int, int, int);
+  (bfd *, struct bfd_link_info *, int, int, int, int, int, int,
+   aarch64_bti_pac_info);
 
 /* ELF AArch64 mapping symbol support.  */
 #define BFD_AARCH64_SPECIAL_SYM_TYPE_MAP       (1 << 0)
index e25da50aafbf4fe14b7220bb2d0791ac7899b4f6..33a29406ae3f4786e1ccb727e29736c2179f122c 100644 (file)
@@ -1002,11 +1002,45 @@ extern void bfd_elf64_aarch64_init_maps
 extern void bfd_elf32_aarch64_init_maps
   (bfd *);
 
+/* Types of PLTs based on the level of security.  This would be a
+   bit-mask to denote which of the combinations of security features
+   are enabled:
+   - No security feature PLTs
+   - PLTs with BTI instruction
+   - PLTs with PAC instruction
+*/
+typedef enum
+{
+  PLT_NORMAL   = 0x0,  /* Normal plts.  */
+  PLT_BTI      = 0x1,  /* plts with bti.  */
+  PLT_PAC      = 0x2,  /* plts with pointer authentication.  */
+  PLT_BTI_PAC  = PLT_BTI | PLT_PAC
+} aarch64_plt_type;
+
+/* To indicate if BTI is enabled with/without warning.  */
+typedef enum
+{
+  BTI_NONE     = 0,  /* BTI is not enabled.  */
+  BTI_WARN     = 1,  /* BTI is enabled with --force-bti.  */
+} aarch64_enable_bti_type;
+
+/* A structure to encompass all information coming from BTI or PAC
+   related command line options.  This involves the "PLT_TYPE" to determine
+   which version of PLTs to pick and "BTI_TYPE" to determine if
+   BTI should be turned on with any warnings.   */
+typedef struct
+{
+  aarch64_plt_type plt_type;
+  aarch64_enable_bti_type bti_type;
+} aarch64_bti_pac_info;
+
 extern void bfd_elf64_aarch64_set_options
-  (bfd *, struct bfd_link_info *, int, int, int, int, int, int);
+  (bfd *, struct bfd_link_info *, int, int, int, int, int, int,
+   aarch64_bti_pac_info);
 
 extern void bfd_elf32_aarch64_set_options
-  (bfd *, struct bfd_link_info *, int, int, int, int, int, int);
+  (bfd *, struct bfd_link_info *, int, int, int, int, int, int,
+   aarch64_bti_pac_info);
 
 /* ELF AArch64 mapping symbol support.  */
 #define BFD_AARCH64_SPECIAL_SYM_TYPE_MAP       (1 << 0)
index 5b8cc4c9701feacd0deb5c998c89d17d97864646..69b8f83f3c8102ad84bd963733ed066ca11469e1 100644 (file)
 #define PLT_ENTRY_SIZE                 (32)
 #define PLT_SMALL_ENTRY_SIZE           (16)
 #define PLT_TLSDESC_ENTRY_SIZE         (32)
+/* PLT sizes with BTI insn.  */
+#define PLT_BTI_ENTRY_SIZE             (36)
+#define PLT_BTI_SMALL_ENTRY_SIZE       (20)
+#define PLT_BTI_TLSDESC_ENTRY_SIZE     (36)
 
 /* Encoding of the nop instruction.  */
 #define INSN_NOP 0xd503201f
@@ -297,9 +301,27 @@ static const bfd_byte elfNN_aarch64_small_plt0_entry[PLT_ENTRY_SIZE] =
   0x1f, 0x20, 0x03, 0xd5,      /* nop */
 };
 
+static const bfd_byte elfNN_aarch64_small_plt0_bti_entry[PLT_BTI_ENTRY_SIZE] =
+{
+  0x5f, 0x24, 0x03, 0xd5,      /* bti c.  */
+  0xf0, 0x7b, 0xbf, 0xa9,      /* stp x16, x30, [sp, #-16]!  */
+  0x10, 0x00, 0x00, 0x90,      /* adrp x16, (GOT+16)  */
+#if ARCH_SIZE == 64
+  0x11, 0x0A, 0x40, 0xf9,      /* ldr x17, [x16, #PLT_GOT+0x10]  */
+  0x10, 0x42, 0x00, 0x91,      /* add x16, x16,#PLT_GOT+0x10   */
+#else
+  0x11, 0x0A, 0x40, 0xb9,      /* ldr w17, [x16, #PLT_GOT+0x8]  */
+  0x10, 0x22, 0x00, 0x11,      /* add w16, w16,#PLT_GOT+0x8   */
+#endif
+  0x20, 0x02, 0x1f, 0xd6,      /* br x17  */
+  0x1f, 0x20, 0x03, 0xd5,      /* nop */
+  0x1f, 0x20, 0x03, 0xd5,      /* nop */
+  0x1f, 0x20, 0x03, 0xd5,      /* nop */
+};
+
 /* Per function entry in a procedure linkage table looks like this
    if the distance between the PLTGOT and the PLT is < 4GB use
-   these PLT entries.  */
+   these PLT entries.  Use BTI versions of the PLTs when enabled.  */
 static const bfd_byte elfNN_aarch64_small_plt_entry[PLT_SMALL_ENTRY_SIZE] =
 {
   0x10, 0x00, 0x00, 0x90,      /* adrp x16, PLTGOT + n * 8  */
@@ -313,6 +335,21 @@ static const bfd_byte elfNN_aarch64_small_plt_entry[PLT_SMALL_ENTRY_SIZE] =
   0x20, 0x02, 0x1f, 0xd6,      /* br x17.  */
 };
 
+static const bfd_byte
+elfNN_aarch64_small_plt_bti_entry[PLT_BTI_SMALL_ENTRY_SIZE] =
+{
+  0x5f, 0x24, 0x03, 0xd5,      /* bti c.  */
+  0x10, 0x00, 0x00, 0x90,      /* adrp x16, PLTGOT + n * 8  */
+#if ARCH_SIZE == 64
+  0x11, 0x02, 0x40, 0xf9,      /* ldr x17, [x16, PLTGOT + n * 8] */
+  0x10, 0x02, 0x00, 0x91,      /* add x16, x16, :lo12:PLTGOT + n * 8  */
+#else
+  0x11, 0x02, 0x40, 0xb9,      /* ldr w17, [x16, PLTGOT + n * 4] */
+  0x10, 0x02, 0x00, 0x11,      /* add w16, w16, :lo12:PLTGOT + n * 4  */
+#endif
+  0x20, 0x02, 0x1f, 0xd6,      /* br x17.  */
+};
+
 static const bfd_byte
 elfNN_aarch64_tlsdesc_small_plt_entry[PLT_TLSDESC_ENTRY_SIZE] =
 {
@@ -331,6 +368,25 @@ elfNN_aarch64_tlsdesc_small_plt_entry[PLT_TLSDESC_ENTRY_SIZE] =
   0x1f, 0x20, 0x03, 0xd5,      /* nop */
 };
 
+static const bfd_byte
+elfNN_aarch64_tlsdesc_small_plt_bti_entry[PLT_BTI_TLSDESC_ENTRY_SIZE] =
+{
+  0x5f, 0x24, 0x03, 0xd5,      /* bti c.  */
+  0xe2, 0x0f, 0xbf, 0xa9,      /* stp x2, x3, [sp, #-16]! */
+  0x02, 0x00, 0x00, 0x90,      /* adrp x2, 0 */
+  0x03, 0x00, 0x00, 0x90,      /* adrp x3, 0 */
+#if ARCH_SIZE == 64
+  0x42, 0x00, 0x40, 0xf9,      /* ldr x2, [x2, #0] */
+  0x63, 0x00, 0x00, 0x91,      /* add x3, x3, 0 */
+#else
+  0x42, 0x00, 0x40, 0xb9,      /* ldr w2, [x2, #0] */
+  0x63, 0x00, 0x00, 0x11,      /* add w3, w3, 0 */
+#endif
+  0x40, 0x00, 0x1f, 0xd6,      /* br x2 */
+  0x1f, 0x20, 0x03, 0xd5,      /* nop */
+  0x1f, 0x20, 0x03, 0xd5,      /* nop */
+};
+
 #define elf_info_to_howto              elfNN_aarch64_info_to_howto
 #define elf_info_to_howto_rel          elfNN_aarch64_info_to_howto
 
@@ -2438,6 +2494,13 @@ struct elf_aarch64_obj_tdata
 
   /* All GNU_PROPERTY_AARCH64_FEATURE_1_AND properties.  */
   uint32_t gnu_and_prop;
+
+  /* Zero to warn when linking objects with incompatible
+     GNU_PROPERTY_AARCH64_FEATURE_1_BTI.  */
+  int no_bti_warn;
+
+  /* PLT type based on security.  */
+  aarch64_plt_type plt_type;
 };
 
 #define elf_aarch64_tdata(bfd)                         \
@@ -2543,9 +2606,15 @@ struct elf_aarch64_link_hash_table
   /* The number of bytes in the initial entry in the PLT.  */
   bfd_size_type plt_header_size;
 
-  /* The number of bytes in the subsequent PLT etries.  */
+  /* The bytes of the initial PLT entry.  */
+  const bfd_byte *plt0_entry;
+
+  /* The number of bytes in the subsequent PLT entries.  */
   bfd_size_type plt_entry_size;
 
+  /* The bytes of the subsequent PLT entry.  */
+  const bfd_byte *plt_entry;
+
   /* Small local sym cache.  */
   struct sym_cache sym_cache;
 
@@ -2588,6 +2657,9 @@ struct elf_aarch64_link_hash_table
      yet.  */
   bfd_vma tlsdesc_plt;
 
+  /* The number of bytes in the PLT enty for the TLS descriptor.  */
+  bfd_size_type tlsdesc_plt_entry_size;
+
   /* The GOT offset for the lazy trampoline.  Communicated to the
      loader via DT_TLSDESC_GOT.  The magic value (bfd_vma) -1
      indicates an offset is not allocated.  */
@@ -2831,7 +2903,10 @@ elfNN_aarch64_link_hash_table_create (bfd *abfd)
     }
 
   ret->plt_header_size = PLT_ENTRY_SIZE;
+  ret->plt0_entry = elfNN_aarch64_small_plt0_entry;
   ret->plt_entry_size = PLT_SMALL_ENTRY_SIZE;
+  ret->plt_entry = elfNN_aarch64_small_plt_entry;
+  ret->tlsdesc_plt_entry_size = PLT_TLSDESC_ENTRY_SIZE;
   ret->obfd = abfd;
   ret->dt_tlsdesc_got = (bfd_vma) - 1;
 
@@ -4599,6 +4674,28 @@ bfd_elfNN_aarch64_init_maps (bfd *abfd)
     }
 }
 
+static void
+setup_plt_values (struct bfd_link_info *link_info,
+                 aarch64_plt_type plt_type)
+{
+  struct elf_aarch64_link_hash_table *globals;
+  globals = elf_aarch64_hash_table (link_info);
+
+  if (plt_type == PLT_BTI)
+    {
+      globals->plt_header_size = PLT_BTI_ENTRY_SIZE;
+      globals->plt0_entry = elfNN_aarch64_small_plt0_bti_entry;
+      globals->tlsdesc_plt_entry_size = PLT_BTI_TLSDESC_ENTRY_SIZE;
+
+      /* Only in ET_EXEC we need PLTn with BTI.  */
+      if (bfd_link_pde (link_info))
+       {
+         globals->plt_entry_size = PLT_BTI_SMALL_ENTRY_SIZE;
+         globals->plt_entry = elfNN_aarch64_small_plt_bti_entry;
+       }
+    }
+}
+
 /* Set option values needed during linking.  */
 void
 bfd_elfNN_aarch64_set_options (struct bfd *output_bfd,
@@ -4607,7 +4704,8 @@ bfd_elfNN_aarch64_set_options (struct bfd *output_bfd,
                               int no_wchar_warn, int pic_veneer,
                               int fix_erratum_835769,
                               int fix_erratum_843419,
-                              int no_apply_dynamic_relocs)
+                              int no_apply_dynamic_relocs,
+                              aarch64_bti_pac_info bp_info)
 {
   struct elf_aarch64_link_hash_table *globals;
 
@@ -4621,6 +4719,20 @@ bfd_elfNN_aarch64_set_options (struct bfd *output_bfd,
   BFD_ASSERT (is_aarch64_elf (output_bfd));
   elf_aarch64_tdata (output_bfd)->no_enum_size_warning = no_enum_warn;
   elf_aarch64_tdata (output_bfd)->no_wchar_size_warning = no_wchar_warn;
+
+  switch (bp_info.bti_type)
+    {
+    case BTI_WARN:
+      elf_aarch64_tdata (output_bfd)->no_bti_warn = 0;
+      elf_aarch64_tdata (output_bfd)->gnu_and_prop
+       |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
+      break;
+
+    default:
+      break;
+    }
+  elf_aarch64_tdata (output_bfd)->plt_type = bp_info.plt_type;
+  setup_plt_values (link_info, bp_info.plt_type);
 }
 
 static bfd_vma
@@ -8349,7 +8461,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
          /* Make room for this entry. For now we only create the
             small model PLT entries. We later need to find a way
             of relaxing into these from the large model PLT entries.  */
-         s->size += PLT_SMALL_ENTRY_SIZE;
+         s->size += htab->plt_entry_size;
 
          /* We also need to make an entry in the .got.plt section, which
             will be placed in the .got section by the linker script.  */
@@ -8849,10 +8961,10 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
   if (htab->tlsdesc_plt)
     {
       if (htab->root.splt->size == 0)
-       htab->root.splt->size += PLT_ENTRY_SIZE;
+       htab->root.splt->size += htab->plt_header_size;
 
       htab->tlsdesc_plt = htab->root.splt->size;
-      htab->root.splt->size += PLT_TLSDESC_ENTRY_SIZE;
+      htab->root.splt->size += htab->tlsdesc_plt_entry_size;
 
       /* If we're not using lazy TLS relocations, don't generate the
         GOT entry required.  */
@@ -8964,6 +9076,10 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
              && (!add_dynamic_entry (DT_TLSDESC_PLT, 0)
                  || !add_dynamic_entry (DT_TLSDESC_GOT, 0)))
            return FALSE;
+
+         if ((elf_aarch64_tdata (output_bfd)->plt_type == PLT_BTI)
+             && !add_dynamic_entry (DT_AARCH64_BTI_PLT, 0))
+           return FALSE;
        }
 
       if (relocs)
@@ -9060,7 +9176,13 @@ elfNN_aarch64_create_small_pltn_entry (struct elf_link_hash_entry *h,
     gotplt->output_offset + got_offset;
 
   /* Copy in the boiler-plate for the PLTn entry.  */
-  memcpy (plt_entry, elfNN_aarch64_small_plt_entry, PLT_SMALL_ENTRY_SIZE);
+  memcpy (plt_entry, htab->plt_entry, htab->plt_entry_size);
+
+  /* First instruction in BTI enabled PLT stub is a BTI
+     instruction so skip it.  */
+  if (elf_aarch64_tdata (output_bfd)->plt_type & PLT_BTI
+      && elf_elfheader (output_bfd)->e_type == ET_EXEC)
+    plt_entry = plt_entry + 4;
 
   /* Fill in the top 21 bits for this: ADRP x16, PLT_GOT + n * 8.
      ADRP:   ((PG(S+A)-PG(P)) >> 12) & 0x1fffff */
@@ -9365,10 +9487,10 @@ elfNN_aarch64_init_small_plt0_entry (bfd *output_bfd ATTRIBUTE_UNUSED,
   bfd_vma plt_base;
 
 
-  memcpy (htab->root.splt->contents, elfNN_aarch64_small_plt0_entry,
-         PLT_ENTRY_SIZE);
+  memcpy (htab->root.splt->contents, htab->plt0_entry,
+         htab->plt_header_size);
   elf_section_data (htab->root.splt->output_section)->this_hdr.sh_entsize =
-    PLT_ENTRY_SIZE;
+    htab->plt_header_size;
 
   plt_got_2nd_ent = (htab->root.sgotplt->output_section->vma
                  + htab->root.sgotplt->output_offset
@@ -9377,18 +9499,24 @@ elfNN_aarch64_init_small_plt0_entry (bfd *output_bfd ATTRIBUTE_UNUSED,
   plt_base = htab->root.splt->output_section->vma +
     htab->root.splt->output_offset;
 
+  /* First instruction in BTI enabled PLT stub is a BTI
+     instruction so skip it.  */
+  bfd_byte *plt0_entry = htab->root.splt->contents;
+  if (elf_aarch64_tdata (output_bfd)->plt_type & PLT_BTI)
+    plt0_entry = plt0_entry + 4;
+
   /* Fill in the top 21 bits for this: ADRP x16, PLT_GOT + n * 8.
      ADRP:   ((PG(S+A)-PG(P)) >> 12) & 0x1fffff */
   elf_aarch64_update_plt_entry (output_bfd, BFD_RELOC_AARCH64_ADR_HI21_PCREL,
-                               htab->root.splt->contents + 4,
+                               plt0_entry + 4,
                                PG (plt_got_2nd_ent) - PG (plt_base + 4));
 
   elf_aarch64_update_plt_entry (output_bfd, BFD_RELOC_AARCH64_LDSTNN_LO12,
-                               htab->root.splt->contents + 8,
+                               plt0_entry + 8,
                                PG_OFFSET (plt_got_2nd_ent));
 
   elf_aarch64_update_plt_entry (output_bfd, BFD_RELOC_AARCH64_ADD_LO12,
-                               htab->root.splt->contents + 12,
+                               plt0_entry + 12,
                                PG_OFFSET (plt_got_2nd_ent));
 }
 
@@ -9472,9 +9600,18 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd,
          bfd_put_NN (output_bfd, (bfd_vma) 0,
                      htab->root.sgot->contents + htab->dt_tlsdesc_got);
 
+         const bfd_byte *entry = elfNN_aarch64_tlsdesc_small_plt_entry;
+         htab->tlsdesc_plt_entry_size = PLT_TLSDESC_ENTRY_SIZE;
+
+         aarch64_plt_type type = elf_aarch64_tdata (output_bfd)->plt_type;
+         if (type == PLT_BTI)
+           {
+             entry = elfNN_aarch64_tlsdesc_small_plt_bti_entry;
+             htab->tlsdesc_plt_entry_size = PLT_BTI_TLSDESC_ENTRY_SIZE;
+           }
+
          memcpy (htab->root.splt->contents + htab->tlsdesc_plt,
-                 elfNN_aarch64_tlsdesc_small_plt_entry,
-                 sizeof (elfNN_aarch64_tlsdesc_small_plt_entry));
+                 entry, htab->tlsdesc_plt_entry_size);
 
          {
            bfd_vma adrp1_addr =
@@ -9496,6 +9633,15 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd,
            bfd_byte *plt_entry =
              htab->root.splt->contents + htab->tlsdesc_plt;
 
+          /* First instruction in BTI enabled PLT stub is a BTI
+             instruction so skip it.  */
+           if (type & PLT_BTI)
+             {
+               plt_entry = plt_entry + 4;
+               adrp1_addr = adrp1_addr + 4;
+               adrp2_addr = adrp2_addr + 4;
+             }
+
            /* adrp x2, DT_TLSDESC_GOT */
            elf_aarch64_update_plt_entry (output_bfd,
                                          BFD_RELOC_AARCH64_ADR_HI21_PCREL,
@@ -9574,6 +9720,53 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd,
   return TRUE;
 }
 
+/* Check if BTI enabled PLTs are needed.  Returns the type needed.  */
+static aarch64_plt_type
+get_plt_type (bfd *abfd)
+{
+  aarch64_plt_type ret = PLT_NORMAL;
+  bfd_byte *contents, *extdyn, *extdynend;
+  asection *sec = bfd_get_section_by_name (abfd, ".dynamic");
+  if (!sec || !bfd_malloc_and_get_section (abfd, sec, &contents))
+    return ret;
+  extdyn = contents;
+  extdynend = contents + sec->size;
+  for (; extdyn < extdynend; extdyn += sizeof (ElfNN_External_Dyn))
+    {
+      Elf_Internal_Dyn dyn;
+      bfd_elfNN_swap_dyn_in (abfd, extdyn, &dyn);
+
+      /* Let's check the processor specific dynamic array tags.  */
+      bfd_vma tag = dyn.d_tag;
+      if (tag < DT_LOPROC || tag > DT_HIPROC)
+       continue;
+
+      switch (tag)
+       {
+       case DT_AARCH64_BTI_PLT:
+         ret = PLT_BTI;
+         break;
+
+       default: break;
+       }
+    }
+  free (contents);
+  return ret;
+}
+
+static long
+elfNN_aarch64_get_synthetic_symtab (bfd *abfd,
+                                   long symcount,
+                                   asymbol **syms,
+                                   long dynsymcount,
+                                   asymbol **dynsyms,
+                                   asymbol **ret)
+{
+  elf_aarch64_tdata (abfd)->plt_type = get_plt_type (abfd);
+  return _bfd_elf_get_synthetic_symtab (abfd, symcount, syms,
+                                       dynsymcount, dynsyms, ret);
+}
+
 /* Return address for Ith PLT stub in section PLT, for relocation REL
    or (bfd_vma) -1 if it should not be included.  */
 
@@ -9581,7 +9774,16 @@ static bfd_vma
 elfNN_aarch64_plt_sym_val (bfd_vma i, const asection *plt,
                           const arelent *rel ATTRIBUTE_UNUSED)
 {
-  return plt->vma + PLT_ENTRY_SIZE + i * PLT_SMALL_ENTRY_SIZE;
+  size_t plt0_size = PLT_ENTRY_SIZE;
+  size_t pltn_size = PLT_SMALL_ENTRY_SIZE;
+
+  if (elf_aarch64_tdata (plt->owner)->plt_type == PLT_BTI)
+    {
+      plt0_size = PLT_BTI_ENTRY_SIZE;
+      if (elf_elfheader (plt->owner)->e_type == ET_EXEC)
+       pltn_size = PLT_BTI_SMALL_ENTRY_SIZE;
+    }
+  return plt->vma + plt0_size + i * pltn_size;
 }
 
 /* Returns TRUE if NAME is an AArch64 mapping symbol.
@@ -9627,6 +9829,9 @@ 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;
+  elf_aarch64_tdata (info->output_bfd)->plt_type
+    |= (prop & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) ? PLT_BTI : 0;
+  setup_plt_values (info, elf_aarch64_tdata (info->output_bfd)->plt_type);
   return pbfd;
 }
 
@@ -9641,6 +9846,23 @@ elfNN_aarch64_merge_gnu_properties (struct bfd_link_info *info,
 {
   uint32_t prop
     = elf_aarch64_tdata (info->output_bfd)->gnu_and_prop;
+
+  /* If output has been marked with BTI using command line argument, give out
+     warning if necessary.  */
+  if ((prop & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
+      && (!elf_aarch64_tdata (info->output_bfd)->no_bti_warn))
+    {
+      if ((aprop && !(aprop->u.number & GNU_PROPERTY_AARCH64_FEATURE_1_BTI))
+         || (bprop && !(bprop->u.number & GNU_PROPERTY_AARCH64_FEATURE_1_BTI))
+         /* If either property is NULL, it means its bfd did not have any
+            property.  */
+         || !aprop || !bprop)
+       {
+         _bfd_error_handler (_("warning: BTI turned on by --force-bti when "
+                               "all inputs do not have BTI in NOTE section."));
+       }
+    }
+
   return  _bfd_aarch64_elf_merge_gnu_properties (info, abfd, aprop,
                                                 bprop, prop);
 }
@@ -9718,6 +9940,9 @@ const struct elf_size_info elfNN_aarch64_size_info =
 #define bfd_elfNN_find_nearest_line            \
   elfNN_aarch64_find_nearest_line
 
+#define bfd_elfNN_get_synthetic_symtab         \
+  elfNN_aarch64_get_synthetic_symtab
+
 #define bfd_elfNN_mkobject                     \
   elfNN_aarch64_mkobject
 
index 894eb5590648da1bc07d2a8a943896806915c36d..b2adf169adf5c669e872055f5dceff1512d87671 100644 (file)
@@ -1,3 +1,11 @@
+2019-03-13  Sudakshina Das  <sudi.das@arm.com>
+           Szabolcs Nagy  <szabolcs.nagy@arm.com>
+
+       * readelf.c (get_aarch64_dynamic_type): New.
+       (get_dynamic_type): Use above for EM_AARCH64.
+       (dynamic_section_aarch64_val): New.
+       (process_dynamic_section): Use above for EM_AARCH64.
+
 2019-03-13  Sudakshina Das  <sudi.das@arm.com>
 
        * readelf.c (decode_aarch64_feature_1_and): New.
index 7446ffeee21961bf56b12ff16afbf52e5cd35387..f4775b439fc6a14a14699c88af3fe5f07648352e 100644 (file)
@@ -1797,6 +1797,17 @@ dump_relocations (Filedata *          filedata,
   return res;
 }
 
+static const char *
+get_aarch64_dynamic_type (unsigned long type)
+{
+  switch (type)
+    {
+    case DT_AARCH64_BTI_PLT:  return "AARCH64_BTI_PLT";
+    default:
+      return NULL;
+    }
+}
+
 static const char *
 get_mips_dynamic_type (unsigned long type)
 {
@@ -2170,6 +2181,9 @@ get_dynamic_type (Filedata * filedata, unsigned long type)
 
          switch (filedata->file_header.e_machine)
            {
+           case EM_AARCH64:
+             result = get_aarch64_dynamic_type (type);
+             break;
            case EM_MIPS:
            case EM_MIPS_RS3_LE:
              result = get_mips_dynamic_type (type);
@@ -9344,6 +9358,20 @@ process_unwind (Filedata * filedata)
   return TRUE;
 }
 
+static void
+dynamic_section_aarch64_val (Elf_Internal_Dyn * entry)
+{
+  switch (entry->d_tag)
+    {
+    case DT_AARCH64_BTI_PLT:
+      break;
+    default:
+      print_vma (entry->d_un.d_ptr, PREFIX_HEX);
+      break;
+    }
+  putchar ('\n');
+}
+
 static void
 dynamic_section_mips_val (Elf_Internal_Dyn * entry)
 {
@@ -10358,6 +10386,9 @@ process_dynamic_section (Filedata * filedata)
            {
              switch (filedata->file_header.e_machine)
                {
+               case EM_AARCH64:
+                 dynamic_section_aarch64_val (entry);
+                 break;
                case EM_MIPS:
                case EM_MIPS_RS3_LE:
                  dynamic_section_mips_val (entry);
index cf4353c9f500d6c9f6024a2ae3c82e32c5e064a9..d67f80f5cb302a178829d2b1b234a56b5f63a70b 100644 (file)
@@ -1,3 +1,8 @@
+2019-03-13  Sudakshina Das  <sudi.das@arm.com>
+           Szabolcs Nagy  <szabolcs.nagy@arm.com>
+
+       * elf/aarch64.h (DT_AARCH64_BTI_PLT): New.
+
 2019-03-13  Sudakshina Das  <sudi.das@arm.com>
 
        * elf/common.h (GNU_PROPERTY_AARCH64_FEATURE_1_AND): New.
index 3133ea6f6653eefc846da224e14fc6974cb2bf54..b86a1006297891d38f55f0c29d0ac51056b0c6e3 100644 (file)
@@ -35,6 +35,8 @@
                                                entry point.  */
 #define SHF_COMDEF             0x80000000   /* Section may be multiply defined
                                                in the input to a link step.  */
+/* Processor specific dynamic array tags.  */
+#define DT_AARCH64_BTI_PLT     (DT_LOPROC + 1)
 
 /* Relocation types.  */
 
index 32b53878508de1fd195ce2a02d4b6525afdaff41..151877da3f33076df4cbc76962a2d1108efd338e 100644 (file)
@@ -1,3 +1,22 @@
+2019-03-13  Sudakshina Das  <sudi.das@arm.com>
+           Szabolcs Nagy  <szabolcs.nagy@arm.com>
+
+       * NEWS: Document --force-bti.
+       * emultempl/aarch64elf.em (plt_type, bti_type, OPTION_FORCE_BTI): New.
+       (PARSE_AND_LIST_SHORTOPTS, PARSE_AND_LIST_OPTIONS): Add force-bti.
+       (PARSE_AND_LIST_ARGS_CASES): Handle OPTION_FORCE_BTI.
+       * testsuite/ld-aarch64/aarch64-elf.exp: Add all the tests below.
+       * testsuite/ld-aarch64/bti-plt-1.d: New test.
+       * testsuite/ld-aarch64/bti-plt-1.s: New test.
+       * testsuite/ld-aarch64/bti-plt-2.d: New test.
+       * testsuite/ld-aarch64/bti-plt-3.d: New test.
+       * testsuite/ld-aarch64/bti-plt-4.d: New test.
+       * testsuite/ld-aarch64/bti-plt-5.d: New test.
+       * testsuite/ld-aarch64/bti-plt-6.d: New test.
+       * testsuite/ld-aarch64/bti-plt-7.d: New test.
+       * testsuite/ld-aarch64/bti-plt-so.s: New test.
+       * testsuite/ld-aarch64/bti-plt.ld: New test.
+
 2019-03-13  Sudakshina Das  <sudi.das@arm.com>
 
        * NEWS: Document GNU_PROPERTY_AARCH64_FEATURE_1_BTI and
diff --git a/ld/NEWS b/ld/NEWS
index dcf11854f528028820cbe1983bbcdd5753d97eaf..ed8dfc5d6cfa25b67c954e82f4b4b315bfb185d4 100644 (file)
--- a/ld/NEWS
+++ b/ld/NEWS
@@ -10,6 +10,10 @@ Changes in 2.33:
 * Add support for GNU_PROPERTY_AARCH64_FEATURE_1_PAC in ELF GNU program
   properties in the AArch64 ELF linker.
 
+* Add --force-bti for AArch64 to enable GNU_PROPERTY_AARCH64_FEATURE_1_BTI
+  on output while warning about missing GNU_PROPERTY_AARCH64_FEATURE_1_BTI
+  on inputs and use PLTs protected with BTI.
+
 Changes in 2.32:
 
 * Report property change in linker map file when merging GNU properties.
index 45e40b510cf0da21e777f5734dcc9d1be54918a5..02243d9a79b4ea37c19bef527272ef601e005094 100644 (file)
@@ -33,6 +33,8 @@ static int pic_veneer = 0;
 static int fix_erratum_835769 = 0;
 static int fix_erratum_843419 = 0;
 static int no_apply_dynamic_relocs = 0;
+static aarch64_plt_type plt_type = PLT_NORMAL;
+static aarch64_enable_bti_type bti_type = BTI_NONE;
 
 static void
 gld${EMULATION_NAME}_before_parse (void)
@@ -308,12 +310,17 @@ aarch64_elf_create_output_section_statements (void)
       return;
     }
 
+  aarch64_bti_pac_info bp_info;
+  bp_info.plt_type = plt_type;
+  bp_info.bti_type = bti_type;
+
   bfd_elf${ELFSIZE}_aarch64_set_options (link_info.output_bfd, &link_info,
                                 no_enum_size_warning,
                                 no_wchar_size_warning,
                                 pic_veneer,
                                 fix_erratum_835769, fix_erratum_843419,
-                                no_apply_dynamic_relocs);
+                                no_apply_dynamic_relocs,
+                                bp_info);
 
   stub_file = lang_add_input_file ("linker stubs",
                                   lang_input_file_is_fake_enum,
@@ -365,6 +372,7 @@ PARSE_AND_LIST_PROLOGUE='
 #define OPTION_FIX_ERRATUM_835769      313
 #define OPTION_FIX_ERRATUM_843419      314
 #define OPTION_NO_APPLY_DYNAMIC_RELOCS 315
+#define OPTION_FORCE_BTI               316
 '
 
 PARSE_AND_LIST_SHORTOPTS=p
@@ -378,6 +386,7 @@ PARSE_AND_LIST_LONGOPTS='
   { "fix-cortex-a53-835769", no_argument, NULL, OPTION_FIX_ERRATUM_835769},
   { "fix-cortex-a53-843419", no_argument, NULL, OPTION_FIX_ERRATUM_843419},
   { "no-apply-dynamic-relocs", no_argument, NULL, OPTION_NO_APPLY_DYNAMIC_RELOCS},
+  { "force-bti", no_argument, NULL, OPTION_FORCE_BTI},
 '
 
 PARSE_AND_LIST_OPTIONS='
@@ -398,6 +407,7 @@ PARSE_AND_LIST_OPTIONS='
   fprintf (file, _("  --fix-cortex-a53-835769      Fix erratum 835769\n"));
   fprintf (file, _("  --fix-cortex-a53-843419      Fix erratum 843419\n"));
   fprintf (file, _("  --no-apply-dynamic-relocs    Do not apply link-time values for dynamic relocations\n"));
+  fprintf (file, _("  --force-bti                  Turn on Branch Target Identification mechanism and generate PLTs with BTI. Generate warnings for missing BTI on inputs\n"));
 '
 
 PARSE_AND_LIST_ARGS_CASES='
@@ -429,6 +439,11 @@ PARSE_AND_LIST_ARGS_CASES='
       no_apply_dynamic_relocs = 1;
       break;
 
+    case OPTION_FORCE_BTI:
+      plt_type |= PLT_BTI;
+      bti_type = BTI_WARN;
+      break;
+
     case OPTION_STUBGROUP_SIZE:
       {
        const char *end;
index c6fefbbd5c3f7e5516086c7eca0e056ae243d36d..906534b230c8905fb97a6739e1c1411683455fe3 100644 (file)
@@ -374,6 +374,8 @@ 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"
+run_dump_test "bti-plt-1"
+run_dump_test "bti-plt-2"
 
 set aarch64elflinktests {
   {"ld-aarch64/so with global symbol" "-shared" "" "" {copy-reloc-so.s}
@@ -389,6 +391,14 @@ set aarch64elflinktests {
   {"ld-aarch64/func sym hash opt for exe"
    "-e0 --hash-style=gnu tmpdir/func-in-so.so" "" ""
     {func-sym-hash-opt.s} {{readelf --dyn-sym func-sym-hash-opt.d}} "hash-opt"}
+  {"Build bti-plt-so for PLT tests" "-shared" "" "" {bti-plt-so.s}
+    {} "libbti-plt-so.so"}
 }
 
 run_ld_link_tests $aarch64elflinktests
+
+run_dump_test "bti-plt-3"
+run_dump_test "bti-plt-4"
+run_dump_test "bti-plt-5"
+run_dump_test "bti-plt-6"
+run_dump_test "bti-plt-7"
diff --git a/ld/testsuite/ld-aarch64/bti-plt-1.d b/ld/testsuite/ld-aarch64/bti-plt-1.d
new file mode 100644 (file)
index 0000000..b7b58a8
--- /dev/null
@@ -0,0 +1,32 @@
+#name: Check --force-bti emits BTI PLT (shared)
+#source: bti-plt-1.s
+#as: -mabi=lp64
+#ld: -shared --force-bti -T bti-plt.ld
+#objdump: -dr -j .plt
+
+[^:]*: *file format elf64-.*aarch64
+
+Disassembly of section \.plt:
+
+[0-9]+ <.*>:
+.*:    d503245f        bti     c
+.*:    a9bf7bf0        stp     x16, x30, \[sp, #-16\]!
+.*:    90000090        adrp    x16, 28000 <_GLOBAL_OFFSET_TABLE_>
+.*:    f9400e11        ldr     x17, \[x16, #24\]
+.*:    91006210        add     x16, x16, #0x18
+.*:    d61f0220        br      x17
+.*:    d503201f        nop
+.*:    d503201f        nop
+.*:    d503201f        nop
+
+[0-9]+ <.*>:
+.*:    90000090        adrp    x16, 28000 <_GLOBAL_OFFSET_TABLE_>
+.*:    f9401211        ldr     x17, \[x16, #32\]
+.*:    91008210        add     x16, x16, #0x20
+.*:    d61f0220        br      x17
+
+[0-9]+ <.*>:
+.*:    90000090        adrp    x16, 28000 <_GLOBAL_OFFSET_TABLE_>
+.*:    f9401611        ldr     x17, \[x16, #40\]
+.*:    9100a210        add     x16, x16, #0x28
+.*:    d61f0220        br      x17
diff --git a/ld/testsuite/ld-aarch64/bti-plt-1.s b/ld/testsuite/ld-aarch64/bti-plt-1.s
new file mode 100644 (file)
index 0000000..78e1aaa
--- /dev/null
@@ -0,0 +1,21 @@
+       .text
+       .globl _start
+       .type _start,@function
+_start:
+       bl foo
+       bl bar
+       .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:
diff --git a/ld/testsuite/ld-aarch64/bti-plt-2.d b/ld/testsuite/ld-aarch64/bti-plt-2.d
new file mode 100644 (file)
index 0000000..c26e47a
--- /dev/null
@@ -0,0 +1,11 @@
+#name: Check --force-bti emits BTI feature (shared)
+#source: bti-plt-1.s
+#source: bti-plt-2.s
+#as: -mabi=lp64
+#ld: -shared --force-bti -T bti-plt.ld
+#readelf: -n
+
+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/bti-plt-2.s b/ld/testsuite/ld-aarch64/bti-plt-2.s
new file mode 100644 (file)
index 0000000..fff945c
--- /dev/null
@@ -0,0 +1,21 @@
+       .text
+       .globl _start
+       .type _start,@function
+func2:
+       bl foo2
+       bl bar2
+       .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:
diff --git a/ld/testsuite/ld-aarch64/bti-plt-3.d b/ld/testsuite/ld-aarch64/bti-plt-3.d
new file mode 100644 (file)
index 0000000..0d4c467
--- /dev/null
@@ -0,0 +1,34 @@
+#name: Check --force-bti emits BTI PLT (exec)
+#source: bti-plt-1.s
+#as: -mabi=lp64
+#ld: --force-bti -e _start -T bti-plt.ld -L./tmpdir -lbti-plt-so
+#objdump: -dr -j .plt
+
+[^:]*: *file format elf64-.*aarch64
+
+Disassembly of section \.plt:
+
+[0-9]+ <.*>:
+.*:    d503245f        bti     c
+.*:    a9bf7bf0        stp     x16, x30, \[sp, #-16\]!
+.*:    90000090        adrp    x16, 28000 <_GLOBAL_OFFSET_TABLE_>
+.*:    f9400e11        ldr     x17, \[x16, #24\]
+.*:    91006210        add     x16, x16, #0x18
+.*:    d61f0220        br      x17
+.*:    d503201f        nop
+.*:    d503201f        nop
+.*:    d503201f        nop
+
+[0-9]+ <.*>:
+.*:    d503245f        bti     c
+.*:    90000090        adrp    x16, 28000 <_GLOBAL_OFFSET_TABLE_>
+.*:    f9401211        ldr     x17, \[x16, #32\]
+.*:    91008210        add     x16, x16, #0x20
+.*:    d61f0220        br      x17
+
+[0-9]+ <.*>:
+.*:    d503245f        bti     c
+.*:    90000090        adrp    x16, 28000 <_GLOBAL_OFFSET_TABLE_>
+.*:    f9401611        ldr     x17, \[x16, #40\]
+.*:    9100a210        add     x16, x16, #0x28
+.*:    d61f0220        br      x17
diff --git a/ld/testsuite/ld-aarch64/bti-plt-4.d b/ld/testsuite/ld-aarch64/bti-plt-4.d
new file mode 100644 (file)
index 0000000..90aeed2
--- /dev/null
@@ -0,0 +1,10 @@
+#name: Check --force-bti emits BTI feature (exec)
+#source: bti-plt-1.s
+#as: -mabi=lp64
+#ld: --force-bti -e _start -T bti-plt.ld -L./tmpdir -lbti-plt-so
+#readelf: -n
+
+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/bti-plt-5.d b/ld/testsuite/ld-aarch64/bti-plt-5.d
new file mode 100644 (file)
index 0000000..01231b6
--- /dev/null
@@ -0,0 +1,28 @@
+#name: BTI PLT with only GNU PROP
+#source: property-bti-pac1.s
+#as: -mabi=lp64 -defsym __property_bti__=1
+#ld: -e _start -L./tmpdir -lbti-plt-so
+#objdump: -dr -j .plt
+#target: *linux*
+
+[^:]*: *file format elf64-.*aarch64
+
+Disassembly of section \.plt:
+
+[0-9a-f]+ <.*>:
+.*:    d503245f        bti     c
+.*:    a9bf7bf0        stp     x16, x30, \[sp, #-16\]!
+.*:    90000090        adrp    x16, 410000 <_start\+0xfd28>
+.*:    f9421611        ldr     x17, \[x16, #1064\]
+.*:    9110a210        add     x16, x16, #0x428
+.*:    d61f0220        br      x17
+.*:    d503201f        nop
+.*:    d503201f        nop
+.*:    d503201f        nop
+
+[0-9a-f]+ <.*>:
+.*:    d503245f        bti     c
+.*:    90000090        adrp    x16, 410000 <_start\+0xfd28>
+.*:    f9421a11        ldr     x17, \[x16, #1072\]
+.*:    9110c210        add     x16, x16, #0x430
+.*:    d61f0220        br      x17
diff --git a/ld/testsuite/ld-aarch64/bti-plt-6.d b/ld/testsuite/ld-aarch64/bti-plt-6.d
new file mode 100644 (file)
index 0000000..c7d5169
--- /dev/null
@@ -0,0 +1,15 @@
+#name: Warn with one missing GNU NOTE BTI input
+#source: property-bti-pac1.s
+#source: property-bti-pac2.s
+#as: -mabi=lp64 -defsym __property_pac__=1
+#ld: -shared --force-bti
+#warning: .*: warning: BTI turned on by --force-bti.*$
+#readelf: -n
+
+# Should warn about the missing input BTI NOTE but should
+# still mark output as BTI
+
+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/bti-plt-7.d b/ld/testsuite/ld-aarch64/bti-plt-7.d
new file mode 100644 (file)
index 0000000..625f284
--- /dev/null
@@ -0,0 +1,15 @@
+#name: Warn when neither inputs has GNU NOTE BTI
+#source: property-bti-pac1.s
+#source: plt_mapping_symbol.s
+#as: -mabi=lp64
+#ld: -shared --force-bti
+#warning: .*: warning: BTI turned on by --force-bti.*$
+#readelf: -n
+
+# Should warn about the missing input BTI NOTE but should
+# still mark output as BTI
+
+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/bti-plt-so.s b/ld/testsuite/ld-aarch64/bti-plt-so.s
new file mode 100644 (file)
index 0000000..2c11356
--- /dev/null
@@ -0,0 +1,41 @@
+       .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
+bar:
+       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   bar, .-bar
+       .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:
diff --git a/ld/testsuite/ld-aarch64/bti-plt.ld b/ld/testsuite/ld-aarch64/bti-plt.ld
new file mode 100644 (file)
index 0000000..8682623
--- /dev/null
@@ -0,0 +1,14 @@
+OUTPUT_ARCH(aarch64)
+ENTRY(_start)
+SECTIONS
+{
+  . = 0x10000;
+  .rela.plt       : { *(.rela.plt) *(.rela.iplt) }
+  . = 0x18000;
+  .plt            : { *(.plt) *(.iplt) }
+  . = 0x20000;
+  .text           : { *(.text) }
+  . = 0x28000;
+  .got            : { *(.got) *(.got.plt) }
+  .ARM.attributes 0 : { *(.ARM.atttributes) }
+}