[BFD, LD, AArch64, 2/3] Add --force-bti to enable BTI and to select BTI enabled PLTs

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.
This commit is contained in:
Sudakshina Das 2019-03-13 10:54:30 +00:00
parent cd702818c6
commit 37c18eedff
23 changed files with 687 additions and 21 deletions

View 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

View 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)

View 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)

View File

@ -267,6 +267,10 @@
#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

View 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.

View 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);

View 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.

View 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. */

View 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

View File

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

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

View 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"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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