diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/CodeGen/CodeGen.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/CodeGen/NoopInsertion.cpp | 101 | ||||
-rw-r--r-- | llvm/lib/CodeGen/Passes.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86InstrInfo.cpp | 61 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86InstrInfo.h | 7 |
6 files changed, 174 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt index 48bf3545e73..672b6bae2dd 100644 --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -71,6 +71,7 @@ add_llvm_library(LLVMCodeGen MachineSink.cpp MachineTraceMetrics.cpp MachineVerifier.cpp + NoopInsertion.cpp OcamlGC.cpp OptimizePHIs.cpp PHIElimination.cpp diff --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp index 307dec548fc..fdb89438115 100644 --- a/llvm/lib/CodeGen/CodeGen.cpp +++ b/llvm/lib/CodeGen/CodeGen.cpp @@ -51,6 +51,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) { initializeMachineSchedulerPass(Registry); initializeMachineSinkingPass(Registry); initializeMachineVerifierPassPass(Registry); + initializeNoopInsertionPass(Registry); initializeOptimizePHIsPass(Registry); initializePHIEliminationPass(Registry); initializePeepholeOptimizerPass(Registry); diff --git a/llvm/lib/CodeGen/NoopInsertion.cpp b/llvm/lib/CodeGen/NoopInsertion.cpp new file mode 100644 index 00000000000..f2291b8e99c --- /dev/null +++ b/llvm/lib/CodeGen/NoopInsertion.cpp @@ -0,0 +1,101 @@ +//===- NoopInsertion.cpp - Noop Insertion ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass adds fine-grained diversity by displacing code using randomly +// placed (optionally target supplied) Noop instructions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/NoopInsertion.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/RandomNumberGenerator.h" +#include "llvm/Target/TargetInstrInfo.h" +using namespace llvm; + +#define DEBUG_TYPE "noop-insertion" + +static cl::opt<unsigned> NoopInsertionPercentage( + "noop-insertion-percentage", + cl::desc("Percentage of instructions that have Noops prepended"), + cl::init(25)); // Default is a good balance between entropy and + // performance impact + +static cl::opt<unsigned> MaxNoopsPerInstruction( + "max-noops-per-instruction", + llvm::cl::desc("Maximum number of Noops per instruction"), + llvm::cl::init(1)); + +STATISTIC(InsertedNoops, + "Total number of noop type instructions inserted for diversity"); + +char NoopInsertion::ID = 0; +char &llvm::NoopInsertionID = NoopInsertion::ID; +INITIALIZE_PASS(NoopInsertion, "noop-insertion", + "Noop Insertion for fine-grained code randomization", false, + false) + +NoopInsertion::NoopInsertion() : MachineFunctionPass(ID) { + initializeNoopInsertionPass(*PassRegistry::getPassRegistry()); + + // clamp percentage to 100 + if (NoopInsertionPercentage > 100) + NoopInsertionPercentage = 100; +} + +void NoopInsertion::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool NoopInsertion::runOnMachineFunction(MachineFunction &Fn) { + // The RNG must be initialized on first use so we have a Module to + // construct it from + if (!RNG) + RNG.reset(Fn.getFunction()->getParent()->createRNG(this)); + + const TargetInstrInfo *TII = Fn.getSubtarget().getInstrInfo(); + + unsigned FnInsertedNoopCount = 0; + + for (auto &BB : Fn) { + MachineBasicBlock::iterator FirstTerm = BB.getFirstTerminator(); + + for (MachineBasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; + ++I) { + if (I->isPseudo()) + continue; + + // Insert random number of Noop-like instructions. + for (unsigned i = 0; i < MaxNoopsPerInstruction; i++) { + if (Distribution(*RNG) >= NoopInsertionPercentage) + continue; + + TII->insertNoop(BB, I, *RNG); + + ++FnInsertedNoopCount; + } + + if (I == FirstTerm) + break; + } + } + + InsertedNoops += FnInsertedNoopCount; + + return FnInsertedNoopCount > 0; +} diff --git a/llvm/lib/CodeGen/Passes.cpp b/llvm/lib/CodeGen/Passes.cpp index 28e9f847a9d..a5d32103d7c 100644 --- a/llvm/lib/CodeGen/Passes.cpp +++ b/llvm/lib/CodeGen/Passes.cpp @@ -583,6 +583,9 @@ void TargetPassConfig::addMachinePasses() { addPass(createGCInfoPrinter(dbgs()), false, false); } + if (TM->Options.NoopInsertion) + addPass(&NoopInsertionID); + // Basic block placement. if (getOptLevel() != CodeGenOpt::None) addBlockPlacement(); diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp index 461569345a1..92fccf3e5c2 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -34,6 +34,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/RandomNumberGenerator.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetOptions.h" #include <limits> @@ -5620,6 +5621,66 @@ void X86InstrInfo::setExecutionDomain(MachineInstr *MI, unsigned Domain) const { MI->setDesc(get(table[Domain-1])); } +/// insertNoop - Insert a noop into the instruction stream at the specified +/// point. +void X86InstrInfo::insertNoop(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const { + DebugLoc DL; + BuildMI(MBB, MI, DL, get(X86::NOOP)); +} + +/// insertNoop - Insert a randomly chosen type of noop into the instruction +/// stream at the specified point to introduce fine-grained diversity. +void X86InstrInfo::insertNoop(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + RandomNumberGenerator &RNG) const { + // This set of Noop instructions was carefully chosen so that + // misaligned parses of these instructions do not introduce new, + // useful ROP gadgets. The ASM instructions noted are for misaligned + // parses of the noop in 32 and 64 bits. + enum { + NOP, // 90 + MOV_BP, // 89 ed, 48 89 ed -- IN EAX, IN AL (privileged) + MOV_SP, // 89 e4, 48 89 e4 -- IN AL, IN EAX (privileged) + LEA_SI, // 8d 36, 48 8d 36 -- SS segment override, NULL + // prefix (does not add new gadget) + LEA_DI, // 8d 3f, 48 8d 3f -- AAS (bcd->hex), invalid + MAX_NOPS + }; + + static const unsigned NopRegs[MAX_NOPS][2] = { + {0, 0}, + {X86::EBP, X86::RBP}, + {X86::ESP, X86::RSP}, + {X86::ESI, X86::RSI}, + {X86::EDI, X86::RDI}, + }; + + std::uniform_int_distribution<unsigned> Distribution(0, MAX_NOPS - 1); + + unsigned Type = Distribution(RNG); + + DebugLoc DL; + bool is64Bit = Subtarget.is64Bit(); + unsigned Reg = NopRegs[Type][is64Bit]; + + switch (Type) { + case NOP: + BuildMI(MBB, MI, DL, get(X86::NOOP)); + break; + case MOV_BP: + case MOV_SP: + copyPhysReg(MBB, MI, DL, Reg, Reg, false); + break; + case LEA_SI: + case LEA_DI: { + unsigned opc = is64Bit ? X86::LEA64r : X86::LEA32r; + addRegOffset(BuildMI(MBB, MI, DL, get(opc), Reg), Reg, false, 0); + break; + } + } +} + /// getNoopForMachoTarget - Return the noop instruction to use for a noop. void X86InstrInfo::getNoopForMachoTarget(MCInst &NopInst) const { NopInst.setOpcode(X86::NOOP); diff --git a/llvm/lib/Target/X86/X86InstrInfo.h b/llvm/lib/Target/X86/X86InstrInfo.h index 5662e86932c..eecc67309c3 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.h +++ b/llvm/lib/Target/X86/X86InstrInfo.h @@ -361,6 +361,13 @@ public: bool shouldScheduleAdjacent(MachineInstr* First, MachineInstr *Second) const override; + void insertNoop(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const override; + + void insertNoop(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + RandomNumberGenerator &RNG) const override; + void getNoopForMachoTarget(MCInst &NopInst) const override; bool |