summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
diff options
context:
space:
mode:
authorOliver Stannard <oliver.stannard@arm.com>2018-10-08 14:04:24 +0000
committerOliver Stannard <oliver.stannard@arm.com>2018-10-08 14:04:24 +0000
commit250e5a5b655f67d58470533a7b21ce38d7946d50 (patch)
treeadff3250f0798fad85f09d5d2c0b8e6ff4df469b /llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
parent1aedf203dd17e58be86c61a6fd674b3f8d41b296 (diff)
downloadbcm5719-llvm-250e5a5b655f67d58470533a7b21ce38d7946d50.tar.gz
bcm5719-llvm-250e5a5b655f67d58470533a7b21ce38d7946d50.zip
[AArch64][v8.5A] Branch Target Identification code-generation pass
The Branch Target Identification extension, introduced to AArch64 in Armv8.5-A, adds the BTI instruction, which is used to mark valid targets of indirect branches. When enabled, the processor will trap if an instruction in a protected page tries to perform an indirect branch to any instruction other than a BTI. The BTI instruction uses encodings which were NOPs in earlier versions of the architecture, so BTI-enabled code will still run on earlier hardware, just without the extra protection. There are 3 variants of the BTI instruction, which are valid targets for different kinds or branches: - BTI C can be targeted by call instructions, and is inteneded to be used at function entry points. These are the BLR instruction, as well as BR with x16 or x17. These BR instructions are allowed for use in PLT entries, and we can also use them to allow indirect tail-calls. - BTI J can be targeted by BR only, and is intended to be used by jump tables. - BTI JC acts ab both a BTI C and a BTI J instruction, and can be targeted by any BLR or BR instruction. Note that RET instructions are not restricted by branch target identification, the reason for this is that return addresses can be protected more effectively using return address signing. Direct branches and calls are also unaffected, as it is assumed that an attacker cannot modify executable pages (if they could, they wouldn't need to do a ROP/JOP attack). This patch adds a MachineFunctionPass which: - Adds a BTI C at the start of every function which could be indirectly called (either because it is address-taken, or externally visible so could be address-taken in another translation unit). - Adds a BTI J at the start of every basic block which could be indirectly branched to. This could be either done by a jump table, or by taking the address of the block (e.g. the using GCC label values extension). We only need to use BTI JC when a function is indirectly-callable, and takes the address of the entry block. I've not been able to trigger this from C or IR, but I've included a MIR test just in case. Using BTI C at function entries relies on the fact that no other code in BTI-protected pages uses indirect tail-calls, unless they use x16 or x17 to hold the address. I'll add that code-generation restriction as a separate patch. Differential revision: https://reviews.llvm.org/D52867 llvm-svn: 343967
Diffstat (limited to 'llvm/lib/Target/AArch64/AArch64TargetMachine.cpp')
-rw-r--r--llvm/lib/Target/AArch64/AArch64TargetMachine.cpp9
1 files changed, 9 insertions, 0 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
index a66f5277f24..e183288d8df 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
@@ -141,6 +141,11 @@ static cl::opt<int> EnableGlobalISelAtO(
static cl::opt<bool> EnableFalkorHWPFFix("aarch64-enable-falkor-hwpf-fix",
cl::init(true), cl::Hidden);
+static cl::opt<bool>
+ EnableBranchTargets("aarch64-enable-branch-targets", cl::Hidden,
+ cl::desc("Enable the AAcrh64 branch target pass"),
+ cl::init(true));
+
extern "C" void LLVMInitializeAArch64Target() {
// Register the target.
RegisterTargetMachine<AArch64leTargetMachine> X(getTheAArch64leTarget());
@@ -151,6 +156,7 @@ extern "C" void LLVMInitializeAArch64Target() {
initializeAArch64A53Fix835769Pass(*PR);
initializeAArch64A57FPLoadBalancingPass(*PR);
initializeAArch64AdvSIMDScalarPass(*PR);
+ initializeAArch64BranchTargetsPass(*PR);
initializeAArch64CollectLOHPass(*PR);
initializeAArch64ConditionalComparesPass(*PR);
initializeAArch64ConditionOptimizerPass(*PR);
@@ -537,6 +543,9 @@ void AArch64PassConfig::addPreEmitPass() {
if (BranchRelaxation)
addPass(&BranchRelaxationPassID);
+ if (EnableBranchTargets)
+ addPass(createAArch64BranchTargetsPass());
+
if (TM->getOptLevel() != CodeGenOpt::None && EnableCollectLOH &&
TM->getTargetTriple().isOSBinFormatMachO())
addPass(createAArch64CollectLOHPass());
OpenPOWER on IntegriCloud