Skip to content

Commit

Permalink
Add -fcf-protection.
Browse files Browse the repository at this point in the history
Resolves issue #4435
  • Loading branch information
JohanEngelen committed Jul 11, 2023
1 parent d4f2bed commit f3eff0c
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 0 deletions.
13 changes: 13 additions & 0 deletions driver/cl_options_instrumentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,19 @@ llvm::StringRef getXRayInstructionThresholdString() {
return thresholdString;
}

cl::opt<CFProtectionType> fCFProtection(
"fcf-protection",
cl::desc("Instrument control-flow architecture protection"), cl::ZeroOrMore,
cl::ValueOptional,
cl::values(clEnumValN(CFProtectionType::None, "none", ""),
clEnumValN(CFProtectionType::Branch, "branch", ""),
clEnumValN(CFProtectionType::Return, "return", ""),
clEnumValN(CFProtectionType::Full, "full", ""),
clEnumValN(CFProtectionType::Full, "",
"") // default to "full" if no argument specified
),
cl::init(CFProtectionType::None));

void initializeInstrumentationOptionsFromCmdline(const llvm::Triple &triple) {
if (ASTPGOInstrGenFile.getNumOccurrences() > 0) {
pgoMode = PGO_ASTBasedInstr;
Expand Down
3 changes: 3 additions & 0 deletions driver/cl_options_instrumentation.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ extern cl::opt<bool> instrumentFunctions;
extern cl::opt<bool> fXRayInstrument;
llvm::StringRef getXRayInstructionThresholdString();

enum class CFProtectionType { None, Branch, Return, Full };
extern cl::opt<CFProtectionType> fCFProtection;

/// This initializes the instrumentation options, and checks the validity of the
/// commandline flags. targetTriple should be initialized before calling this.
/// It should be called only once.
Expand Down
14 changes: 14 additions & 0 deletions driver/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,20 @@ void registerPredefinedVersions() {
VersionCondition::addPredefinedGlobalIdent("LDC_ThreadSanitizer");
}

switch (opts::fCFProtection) {
case opts::CFProtectionType::Branch:
VersionCondition::addPredefinedGlobalIdent("__CET_1__");
break;
case opts::CFProtectionType::Return:
VersionCondition::addPredefinedGlobalIdent("__CET_2__");
break;
case opts::CFProtectionType::Full:
VersionCondition::addPredefinedGlobalIdent("__CET_3__");
break;
case opts::CFProtectionType::None:
break;
}

#if LDC_LLVM_VER >= 1400
// A version identifier for whether opaque pointers are enabled or not. (needed e.g. for intrinsic mangling)
if (!getGlobalContext().supportsTypedPointers()) {
Expand Down
15 changes: 15 additions & 0 deletions gen/modules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -393,8 +393,21 @@ void registerModuleInfo(Module *m) {
emitModuleRefToSection(mangle, moduleInfoSym);
}
}

void addModuleFlags(llvm::Module &m) {
if (opts::fCFProtection == opts::CFProtectionType::Return ||
opts::fCFProtection == opts::CFProtectionType::Full) {
m.addModuleFlag(llvm::Module::Min, "cf-protection-return", 1);
}

if (opts::fCFProtection == opts::CFProtectionType::Branch ||
opts::fCFProtection == opts::CFProtectionType::Full) {
m.addModuleFlag(llvm::Module::Min, "cf-protection-branch", 1);
}
}

} // anonymous namespace

void codegenModule(IRState *irs, Module *m) {
TimeTraceScope timeScope("Generate IR", m->toChars(), m->loc);

Expand Down Expand Up @@ -444,6 +457,8 @@ void codegenModule(IRState *irs, Module *m) {
addCoverageAnalysisInitializer(m);
}

addModuleFlags(irs->module);

gIR = nullptr;
irs->dmodule = nullptr;
}
28 changes: 28 additions & 0 deletions tests/codegen/fcf_protection.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Test -fcf-protection

// REQUIRES: target_X86

// RUN: %ldc -mtriple=x86_64-linux-gnu -output-ll -of=%t.ll %s && FileCheck %s --check-prefix=NOTHING < %t.ll

// RUN: %ldc -mtriple=x86_64-linux-gnu -output-ll -of=%t_branch.ll %s --fcf-protection=branch -d-version=BRANCH && FileCheck %s --check-prefix=BRANCH < %t_branch.ll
// RUN: %ldc -mtriple=x86_64-linux-gnu -output-ll -of=%t_return.ll %s --fcf-protection=return -d-version=RETURN && FileCheck %s --check-prefix=RETURN < %t_return.ll
// RUN: %ldc -mtriple=x86_64-linux-gnu -output-ll -of=%t_full.ll %s --fcf-protection=full -d-version=FULL && FileCheck %s --check-prefix=FULL < %t_full.ll
// RUN: %ldc -mtriple=x86_64-linux-gnu -output-ll -of=%t_noarg.ll %s --fcf-protection -d-version=FULL && FileCheck %s --check-prefix=FULL < %t_noarg.ll

// NOTHING-NOT: cf-prot
// BRANCH-DAG: "cf-protection-branch", i32 1
// RETURN-DAG: "cf-protection-return", i32 1
// FULL-DAG: "cf-protection-branch", i32 1
// FULL-DAG: "cf-protection-return", i32 1

void foo() {}

version(BRANCH) {
version(__CET_1__) {} else { static assert(false); };
}
version(RETURN) {
version(__CET_2__) {} else { static assert(false); };
}
version(FULL) {
version(__CET_3__) {} else { static assert(false); };
}

0 comments on commit f3eff0c

Please sign in to comment.