OSDN Git Service

[AArch64][v8.5A] Branch Target Identification code-generation pass
authorOliver Stannard <oliver.stannard@arm.com>
Mon, 8 Oct 2018 14:04:24 +0000 (14:04 +0000)
committerOliver Stannard <oliver.stannard@arm.com>
Mon, 8 Oct 2018 14:04:24 +0000 (14:04 +0000)
commit4bc81028d48c0ab07e7b429d2a98ed6d15140a23
treeca765d59af6a19df2123a01dd78a72229bd883ae
parentc190984a44d4c81422bac2e0fe528bbc1dd3d7ca
[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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@343967 91177308-0d34-0410-b5e6-96231b3b80d8
lib/Target/AArch64/AArch64.h
lib/Target/AArch64/AArch64BranchTargets.cpp [new file with mode: 0644]
lib/Target/AArch64/AArch64TargetMachine.cpp
lib/Target/AArch64/CMakeLists.txt
test/CodeGen/AArch64/O0-pipeline.ll
test/CodeGen/AArch64/O3-pipeline.ll
test/CodeGen/AArch64/branch-target-enforcment.mir [new file with mode: 0644]