summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/CMakeLists.txt1
-rw-r--r--llvm/lib/CodeGen/CodeGen.cpp1
-rw-r--r--llvm/lib/CodeGen/NoopInsertion.cpp101
-rw-r--r--llvm/lib/CodeGen/Passes.cpp3
-rw-r--r--llvm/lib/Target/X86/X86InstrInfo.cpp61
-rw-r--r--llvm/lib/Target/X86/X86InstrInfo.h7
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
OpenPOWER on IntegriCloud