void SecureFunctionTypeTraversal::visit(SgNode* sgn) { if(isSgFunctionCallExp(sgn)) { SgFunctionDeclaration* fndecl = isSgFunctionCallExp(sgn)->getAssociatedFunctionDeclaration(); string filename = fndecl->get_file_info()->get_filename(); if(filename != "compilerGenerated") { StringUtility::FileNameClassification classification; classification = StringUtility::classifyFileName(filename, this->sourcedir, this->trustedlibs); //StringUtility::FileNameLocation filetypeclassification = classification.getLocation(); //cout << sgn->unparseToString() << filename << " : " << classification.getLocation() << ", " << classification.getLibrary() << endl; bool isSecure; if(untrustedFunctions.find(fndecl->get_name().getString()) != untrustedFunctions.end()) { isSecure = false; } else if(classification.isLibraryCode() || classification.isUserCode()) { isSecure = true; } else { isSecure = false; } AstAttribute* attr = dynamic_cast<AstAttribute*> ( new SecureFunctionType(isSecure) ); sgn->setAttribute("SECURE_TYPE", attr); } } }
void CompassAnalyses::FunctionDocumentation::Traversal:: visit(SgNode* sgNode) { // Implement your traversal here. if (isSgFunctionDeclaration(sgNode)) { SgFunctionDeclaration* funcDecl = isSgFunctionDeclaration(sgNode); if (funcDecl->get_file_info()->isCompilerGenerated() || funcDecl->get_definingDeclaration() != sgNode ) return; if (!( isDocumented( funcDecl) || isDocumented(isSgFunctionDeclaration(funcDecl->get_firstNondefiningDeclaration())) ) ) { std::string funcName = funcDecl->get_qualified_name(); output->addOutput(new CheckerOutput(funcDecl, funcName)); } } } //End of the visit function.
int main( int argc, char * argv[] ) { // Build the AST used by ROSE SgProject* project = frontend(argc,argv); ROSE_ASSERT(project != NULL); // Build a list of functions within the AST Rose_STL_Container<SgNode*> functionCallList = NodeQuery::querySubTree (project,V_SgFunctionCallExp); int functionCounter = 0; for (Rose_STL_Container<SgNode*>::iterator i = functionCallList.begin(); i != functionCallList.end(); i++) { SgExpression* functionExpression = isSgFunctionCallExp(*i)->get_function(); ROSE_ASSERT(functionExpression != NULL); SgFunctionRefExp* functionRefExp = isSgFunctionRefExp(functionExpression); SgFunctionSymbol* functionSymbol = NULL; if (functionRefExp != NULL) { // Case of non-member function functionSymbol = functionRefExp->get_symbol(); } else { // Case of member function (hidden in rhs of binary dot operator expression) SgDotExp* dotExp = isSgDotExp(functionExpression); ROSE_ASSERT(dotExp != NULL); functionExpression = dotExp->get_rhs_operand(); SgMemberFunctionRefExp* memberFunctionRefExp = isSgMemberFunctionRefExp(functionExpression); ROSE_ASSERT(memberFunctionRefExp != NULL); functionSymbol = memberFunctionRefExp->get_symbol(); } ROSE_ASSERT(functionSymbol != NULL); SgFunctionDeclaration* functionDeclaration = functionSymbol->get_declaration(); ROSE_ASSERT(functionDeclaration != NULL); // Output mapping of function calls to function declarations printf ("Location of function call #%d at line %d resolved by overloaded function declared at line %d \n", functionCounter++, isSgFunctionCallExp(*i)->get_file_info()->get_line(), functionDeclaration->get_file_info()->get_line()); } return 0; }
// Function printFunctionDeclarationList will print all function names in the list void printFunctionDeclarationList(Rose_STL_Container<SgNode*> functionDeclarationList) { int counter = 0; for (Rose_STL_Container<SgNode*>::iterator i = functionDeclarationList.begin(); i != functionDeclarationList.end(); i++) { // Build a pointer to the current type so that we can call the get_name() member function. SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i); ROSE_ASSERT(functionDeclaration != NULL); // output the function number and the name of the function printf ("function name #%d is %s at line %d \n", counter++,functionDeclaration->get_name().str(), functionDeclaration->get_file_info()->get_line()); } }
void findCandidateFunctionDefinitions (SgProject* project, std::vector<SgFunctionDefinition* >& candidateFuncDefs) { ROSE_ASSERT (project != NULL); // For each source file in the project SgFilePtrList & ptr_list = project->get_fileList(); for (SgFilePtrList::iterator iter = ptr_list.begin(); iter!=ptr_list.end(); iter++) { SgFile* sageFile = (*iter); SgSourceFile * sfile = isSgSourceFile(sageFile); ROSE_ASSERT(sfile); // SgGlobal *root = sfile->get_globalScope(); if (enable_debug) cout<<"Processing each function within the files "<< sfile->get_file_info()->get_filename() <<endl; // cout<<"\t loop at:"<< cur_loop->get_file_info()->get_line() <<endl; // This is wrong, many functions in question are not top level declarations!! //SgDeclarationStatementPtrList& declList = root->get_declarations (); //VariantVector vv; Rose_STL_Container<SgNode*> defList = NodeQuery::querySubTree(sfile, V_SgFunctionDefinition); // bool hasOpenMP= false; // flag to indicate if omp.h is needed in this file //For each function body in the scope //for (SgDeclarationStatementPtrList::iterator p = declList.begin(); p != declList.end(); ++p) for (Rose_STL_Container<SgNode*>::iterator p = defList.begin(); p != defList.end(); ++p) { SgFunctionDefinition *defn = isSgFunctionDefinition(*p); ROSE_ASSERT (defn != NULL); SgFunctionDeclaration *func = defn->get_declaration(); ROSE_ASSERT (func != NULL); if (enable_debug) cout<<"\t considering function "<< func->get_name() << " at "<< func->get_file_info()->get_line()<<endl; //ignore functions in system headers, Can keep them to test robustness if (defn->get_file_info()->get_filename()!=sageFile->get_file_info()->get_filename()) { if (enable_debug) cout<<"\t Skipped since the function's associated file name does not match current file being considered. Mostly from a header. "<<endl; continue; } candidateFuncDefs.push_back(defn); } // end for def list } // end for file list }
int main( int argc, char * argv[] ) { // Build the AST used by ROSE SgProject* project = frontend(argc,argv); ROSE_ASSERT(project != NULL); // Build a list of functions within the AST Rose_STL_Container<SgNode*> functionDeclarationList = NodeQuery::querySubTree (project,V_SgFunctionDeclaration); int counter = 0; for (Rose_STL_Container<SgNode*>::iterator i = functionDeclarationList.begin(); i != functionDeclarationList.end(); i++) { // Build a pointer to the current type so that we can call the get_name() member function. SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i); ROSE_ASSERT(functionDeclaration != NULL); // DQ (3/5/2006): Only output the non-compiler generated IR nodes if ( (*i)->get_file_info()->isCompilerGenerated() == false) { // output the function number and the name of the function printf ("Function #%2d name is %s at line %d \n", counter++,functionDeclaration->get_name().str(), functionDeclaration->get_file_info()->get_line()); } else { // Output something about the compiler-generated builtin functions printf ("Compiler-generated (builtin) function #%2d name is %s \n", counter++,functionDeclaration->get_name().str()); } } // Note: Show composition of AST queries return 0; }
void SystemDependenceGraph::build() { boost::unordered_map<CFGVertex, Vertex> cfgVerticesToSdgVertices; boost::unordered_map<SgNode*, Vertex> astNodesToSdgVertices; //map<SgFunctionCallExp*, vector<SDGNode*> > funcCallToArgs; vector<CallSiteInfo> functionCalls; map<SgNode*, vector<Vertex> > actualInParameters; map<SgNode*, vector<Vertex> > actualOutParameters; map<SgNode*, Vertex> formalInParameters; map<SgNode*, Vertex> formalOutParameters; vector<SgFunctionDefinition*> funcDefs = SageInterface::querySubTree<SgFunctionDefinition>(project_, V_SgFunctionDefinition); foreach (SgFunctionDefinition* funcDef, funcDefs) { SgFunctionDeclaration* funcDecl = funcDef->get_declaration(); CFG* cfg = new CFG(funcDef, cfgNodefilter_); functionsToCFGs_[funcDecl] = cfg; // For each function, build an entry node for it. SDGNode* entry = new SDGNode(SDGNode::Entry); entry->astNode = funcDef; //entry->funcDef = funcDef; Vertex entryVertex = addVertex(entry); functionsToEntries_[funcDecl] = entryVertex; // Add all out formal parameters to SDG. const SgInitializedNamePtrList& formalArgs = funcDecl->get_args(); foreach (SgInitializedName* initName, formalArgs) { // If the parameter is passed by reference, create a formal-out node. if (isParaPassedByRef(initName->get_type())) { SDGNode* formalOutNode = new SDGNode(SDGNode::FormalOut); formalOutNode->astNode = initName; Vertex formalOutVertex = addVertex(formalOutNode); formalOutParameters[initName] = formalOutVertex; // Add a CD edge from call node to this formal-out node. addTrueCDEdge(entryVertex, formalOutVertex); } } // A vertex representing the returned value. Vertex returnVertex; // If the function returns something, build a formal-out node. if (!isSgTypeVoid(funcDecl->get_type()->get_return_type())) { SDGNode* formalOutNode = new SDGNode(SDGNode::FormalOut); // Assign the function declaration to the AST node of this vertex to make // it possible to classify this node into the subgraph of this function. formalOutNode->astNode = funcDecl; returnVertex = addVertex(formalOutNode); formalOutParameters[funcDecl] = returnVertex; // Add a CD edge from call node to this formal-out node. addTrueCDEdge(entryVertex, returnVertex); } // Add all CFG vertices to SDG. foreach (CFGVertex cfgVertex, boost::vertices(*cfg)) { if (cfgVertex == cfg->getEntry() || cfgVertex == cfg->getExit()) continue; SgNode* astNode = (*cfg)[cfgVertex]->getNode(); // If this node is an initialized name and it is a parameter, make it // as a formal in node. SgInitializedName* initName = isSgInitializedName(astNode); if (initName && isSgFunctionParameterList(initName->get_parent())) { SDGNode* formalInNode = new SDGNode(SDGNode::FormalIn); formalInNode->astNode = initName; Vertex formalInVertex = addVertex(formalInNode); formalInParameters[initName] = formalInVertex; cfgVerticesToSdgVertices[cfgVertex] = formalInVertex; astNodesToSdgVertices[astNode] = formalInVertex; // Add a CD edge from call node to this formal-in node. addTrueCDEdge(entryVertex, formalInVertex); continue; } // Add a new node to SDG. SDGNode* newSdgNode = new SDGNode(SDGNode::ASTNode); //newSdgNode->cfgNode = (*cfg)[cfgVertex]; newSdgNode->astNode = astNode; Vertex sdgVertex = addVertex(newSdgNode); cfgVerticesToSdgVertices[cfgVertex] = sdgVertex; astNodesToSdgVertices[astNode] = sdgVertex; // Connect a vertex containing the return statement to the formal-out return vertex. if (isSgReturnStmt(astNode) || isSgReturnStmt(astNode->get_parent())) { SDGEdge* newEdge = new SDGEdge(SDGEdge::DataDependence); addEdge(sdgVertex, returnVertex, newEdge); } // If this CFG node contains a function call expression, extract its all parameters // and make them as actual-in nodes. if (SgFunctionCallExp* funcCallExpr = isSgFunctionCallExp(astNode)) { CallSiteInfo callInfo; callInfo.funcCall = funcCallExpr; callInfo.vertex = sdgVertex; // Change the node type. newSdgNode->type = SDGNode::FunctionCall; vector<SDGNode*> argsNodes; // Get the associated function declaration. SgFunctionDeclaration* funcDecl = funcCallExpr->getAssociatedFunctionDeclaration(); if (funcDecl == NULL) continue; ROSE_ASSERT(funcDecl); const SgInitializedNamePtrList& formalArgs = funcDecl->get_args(); SgExprListExp* args = funcCallExpr->get_args(); const SgExpressionPtrList& actualArgs = args->get_expressions(); if (formalArgs.size() != actualArgs.size()) { cout << "The following function has variadic arguments:\n"; cout << funcDecl->get_file_info()->get_filename() << endl; cout << funcDecl->get_name() << formalArgs.size() << " " << actualArgs.size() << endl; continue; } for (int i = 0, s = actualArgs.size(); i < s; ++i) { // Make sure that this parameter node is added to SDG then we // change its node type from normal AST node to a ActualIn arg. ROSE_ASSERT(astNodesToSdgVertices.count(actualArgs[i])); Vertex paraInVertex = astNodesToSdgVertices.at(actualArgs[i]); SDGNode* paraInNode = (*this)[paraInVertex]; paraInNode->type = SDGNode::ActualIn; actualInParameters[formalArgs[i]].push_back(paraInVertex); callInfo.inPara.push_back(paraInVertex); // Add a CD edge from call node to this actual-in node. addTrueCDEdge(sdgVertex, paraInVertex); // If the parameter is passed by reference, create a parameter-out node. if (isParaPassedByRef(formalArgs[i]->get_type())) { SDGNode* paraOutNode = new SDGNode(SDGNode::ActualOut); paraOutNode->astNode = actualArgs[i]; //argsNodes.push_back(paraInNode); // Add an actual-out parameter node. Vertex paraOutVertex = addVertex(paraOutNode); actualOutParameters[formalArgs[i]].push_back(paraOutVertex); callInfo.outPara.push_back(paraOutVertex); // Add a CD edge from call node to this actual-out node. addTrueCDEdge(sdgVertex, paraOutVertex); } } if (!isSgTypeVoid(funcDecl->get_type()->get_return_type())) { // If this function returns a value, create a actual-out vertex. SDGNode* paraOutNode = new SDGNode(SDGNode::ActualOut); paraOutNode->astNode = funcCallExpr; // Add an actual-out parameter node. Vertex paraOutVertex = addVertex(paraOutNode); actualOutParameters[funcDecl].push_back(paraOutVertex); callInfo.outPara.push_back(paraOutVertex); callInfo.isVoid = false; callInfo.returned = paraOutVertex; // Add a CD edge from call node to this actual-out node. addTrueCDEdge(sdgVertex, paraOutVertex); } functionCalls.push_back(callInfo); //funcCallToArgs[funcCallExpr] = argsNodes; } } // Add control dependence edges. addControlDependenceEdges(cfgVerticesToSdgVertices, *cfg, entryVertex); }
IntermediateRepresentationNodeGraph::IntermediateRepresentationNodeGraph(ofstream & inputFile, SgProject* project, const std::vector<VariantT> & inputNodeKindList) : file(inputFile), nodeKindList(inputNodeKindList) { for (size_t i = 0; i < nodeKindList.size(); i++) { printf ("Adding nodeKindList[%" PRIuPTR "] = %d = %s to nodeKindSet \n",i,Cxx_GrammarTerminalNames[nodeKindList[i]].variant,Cxx_GrammarTerminalNames[nodeKindList[i]].name.c_str()); include_nodeKindSet.insert(nodeKindList[i]); } // Build a list of functions within the AST // Rose_STL_Container<SgNode*> functionDeclarationList = NodeQuery::querySubTree (project,V_SgFunctionDeclaration); // Rose_STL_Container<SgNode*> functionDeclarationList = NodeQuery::querySubTree (project,V_SgDeclarationStatement); Rose_STL_Container<SgNode*> functionDeclarationList = NodeQuery::querySubTree (project,V_SgStatement); // include_nodeSet.insert(functionDeclarationList.begin(),functionDeclarationList.end()); int maxNumberOfNodes = 5000; int numberOfNodes = (int)functionDeclarationList.size(); printf ("Number of IR nodes in IntermediateRepresentationNodeGraph = %d \n",numberOfNodes); #if 1 int counter = 0; for (Rose_STL_Container<SgNode*>::iterator i = functionDeclarationList.begin(); i != functionDeclarationList.end(); i++) { SgStatement* statement = isSgStatement(*i); SgDeclarationStatement* declaration = isSgDeclarationStatement(*i); SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i); SgTemplateInstantiationFunctionDecl* templateInstantiationFunctionDeclaration = isSgTemplateInstantiationFunctionDecl(*i); // if (declaration != NULL && declaration->get_file_info()->isCompilerGenerated() == false) if (statement != NULL && statement->get_file_info()->isCompilerGenerated() == false) { include_nodeSet.insert(statement); } if (templateInstantiationFunctionDeclaration != NULL) { include_nodeSet.insert(statement); } #if 0 // Build a pointer to the current type so that we can call the get_name() member function. SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(*i); if (functionDeclaration != NULL) { // DQ (3/5/2006): Only output the non-compiler generated IR nodes if ( (*i)->get_file_info()->isCompilerGenerated() == false) { // output the function number and the name of the function printf ("Function #%2d name is %s at line %d \n",counter++,functionDeclaration->get_name().str(),functionDeclaration->get_file_info()->get_line()); } else { // Output something about the compiler-generated builtin functions printf ("Compiler-generated (builtin) function #%2d name is %s \n",counter++,functionDeclaration->get_name().str()); } } else { SgDeclarationStatement* declaration = isSgDeclarationStatement(*i); ROSE_ASSERT(declaration != NULL); printf ("--- declaration #%2d is: %p = %s \n",counter++,declaration,declaration->class_name().c_str()); } #endif } #endif if (numberOfNodes <= maxNumberOfNodes) { // Ouput nodes. for (std::set<SgNode*>::iterator i = include_nodeSet.begin(); i != include_nodeSet.end(); i++) { SgNode* node = *i; file << "\"" << StringUtility::numberToString(node) << "\"[" << "label=\"" << node->class_name() << "\\n" << StringUtility::numberToString(node) << "\"];" << endl; } // Output edges for (std::set<SgNode*>::iterator i = include_nodeSet.begin(); i != include_nodeSet.end(); i++) { SgNode* node = *i; std::vector<std::pair<SgNode*,std::string> > listOfIRnodes = node->returnDataMemberPointers(); std::vector<std::pair<SgNode*,std::string> >::iterator j = listOfIRnodes.begin(); while (j != listOfIRnodes.end()) { if (include_nodeSet.find(j->first) != include_nodeSet.end()) { file << "\"" << StringUtility::numberToString(node) << "\" -> \"" << StringUtility::numberToString(j->first) << "\"[label=\"" << j->second << "\"];" << endl; } j++; } } } else { printf ("WARNING: IntermediateRepresentationNodeGraph is too large to generate: numberOfNodes = %d (max size = %d) \n",numberOfNodes,maxNumberOfNodes); } }