| //===- Terminate.cpp --------------------------------------------*- C++ -*----// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // 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 modify SAFECode's initialization in the program to terminate on the |
| // first memory safety error. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/IR/Constants.h" |
| #include "llvm/IR/DerivedTypes.h" |
| #include "llvm/IR/Module.h" |
| #include "llvm/Pass.h" |
| #include "llvm/Support/CallSite.h" |
| |
| namespace llvm { |
| class Terminate : public llvm::ModulePass { |
| public: |
| static char ID; |
| Terminate () : llvm::ModulePass(ID) { |
| } |
| virtual bool runOnModule(llvm::Module & M); |
| virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const { |
| AU.setPreservesCFG(); |
| } |
| }; |
| |
| ModulePass * createSCTerminatePass (void); |
| } |
| |
| using namespace llvm; |
| |
| // ID for the Terminate pass |
| char Terminate::ID = 0; |
| |
| // |
| // Method: runOnModule() |
| // |
| // Description: |
| // This method is the entry point for this LLVM pass. We look for calls to |
| // the pool_init_runtime() function in the program and modify them to tell the |
| // run-time to terminate the program when a memory error is detected. |
| // |
| // Return value: |
| // true - The program was modified in some way. |
| // false - This pass did not modify the program. |
| // |
| bool |
| Terminate::runOnModule (Module & M) { |
| // |
| // Find the pool_init_runtime() function. If it does not exit, then there |
| // is nothing to do. |
| // |
| Function * F = M.getFunction ("pool_init_runtime"); |
| if (!F) |
| return false; |
| |
| // |
| // Scan through all uses of the function looking for calls to it. If we |
| // find them, modify the last argument (the terminate argument) to be true. |
| // |
| bool modified = false; |
| Type * Int32Type = IntegerType::getInt32Ty(M.getContext()); |
| Function::use_iterator i, e; |
| for (i = F->use_begin(), e = F->use_end(); i != e; ++i) { |
| if (CallInst * CI = dyn_cast<CallInst>(*i)) { |
| CallSite CS(CI); |
| CS.setArgument(2, ConstantInt::get(Int32Type, 1)); |
| modified = true; |
| } |
| } |
| |
| return modified; |
| } |
| |
| // Function to allow external code to create objects of this pass |
| ModulePass * |
| llvm::createSCTerminatePass (void) { |
| return new Terminate(); |
| } |