| //===- RegisterRuntimeInitializer.cpp ---------------------------*- C++ -*----// |
| // |
| // The SAFECode Compiler |
| // |
| // This file was developed by the LLVM research group and is distributed under |
| // the University of Illinois Open Source License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // Pass to register runtime initialization calls into user-space programs. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "safecode/InsertChecks/RegisterRuntimeInitializer.h" |
| #include "safecode/SAFECodeConfig.h" |
| |
| #include "llvm/Constants.h" |
| #include "llvm/LLVMContext.h" |
| |
| using namespace llvm; |
| |
| NAMESPACE_SC_BEGIN |
| |
| char RegisterRuntimeInitializer::ID = 0; |
| |
| static llvm::RegisterPass<RegisterRuntimeInitializer> X1 ("reg-runtime-init", "Register runtime initializer into programs"); |
| |
| |
| bool |
| RegisterRuntimeInitializer::runOnModule(llvm::Module & M) { |
| intrinsic = &getAnalysis<InsertSCIntrinsic>(); |
| constructInitializer(M); |
| insertInitializerIntoGlobalCtorList(M); |
| return true; |
| } |
| |
| void |
| RegisterRuntimeInitializer::constructInitializer(llvm::Module & M) { |
| // |
| // Create a new function with zero arguments. This will be the SAFECode |
| // run-time constructor; it will be called by static global variable |
| // constructor magic before main() is called. |
| // |
| |
| Function * RuntimeCtor = intrinsic->getIntrinsic("sc.init_runtime").F; |
| Function * RuntimeInit = intrinsic->getIntrinsic("sc.init_pool_runtime").F; |
| Function * RegGlobals = intrinsic->getIntrinsic("sc.register_globals").F; |
| // Function * PoolInit = M.getFunction("poolalloc.init"); |
| |
| // Make the runtime constructor compatible with other ctors |
| RuntimeCtor->setDoesNotThrow(); |
| RuntimeCtor->setLinkage(GlobalValue::InternalLinkage); |
| |
| // |
| // Add a call in the new constructor function to the SAFECode initialization |
| // function. |
| // |
| BasicBlock * BB = BasicBlock::Create (getGlobalContext(), "entry", RuntimeCtor); |
| |
| // Delegate the responbilities of initializing pool descriptor to the |
| // SAFECode runtime initializer |
| // CallInst::Create (PoolInit, "", BB); |
| |
| const Type * Int32Type = IntegerType::getInt32Ty(getGlobalContext()); |
| std::vector<Value *> args; |
| if (SCConfig.dpChecks()) |
| args.push_back (ConstantInt::get(Int32Type, 1)); |
| else |
| args.push_back (ConstantInt::get(Int32Type, 0)); |
| args.push_back (ConstantInt::get(Int32Type, SCConfig.rewriteOOB())); |
| args.push_back (ConstantInt::get(Int32Type, SCConfig.terminateOnErrors())); |
| CallInst::Create (RuntimeInit, args.begin(), args.end(), "", BB); |
| |
| args.clear(); |
| CallInst::Create (RegGlobals, args.begin(), args.end(), "", BB); |
| |
| |
| // |
| // Add a return instruction at the end of the basic block. |
| // |
| ReturnInst::Create (getGlobalContext(), BB); |
| } |
| |
| void |
| RegisterRuntimeInitializer::insertInitializerIntoGlobalCtorList(Module & M) { |
| Function * RuntimeCtor = intrinsic->getIntrinsic("sc.init_runtime").F; |
| |
| // |
| // Insert the run-time ctor into the ctor list. |
| // |
| const Type * Int32Type = IntegerType::getInt32Ty(getGlobalContext()); |
| std::vector<Constant *> CtorInits; |
| CtorInits.push_back (ConstantInt::get (Int32Type, 65535)); |
| CtorInits.push_back (RuntimeCtor); |
| Constant * RuntimeCtorInit=ConstantStruct::get(getGlobalContext(),CtorInits, false); |
| |
| // |
| // Get the current set of static global constructors and add the new ctor |
| // to the end of the list (the list seems to be initialized in reverse |
| // order). |
| // |
| std::vector<Constant *> CurrentCtors; |
| GlobalVariable * GVCtor = M.getNamedGlobal ("llvm.global_ctors"); |
| if (GVCtor) { |
| if (Constant * C = GVCtor->getInitializer()) { |
| for (unsigned index = 0; index < C->getNumOperands(); ++index) { |
| CurrentCtors.push_back (cast<Constant>(C->getOperand (index))); |
| } |
| } |
| |
| // |
| // Rename the global variable so that we can name our global |
| // llvm.global_ctors. |
| // |
| GVCtor->setName ("removed"); |
| } |
| CurrentCtors.push_back (RuntimeCtorInit); |
| |
| // |
| // Create a new initializer. |
| // |
| const ArrayType * AT = ArrayType::get (RuntimeCtorInit-> getType(), |
| CurrentCtors.size()); |
| Constant * NewInit=ConstantArray::get (AT, CurrentCtors); |
| |
| // |
| // Create the new llvm.global_ctors global variable and replace all uses of |
| // the old global variable with the new one. |
| // |
| new GlobalVariable (M, |
| NewInit->getType(), |
| false, |
| GlobalValue::AppendingLinkage, |
| NewInit, |
| "llvm.global_ctors"); |
| } |
| |
| NAMESPACE_SC_END |