Index: lib/Transforms/NaCl/SandboxMemoryAccesses.cpp |
diff --git a/lib/Transforms/NaCl/SandboxMemoryAccesses.cpp b/lib/Transforms/NaCl/SandboxMemoryAccesses.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ca2425f104a035021c7be392d36ef4bc1f41f7e5 |
--- /dev/null |
+++ b/lib/Transforms/NaCl/SandboxMemoryAccesses.cpp |
@@ -0,0 +1,124 @@ |
+//===- SandboxMemoryAccesses.cpp - Add SFI to memory accesses--------------===// |
+// |
+// The LLVM Compiler Infrastructure |
+// |
+// This file is distributed under the University of Illinois Open Source |
+// License. See LICENSE.TXT for details. |
+// |
+//===----------------------------------------------------------------------===// |
+// |
+// XXX |
+// |
+//===----------------------------------------------------------------------===// |
+ |
+#include "llvm/IR/Function.h" |
+#include "llvm/IR/Instructions.h" |
+#include "llvm/IR/IntrinsicInst.h" |
+#include "llvm/IR/Module.h" |
+#include "llvm/Pass.h" |
+// #include "llvm/Support/raw_ostream.h" |
+#include "llvm/Transforms/NaCl.h" |
+ |
+using namespace llvm; |
+ |
+namespace { |
+ // This is a ModulePass so that XXX... |
+ class SandboxMemoryAccesses : public ModulePass { |
+ Value *MemBaseVar; |
+ Value *MemBase; |
+ |
+ Value *sandboxPtr(Value *Ptr, Instruction *InsertPt); |
+ void sandboxOperand(Instruction *Inst, unsigned OpNum); |
+ void convertFunc(Function *Func); |
+ |
+ public: |
+ static char ID; // Pass identification, replacement for typeid |
+ SandboxMemoryAccesses() : ModulePass(ID) { |
+ initializeSandboxMemoryAccessesPass(*PassRegistry::getPassRegistry()); |
+ } |
+ |
+ virtual bool runOnModule(Module &M); |
+ }; |
+} |
+ |
+char SandboxMemoryAccesses::ID = 0; |
+INITIALIZE_PASS(SandboxMemoryAccesses, "sandbox-memory-accesses", |
+ "Add SFI sandboxing to memory accesses", |
+ false, false) |
+ |
+Value *SandboxMemoryAccesses::sandboxPtr(Value *Ptr, Instruction *InsertPt) { |
+ if (!MemBase) { |
+ Function *Func = InsertPt->getParent()->getParent(); |
+ Instruction *MemBaseInst = new LoadInst(MemBaseVar, "mem_base"); |
+ Func->getEntryBlock().getInstList().push_front(MemBaseInst); |
+ MemBase = MemBaseInst; |
+ } |
+ |
+ Type *I32 = Type::getInt32Ty(InsertPt->getContext()); |
+ Type *I64 = Type::getInt64Ty(InsertPt->getContext()); |
+ |
+ // Look for the pattern produced by ExpandGetElementPtr. |
+ // TODO: ExpandGetElementPtr should really put a "nuw" attr on the |
+ // add, and we should check for this here. |
+ if (IntToPtrInst *Cast = dyn_cast<IntToPtrInst>(Ptr)) { |
+ if (BinaryOperator *Op = dyn_cast<BinaryOperator>(Cast->getOperand(0))) { |
+ if (Op->getOpcode() == Instruction::Add) { |
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(Op->getOperand(1))) { |
+ uint64_t Addend = CI->getZExtValue(); |
+ if (Addend < 0x10000) { |
+ Value *ZExt = new ZExtInst(Op->getOperand(0), I64, "", InsertPt); |
+ Value *Add1 = BinaryOperator::Create( |
+ BinaryOperator::Add, MemBase, ZExt, "", InsertPt); |
+ Value *Add2 = BinaryOperator::Create( |
+ BinaryOperator::Add, Add1, ConstantInt::get(I64, Addend), |
+ "", InsertPt); |
+ return new IntToPtrInst(Add2, Ptr->getType(), "", InsertPt); |
+ } |
+ } |
+ } |
+ } |
+ } |
+ |
+ |
+ Value *Truncated = new PtrToIntInst(Ptr, I32, "", InsertPt); |
+ Value *ZExt = new ZExtInst(Truncated, I64, "", InsertPt); |
+ Value *Added = BinaryOperator::Create(BinaryOperator::Add, MemBase, ZExt, |
+ "", InsertPt); |
+ return new IntToPtrInst(Added, Ptr->getType(), "", InsertPt); |
+} |
+ |
+void SandboxMemoryAccesses::sandboxOperand(Instruction *Inst, unsigned OpNum) { |
+ Inst->setOperand(OpNum, sandboxPtr(Inst->getOperand(OpNum), Inst)); |
+} |
+ |
+void SandboxMemoryAccesses::convertFunc(Function *Func) { |
+ MemBase = NULL; |
+ for (Function::iterator BB = Func->begin(), E = Func->end(); BB != E; ++BB) { |
+ for (BasicBlock::iterator Inst = BB->begin(), E = BB->end(); Inst != E; |
+ ++Inst) { |
+ if (isa<LoadInst>(Inst)) { |
+ sandboxOperand(Inst, 0); |
+ } else if (isa<StoreInst>(Inst)) { |
+ sandboxOperand(Inst, 1); |
+ } else if (isa<MemCpyInst>(Inst) || isa<MemMoveInst>(Inst)) { |
+ sandboxOperand(Inst, 0); |
+ sandboxOperand(Inst, 1); |
+ } else if (isa<MemSetInst>(Inst)) { |
+ sandboxOperand(Inst, 0); |
+ } |
+ } |
+ } |
+} |
+ |
+bool SandboxMemoryAccesses::runOnModule(Module &M) { |
+ Type *I64 = Type::getInt64Ty(M.getContext()); |
+ MemBaseVar = M.getOrInsertGlobal("__sfi_memory_base", I64); |
+ for (Module::iterator Func = M.begin(), E = M.end(); Func != E; ++Func) { |
+ convertFunc(Func); |
+ } |
+ return true; |
+} |
+ |
+ModulePass *llvm::createSandboxMemoryAccessesPass() { |
+ return new SandboxMemoryAccesses(); |
+} |