diff options
author | Andrew Paverd <andrew.paverd@microsoft.com> | 2019-10-28 13:22:19 +0000 |
---|---|---|
committer | David Chisnall <David.Chisnall@microsoft.com> | 2019-10-28 15:19:39 +0000 |
commit | d157a9bc8ba1085cc4808c6941412322a7fd884e (patch) | |
tree | c675a8e26a4bf08d0cd8abcde693780dd5bd3859 /llvm/lib/CodeGen/AsmPrinter | |
parent | a233e7d7cb642ada49985426c23aa3c6a4c98690 (diff) | |
download | bcm5719-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/CodeGen/AsmPrinter')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp | 22 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h | 9 |
3 files changed, 29 insertions, 8 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 73c53d6c4af..3692a03c268 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -139,7 +139,7 @@ static const char *const DbgTimerDescription = "Debug Info Emission"; static const char *const EHTimerName = "write_exception"; static const char *const EHTimerDescription = "DWARF Exception Writer"; static const char *const CFGuardName = "Control Flow Guard"; -static const char *const CFGuardDescription = "Control Flow Guard Tables"; +static const char *const CFGuardDescription = "Control Flow Guard"; static const char *const CodeViewLineTablesGroupName = "linetables"; static const char *const CodeViewLineTablesGroupDescription = "CodeView Line Tables"; @@ -381,12 +381,12 @@ bool AsmPrinter::doInitialization(Module &M) { EHTimerDescription, DWARFGroupName, DWARFGroupDescription); + // Emit tables for any value of cfguard flag (i.e. cfguard=1 or cfguard=2). if (mdconst::extract_or_null<ConstantInt>( - MMI->getModule()->getModuleFlag("cfguardtable"))) + MMI->getModule()->getModuleFlag("cfguard"))) Handlers.emplace_back(std::make_unique<WinCFGuard>(this), CFGuardName, CFGuardDescription, DWARFGroupName, DWARFGroupDescription); - return false; } diff --git a/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp b/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp index 290be81c6ba..f071a2583e5 100644 --- a/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp @@ -6,7 +6,8 @@ // //===----------------------------------------------------------------------===// // -// This file contains support for writing Win64 exception info into asm files. +// This file contains support for writing the metadata for Windows Control Flow +// Guard, including address-taken functions, and valid longjmp targets. // //===----------------------------------------------------------------------===// @@ -29,16 +30,33 @@ WinCFGuard::WinCFGuard(AsmPrinter *A) : AsmPrinterHandler(), Asm(A) {} WinCFGuard::~WinCFGuard() {} +void WinCFGuard::endFunction(const MachineFunction *MF) { + + // Skip functions without any longjmp targets. + if (MF->getLongjmpTargets().empty()) + return; + + // Copy the function's longjmp targets to a module-level list. + LongjmpTargets.insert(LongjmpTargets.end(), MF->getLongjmpTargets().begin(), + MF->getLongjmpTargets().end()); +} + void WinCFGuard::endModule() { const Module *M = Asm->MMI->getModule(); std::vector<const Function *> Functions; for (const Function &F : *M) if (F.hasAddressTaken()) Functions.push_back(&F); - if (Functions.empty()) + if (Functions.empty() && LongjmpTargets.empty()) return; auto &OS = *Asm->OutStreamer; OS.SwitchSection(Asm->OutContext.getObjectFileInfo()->getGFIDsSection()); for (const Function *F : Functions) OS.EmitCOFFSymbolIndex(Asm->getSymbol(F)); + + // Emit the symbol index of each longjmp target. + OS.SwitchSection(Asm->OutContext.getObjectFileInfo()->getGLJMPSection()); + for (const MCSymbol *S : LongjmpTargets) { + OS.EmitCOFFSymbolIndex(S); + } } diff --git a/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h b/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h index def0a59ab00..494a153b05b 100644 --- a/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h +++ b/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h @@ -6,7 +6,8 @@ // //===----------------------------------------------------------------------===// // -// This file contains support for writing windows exception info into asm files. +// This file contains support for writing the metadata for Windows Control Flow +// Guard, including address-taken functions, and valid longjmp targets. // //===----------------------------------------------------------------------===// @@ -15,12 +16,14 @@ #include "llvm/CodeGen/AsmPrinterHandler.h" #include "llvm/Support/Compiler.h" +#include <vector> namespace llvm { class LLVM_LIBRARY_VISIBILITY WinCFGuard : public AsmPrinterHandler { /// Target of directive emission. AsmPrinter *Asm; + std::vector<const MCSymbol *> LongjmpTargets; public: WinCFGuard(AsmPrinter *A); @@ -28,7 +31,7 @@ public: void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override {} - /// Emit the Control Flow Guard function ID table + /// Emit the Control Flow Guard function ID table. void endModule() override; /// Gather pre-function debug information. @@ -39,7 +42,7 @@ public: /// Gather post-function debug information. /// Please note that some AsmPrinter implementations may not call /// beginFunction at all. - void endFunction(const MachineFunction *MF) override {} + void endFunction(const MachineFunction *MF) override; /// Process beginning of an instruction. void beginInstruction(const MachineInstr *MI) override {} |