| 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();
|
| +}
|
|
|