void RoseBin_GMLGraph::printNodes( bool dfg, RoseBin_FlowAnalysis* flow,bool forward_analysis, std::ofstream& myfile, string& recursiveFunctionName) { //bool firstFunc = true; // traverse nodes and visualize results of graph funcMap.clear(); nodesMap.clear(); //cerr << " Preparing graph - Nr of Nodes : " << nodes.size() << " edges : " << edges.size() << endl; //SgGraphNodeList* gnodes = get_nodes(); // rose_graph_hash_multimap& nodes = get_nodes()->get_nodes(); rose_graph_integer_node_hash_map nodes = get_node_index_to_node_map(); int counter=nodes.size(); int count=0; rose_graph_integer_node_hash_map::iterator itn2 = nodes.begin(); for (; itn2!=nodes.end();++itn2) { counter++; count++; pair<int, SgGraphNode*> nt = *itn2; // string hex_address = itn2->first; SgGraphNode* node = isSgGraphNode(itn2->second); string hex_address =node->get_name(); SgNode* internal = node->get_SgNode(); SgAsmFunction* func = isSgAsmFunction(internal); if (func) { vector<SgNode*> list; FindInstructionsVisitorx86 vis; #ifdef _MSC_VER //#pragma message ("WARNING: Removed reference to AstQueryNamespace::querySubTree()") // ROSE_ASSERT(false); // CH (4/7/2010): Workaround for MSVC vector<SgAsmX86Instruction*> temp_list; AstQueryNamespace::querySubTree(func, std::bind2nd( vis, &temp_list )); list.resize(temp_list.size()); std::copy(temp_list.begin(), temp_list.end(), list.begin()); #else #if defined(__APPLE__) && defined(__MACH__) //Pei-Hung (7/28/2016): OSX El Capitan has issue with bind2nd. vector<SgAsmX86Instruction*> temp_list; AstQueryNamespace::querySubTree(func, std::bind2nd( vis, &temp_list )); list.resize(temp_list.size()); std::copy(temp_list.begin(), temp_list.end(), list.begin()); #else AstQueryNamespace::querySubTree(func, std::bind2nd( vis, &list )); #endif #endif int validInstructions = func->nrOfValidInstructions(list); funcMap[func]=counter; nodesMap[func]=count; string name = func->get_name(); string text = "node [\n id " + RoseBin_support::ToString(counter) + "\n id_ " + RoseBin_support::ToString(counter) + "\n label \"" + name + "\"\n "; text +=" nrinstr_ "+RoseBin_support::ToString(validInstructions)+" \n"; text+= " isGroup 1\n isGroup_ 1\n ]\n"; if (name=="frame_dummy") { //cerr << text << endl; vector<SgNode*> succs = func->get_traversalSuccessorContainer(); vector<SgNode*>::iterator j = succs.begin(); //cerr << " ------------- free_dummy"<<endl; int ii=0; for (;j!=succs.end();j++) { //SgNode* n = *j; //cerr << " Node contained at pos:"<<ii<<" - " << n->class_name() << endl; ii++; } //cerr << " number of validInstructions: " << validInstructions << endl; } if (grouping) myfile << text; } SgAsmInstruction* bin_inst = isSgAsmInstruction(internal); if (bin_inst) nodesMap[bin_inst]=count; } //cerr << " Writing graph to GML - Nr of Nodes : " << nodes.size() << endl; int pos=0; rose_graph_integer_node_hash_map::iterator itn = nodes.begin(); for (; itn!=nodes.end();++itn) { pos++; // string hex_address = itn->first; SgGraphNode* node = isSgGraphNode(itn->second); string hex_address = node->get_name(); SgNode* internal = node->get_SgNode(); SgAsmFunction* func = isSgAsmFunction(internal); string text=""; // specifies that this node has no destination address nodest_jmp = false; // specifies that there is a node that has a call error (calling itself) error =false; // specifies a call to a unknown location nodest_call = false; // specifies where its an int instruction interrupt = false; if (func) { string name = func->get_name(); //cerr << " if part name : " << name << endl; ROSE_ASSERT(node); if (grouping==false) { map < int , string> node_p = node->get_properties(); map < int , string>::iterator prop = node_p.begin(); string name = "noname"; string type = "removed";//node->get_type(); for (; prop!=node_p.end(); ++prop) { int addr = prop->first; //cerr << " gml : property for addr : " << addr << endl; if (addr==SgGraph::nodest_jmp) nodest_jmp = true; else if (addr==SgGraph::itself_call) error = true; else if (addr==SgGraph::nodest_call) nodest_call = true; else if (addr==SgGraph::interrupt) interrupt = true; // else // name = prop->second; } } int parent = funcMap[func]; RoseBin_support::checkText(name); int length = name.length(); text = "node [\n id " + RoseBin_support::ToString(pos) + "\n label \"" + name + "\"\n"; if (nodest_jmp) { text += " graphics [ h 30.0 w " + RoseBin_support::ToString(length*7) + " type \"circle\" fill \"#FF0000\" ]\n"; text +=" Node_Color_ \"FF0000\" \n"; } else if (nodest_call) { text += " graphics [ h 30.0 w " + RoseBin_support::ToString(length*7) + " type \"circle\" fill \"#FF9900\" ]\n"; text +=" Node_Color_ \"FF9900\" \n"; } else if (interrupt) { text += " graphics [ h 30.0 w " + RoseBin_support::ToString(length*7) + " type \"circle\" fill \"#0000FF\" ]\n"; text +=" Node_Color_ \"0000FF\" \n"; } else if (error) { text += " graphics [ h 30.0 w " + RoseBin_support::ToString(length*7) + " type \"circle\" fill \"#66FFFF\" ]\n"; text +=" Node_Color_ \"66FFFF\" \n"; }else { text += " graphics [ h 30.0 w " + RoseBin_support::ToString(length*7) + " type \"circle\" fill \"#9933FF\" ]\n"; text +=" Node_Color_ \"9933FF\" \n"; } text +=" gid "+RoseBin_support::ToString(parent)+" \n"; text +=" skip_ 1 \n"; text +=" gid_ "+RoseBin_support::ToString(parent)+" ]\n"; // skip functions for now // if (skipFunctions) // text =""; } /*not a func*/ else { SgAsmX86Instruction* bin_inst = isSgAsmX86Instruction(internal); //cerr << " else part " << endl; SgAsmFunction* funcDecl_parent = NULL; if (bin_inst) { funcDecl_parent = isSgAsmFunction(bin_inst->get_parent()); if (funcDecl_parent==NULL) funcDecl_parent = isSgAsmFunction(bin_inst->get_parent()->get_parent()); } if (funcDecl_parent==NULL) { cerr << " ERROR : printNodes preparation . No parent found for node : " << bin_inst->class_name() << " " << hex_address << endl; continue; } if ((pos % 10000)==0) cout << " GMLGraph:: printing GML Nodes : " << pos << endl; string name = getInternalNodes(node, forward_analysis,bin_inst); int parent=0; map <SgAsmFunction*, int>::iterator its = funcMap.find(funcDecl_parent); if (its!=funcMap.end()) parent = funcMap[funcDecl_parent]; if (parent==0) cerr << " GMLGraph parent == 0 " << endl; if (onlyControlStructure && x86InstructionIsControlTransfer(bin_inst)) { text = "node [\n id " + RoseBin_support::ToString(pos) + "\n" + name ; int instrnr = funcDecl_parent->get_childIndex(bin_inst); text +=" instrnr_ "+RoseBin_support::ToString(instrnr)+" \n"; text +=" gid_ "+RoseBin_support::ToString(parent)+" \n"; text +=" gid "+RoseBin_support::ToString(parent)+" ]\n"; } else { text = "node [\n id " + RoseBin_support::ToString(pos) + "\n" + name ; int instrnr = funcDecl_parent->get_childIndex(bin_inst); text +=" instrnr_ "+RoseBin_support::ToString(instrnr)+" \n"; text +=" gid_ "+RoseBin_support::ToString(parent)+" \n"; text +=" gid "+RoseBin_support::ToString(parent)+" ]\n"; } } myfile << text; // cerr << " this node : " << text << endl; } funcMap.clear(); }
/* * Detect functions (blocks) that can be merged together. */ void RoseBin_FlowAnalysis::resolveFunctions(SgAsmNode* globalNode) { //cerr << " ObjDump-BinRose:: Detecting and merging Functions" << endl; vector<SgAsmFunction*> visitedFunctions; vector<SgNode*> tree =NodeQuery::querySubTree(globalNode, V_SgAsmFunction); // vector<SgNode*>::iterator itV = tree.begin(); int nr=0; while (!tree.empty()) { // for (;itV!=tree.end();itV++) { SgAsmFunction* funcD = isSgAsmFunction(tree.back()); tree.pop_back(); nr++; if ((nr % 100)==0) if (RoseBin_support::DEBUG_MODE()) cerr << " funcListSize : " << tree.size() << " -- iteration : " << nr << " func " << funcD->get_name() << endl; //SgAsmFunction* funcD = isSgAsmFunction(*itV); //itV++; ROSE_ASSERT(funcD); // make sure we dont visit a function twice vector <SgNode*> funcVec =funcD->get_traversalSuccessorContainer(); int last = funcVec.size()-1; if (last<0) continue; bool hasStopCondition=false; for (unsigned int itf = 0; itf < funcVec.size() ; itf++) { SgAsmx86Instruction* finst = isSgAsmx86Instruction(funcVec[itf]); ROSE_ASSERT(finst); if (finst->get_kind() == x86_ret || finst->get_kind() == x86_hlt) { hasStopCondition=true; } } //cerr << " last : " << last << endl; SgAsmx86Instruction* lastInst = isSgAsmx86Instruction(funcVec[last]); ROSE_ASSERT(lastInst); SgAsmx86Instruction* nextInst = isSgAsmx86Instruction(resolveFunction(lastInst, hasStopCondition)); if (nextInst) { SgAsmFunction* nextFunc = isSgAsmFunction(nextInst->get_parent()); if (nextFunc) { ROSE_ASSERT(g_algo->info); g_algo->info->returnTargets[funcD].insert(g_algo->info->returnTargets[nextFunc].begin(), g_algo->info->returnTargets[nextFunc].end()); // make sure that this function is being changed and should not be covered again //visitedFunctions.push_back(nextFunc); // visit current function after alternation again //tree.push_back(funcD); // now we remove this next function and iterate thrgouh all instructions and // attach them to the old function vector <SgNode*> funcNextVec =nextFunc->get_traversalSuccessorContainer(); for (unsigned int i=0; i < funcNextVec.size(); ++i) { SgAsmInstruction* inst = isSgAsmInstruction(funcNextVec[i]); ROSE_ASSERT(inst); inst->set_parent(funcD); funcD->append_statement(inst); //nextFunc->remove_statement(inst); // delete nextFunc; // should delete this later when iterator is done } nextFunc->remove_children(); nextFunc->set_parent(NULL); isSgAsmBlock(globalNode)->remove_statement(nextFunc); } } } // for }