summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR
diff options
context:
space:
mode:
authorAndrew Paverd <andrew.paverd@microsoft.com>2019-10-28 13:22:19 +0000
committerDavid Chisnall <David.Chisnall@microsoft.com>2019-10-28 15:19:39 +0000
commitd157a9bc8ba1085cc4808c6941412322a7fd884e (patch)
treec675a8e26a4bf08d0cd8abcde693780dd5bd3859 /llvm/lib/IR
parenta233e7d7cb642ada49985426c23aa3c6a4c98690 (diff)
downloadbcm5719-llvm-d157a9bc8ba1085cc4808c6941412322a7fd884e.tar.gz
bcm5719-llvm-d157a9bc8ba1085cc4808c6941412322a7fd884e.zip
Add Windows Control Flow Guard checks (/guard:cf).
Summary: A new function pass (Transforms/CFGuard/CFGuard.cpp) inserts CFGuard checks on indirect function calls, using either the check mechanism (X86, ARM, AArch64) or or the dispatch mechanism (X86-64). The check mechanism requires a new calling convention for the supported targets. The dispatch mechanism adds the target as an operand bundle, which is processed by SelectionDAG. Another pass (CodeGen/CFGuardLongjmp.cpp) identifies and emits valid longjmp targets, as required by /guard:cf. This feature is enabled using the `cfguard` CC1 option. Reviewers: thakis, rnk, theraven, pcc Subscribers: ychen, hans, metalcanine, dmajor, tomrittervg, alex, mehdi_amini, mgorny, javed.absar, kristof.beyls, hiraditya, steven_wu, dexonsmith, cfe-commits, llvm-commits Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D65761
Diffstat (limited to 'llvm/lib/IR')
-rw-r--r--llvm/lib/IR/AsmWriter.cpp1
-rw-r--r--llvm/lib/IR/LLVMContext.cpp5
-rw-r--r--llvm/lib/IR/Verifier.cpp12
3 files changed, 15 insertions, 3 deletions
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index b0c26e0ecaf..f811c842cf5 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -353,6 +353,7 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
case CallingConv::CXX_FAST_TLS: Out << "cxx_fast_tlscc"; break;
case CallingConv::GHC: Out << "ghccc"; break;
case CallingConv::Tail: Out << "tailcc"; break;
+ case CallingConv::CFGuard_Check: Out << "cfguard_checkcc"; break;
case CallingConv::X86_StdCall: Out << "x86_stdcallcc"; break;
case CallingConv::X86_FastCall: Out << "x86_fastcallcc"; break;
case CallingConv::X86_ThisCall: Out << "x86_thiscallcc"; break;
diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp
index 5e8772186a2..cb13b27aa50 100644
--- a/llvm/lib/IR/LLVMContext.cpp
+++ b/llvm/lib/IR/LLVMContext.cpp
@@ -62,6 +62,11 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
"gc-transition operand bundle id drifted!");
(void)GCTransitionEntry;
+ auto *CFGuardTargetEntry = pImpl->getOrInsertBundleTag("cfguardtarget");
+ assert(CFGuardTargetEntry->second == LLVMContext::OB_cfguardtarget &&
+ "cfguardtarget operand bundle id drifted!");
+ (void)CFGuardTargetEntry;
+
SyncScope::ID SingleThreadSSID =
pImpl->getOrInsertSyncScopeID("singlethread");
assert(SingleThreadSSID == SyncScope::SingleThread &&
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index b17fc433ed7..497dc394d96 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -2975,10 +2975,10 @@ void Verifier::visitCallBase(CallBase &Call) {
if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
visitIntrinsicCall(ID, Call);
- // Verify that a callsite has at most one "deopt", at most one "funclet" and
- // at most one "gc-transition" operand bundle.
+ // Verify that a callsite has at most one "deopt", at most one "funclet", at
+ // most one "gc-transition", and at most one "cfguardtarget" operand bundle.
bool FoundDeoptBundle = false, FoundFuncletBundle = false,
- FoundGCTransitionBundle = false;
+ FoundGCTransitionBundle = false, FoundCFGuardTargetBundle = false;
for (unsigned i = 0, e = Call.getNumOperandBundles(); i < e; ++i) {
OperandBundleUse BU = Call.getOperandBundleAt(i);
uint32_t Tag = BU.getTagID();
@@ -2997,6 +2997,12 @@ void Verifier::visitCallBase(CallBase &Call) {
Assert(isa<FuncletPadInst>(BU.Inputs.front()),
"Funclet bundle operands should correspond to a FuncletPadInst",
Call);
+ } else if (Tag == LLVMContext::OB_cfguardtarget) {
+ Assert(!FoundCFGuardTargetBundle,
+ "Multiple CFGuardTarget operand bundles", Call);
+ FoundCFGuardTargetBundle = true;
+ Assert(BU.Inputs.size() == 1,
+ "Expected exactly one cfguardtarget bundle operand", Call);
}
}
OpenPOWER on IntegriCloud