| Index: lib/Transforms/NaCl/SandboxIndirectCalls.cpp | 
| diff --git a/lib/Transforms/NaCl/SandboxIndirectCalls.cpp b/lib/Transforms/NaCl/SandboxIndirectCalls.cpp | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..912ae0034c440932f4cc650d829556c0f6a5d2b2 | 
| --- /dev/null | 
| +++ b/lib/Transforms/NaCl/SandboxIndirectCalls.cpp | 
| @@ -0,0 +1,142 @@ | 
| +//===- SandboxIndirectCalls.cpp - Add CFI to indirect function calls-------===// | 
| +// | 
| +//                     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/Constants.h" | 
| +// #include "llvm/IR/Function.h" | 
| +#include "llvm/IR/Instructions.h" | 
| +// #include "llvm/IR/Intrinsics.h" | 
| +#include "llvm/IR/Module.h" | 
| +// #include "llvm/IR/Type.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 SandboxIndirectCalls : public ModulePass { | 
| +  public: | 
| +    static char ID; // Pass identification, replacement for typeid | 
| +    SandboxIndirectCalls() : ModulePass(ID) { | 
| +      initializeSandboxIndirectCallsPass(*PassRegistry::getPassRegistry()); | 
| +    } | 
| + | 
| +    virtual bool runOnModule(Module &M); | 
| +  }; | 
| +} | 
| + | 
| +char SandboxIndirectCalls::ID = 0; | 
| +INITIALIZE_PASS(SandboxIndirectCalls, "sandbox-indirect-calls", | 
| +                "Add CFI to indirect function calls", | 
| +                false, false) | 
| + | 
| +bool SandboxIndirectCalls::runOnModule(Module &M) { | 
| +  Type *I32 = Type::getInt32Ty(M.getContext()); | 
| +  Type *IntPtrType = I32; // XXX | 
| +  PointerType *PtrType = Type::getInt8Ty(M.getContext())->getPointerTo(); | 
| + | 
| +  SmallVector<Constant *, 20> FuncTable; | 
| +  // Reserve index 0. | 
| +  FuncTable.push_back(ConstantPointerNull::get(PtrType)); | 
| + | 
| +  // Build a function table out of address-taken functions. | 
| +  for (Module::iterator Func = M.begin(), E = M.end(); Func != E; ++Func) { | 
| +    // Look for address-taking references to the function. | 
| +    SmallVector<User *, 10> Users; | 
| +    for (Value::use_iterator U = Func->use_begin(), E = Func->use_end(); | 
| +         U != E; ++U) { | 
| +      if (CallInst *Call = dyn_cast<CallInst>(*U)) { | 
| +        // In PNaCl's normal form, a function referenced by a CallInst | 
| +        // can only appear as the callee, not an argument. | 
| +        if (U.getOperandNo() != Call->getNumArgOperands()) { | 
| +          errs() << "Value: " << **U << "\n"; | 
| +          report_fatal_error("SandboxIndirectCalls: Bad function reference"); | 
| +        } | 
| +      } else { | 
| +        // In PNaCl's normal form, all other references are PtrToInt | 
| +        // instructions or ConstantExprs. | 
| +        if (!(isa<PtrToIntInst>(*U) || | 
| +              (isa<ConstantExpr>(*U) && | 
| +               cast<ConstantExpr>(*U)->getOpcode() == Instruction::PtrToInt))) { | 
| +          errs() << "Value: " << **U << "\n"; | 
| +          report_fatal_error("SandboxIndirectCalls: Bad function reference"); | 
| +        } | 
| +        Users.push_back(*U); | 
| +      } | 
| +    } | 
| + | 
| +    // If the function is address-taken, allocate it an ID by adding | 
| +    // it to the function table. | 
| +    if (!Users.empty()) { | 
| +      Value *FuncIndex = ConstantInt::get(IntPtrType, FuncTable.size()); | 
| +      // XXX: Remove bitcast when we use multiple tables. | 
| +      FuncTable.push_back(ConstantExpr::getBitCast(Func, PtrType)); | 
| + | 
| +      for (SmallVectorImpl<User *>::iterator U = Users.begin(), E = Users.end(); | 
| +           U != E; ++U) { | 
| +        (*U)->replaceAllUsesWith(FuncIndex); | 
| +        // XXX: assumes cast is only used once. | 
| +        if (Instruction *Inst = dyn_cast<PtrToIntInst>(*U)) | 
| +          Inst->eraseFromParent(); | 
| +      } | 
| +    } | 
| +  } | 
| + | 
| +  Constant *TableArray = | 
| +      ConstantArray::get(ArrayType::get(PtrType, FuncTable.size()), FuncTable); | 
| +  Value *FuncTableGV = new GlobalVariable( | 
| +      M, TableArray->getType(), /*isConstant=*/true, | 
| +      GlobalVariable::InternalLinkage, TableArray, | 
| +      "__sfi_function_table"); | 
| + | 
| +  // Convert indirect function call instructions. | 
| +  for (Module::iterator Func = M.begin(), E = M.end(); Func != E; ++Func) { | 
| +    for (Function::iterator BB = Func->begin(), E = Func->end(); | 
| +         BB != E; | 
| +         ++BB) { | 
| +      for (BasicBlock::iterator Inst = BB->begin(), E = BB->end(); | 
| +           Inst != E; ++Inst) { | 
| +        assert(!isa<InvokeInst>(Inst)); | 
| +        if (CallInst *Call = dyn_cast<CallInst>(Inst)) { | 
| +          Value *Callee = Call->getCalledValue(); | 
| +          if (!isa<Function>(Callee)) { | 
| +            // assert... | 
| +            IntToPtrInst *Cast = cast<IntToPtrInst>(Callee); | 
| +            Value *FuncIndex = Cast->getOperand(0); | 
| + | 
| +            Value *Indexes[] = { | 
| +              ConstantInt::get(I32, 0), | 
| +              FuncIndex | 
| +            }; | 
| +            Value *Ptr = GetElementPtrInst::Create( | 
| +                FuncTableGV, Indexes, "func_gep", Call); | 
| +            Value *FuncPtr = new LoadInst(Ptr, "func", Call); | 
| +            // XXX: Remove bitcast when we use multiple tables. | 
| +            Value *Bitcast = new BitCastInst(FuncPtr, Cast->getType(), | 
| +                                             "func_bc", Call); | 
| +            Call->setCalledFunction(Bitcast); | 
| +            // XXX: assumes cast is only used once. | 
| +            Cast->eraseFromParent(); | 
| +          } | 
| +        } | 
| +      } | 
| +    } | 
| +  } | 
| + | 
| +  return true; | 
| +} | 
| + | 
| +ModulePass *llvm::createSandboxIndirectCallsPass() { | 
| +  return new SandboxIndirectCalls(); | 
| +} | 
|  |