| //===-- StackSafety.cpp - Analysis for ensuring stack safety ------------// |
| // Implementation of StackSafety.h |
| // |
| |
| |
| #include "llvm/Module.h" |
| #include "llvm/Function.h" |
| #include "llvm/Instructions.h" |
| #include "llvm/BasicBlock.h" |
| #include "llvm/Type.h" |
| #include "llvm/Pass.h" |
| #include "llvm/Support/InstIterator.h" |
| #include "StackSafety.h" |
| #include <iostream> |
| |
| using namespace llvm; |
| |
| using namespace CSS; |
| |
| char checkStackSafety::ID = 0; |
| |
| RegisterPass<checkStackSafety> css("css1", "check stack safety"); |
| |
| |
| |
| bool checkStackSafety::markReachableAllocas(DSNode *DSN, bool start) { |
| reachableAllocaNodes.clear(); |
| return markReachableAllocasInt(DSN,start); |
| } |
| |
| bool checkStackSafety::markReachableAllocasInt(DSNode *DSN, bool start) { |
| bool returnValue = false; |
| reachableAllocaNodes.insert(DSN); |
| if (!start && DSN->isAllocaNode()) { |
| returnValue = true; |
| AllocaNodes.push_back(DSN); |
| } |
| for (unsigned i = 0, e = DSN->getSize(); i < e; i += DS::PointerSize) |
| if (DSNode *DSNchild = DSN->getLink(i).getNode()) { |
| if (reachableAllocaNodes.find(DSNchild) != reachableAllocaNodes.end()) { |
| continue; |
| } else if (markReachableAllocasInt(DSNchild)) { |
| returnValue = returnValue || true; |
| } |
| } |
| return returnValue; |
| } |
| |
| bool checkStackSafety::runOnModule(Module &M) { |
| // TDDataStructures *TDDS; |
| // TDDS = &getAnalysis<TDDataStructures>(); |
| CompleteBUDataStructures *BUDS; |
| BUDS = &getAnalysis<CompleteBUDataStructures>(); |
| Function *MainFunc = M.getFunction("main") ? M.getFunction("main") |
| : M.getFunction ("MAIN__"); |
| for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) { |
| Function &F = *MI; |
| if (&F != MainFunc) { |
| if (!F.isDeclaration()) { |
| DSGraph &BUG = BUDS->getDSGraph(F); |
| |
| // check if return value is a pointers |
| if (isa<PointerType>(F.getReturnType())) { |
| //return value type is a pointer |
| for (inst_iterator ii = inst_begin(F), ie = inst_end(&F); |
| ii != ie; |
| ++ii) { |
| if (ReturnInst *RI = dyn_cast<ReturnInst>(&*ii)) { |
| DSNode *DSN = BUG.getNodeForValue(RI).getNode(); |
| if (DSN && markReachableAllocas(DSN)) { |
| std::cerr << "Instruction : \n" << RI |
| << "points to a stack location\n"; |
| std::cerr << "In Function " << F.getName() << "\n"; |
| return false; |
| } |
| } |
| } |
| } |
| |
| Function::arg_iterator AI = F.arg_begin(), AE = F.arg_end(); |
| for (; AI != AE; ++AI) { |
| if (isa<PointerType>(AI->getType())) { |
| DSNode *DSN = BUG.getNodeForValue(AI).getNode(); |
| if (markReachableAllocas(DSN,true)) { |
| std::cerr << "Instruction : \n" << AI |
| << "points to a stack location\n"; |
| std::cerr << "In Function " << F.getName() << "\n"; |
| } |
| } |
| } |
| |
| // Also, mark allocas pointed to by globals |
| DSGraph::node_iterator DSNI = BUG.node_begin(), DSNE = BUG.node_end(); |
| |
| for (; DSNI != DSNE; ++DSNI) { |
| if (DSNI->isGlobalNode()) { |
| if (markReachableAllocas(DSNI)) { |
| std::cerr << "Global points to a stack location\n"; |
| std::cerr << "In Function " << F.getName() << "\n"; |
| } |
| } |
| } |
| } |
| } |
| } |
| return false; |
| } |
| |
| |
| Pass *createStackSafetyPass() { return new CSS::checkStackSafety(); } |
| |
| |
| |