/** HashAST::visit * * Called by traverse. Gets the whatever data is of interest and puts * it in the hash. * * @param[in] node to submit to hash **/ void AstHash::visit(SgNode* node) { //Always include the type of each node in the hash VariantT vType = node->variantT(); hasher_.insert(vType); //If it's an instruction, include the mnemonic, and maybe the address SgAsmInstruction* asmInstruction = isSgAsmInstruction(node); if(asmInstruction != NULL) { std::string mnemonic = asmInstruction->get_mnemonic(); hasher_.insert(mnemonic); if(includeAddresses) { rose_addr_t addr = asmInstruction->get_address(); hasher_.insert(addr); } return; } //Always include register references SgAsmRegisterReferenceExpression* regRef = isSgAsmRegisterReferenceExpression(node); if(regRef != NULL) { unsigned regHash = regRef->get_descriptor().hash(); hasher_.insert(regHash); return; } //Maybe inlcude constants (integers, floats, pointers) if(includeConstants) { SgAsmConstantExpression* constExpr = isSgAsmConstantExpression(node); if(constExpr != NULL) { std::string mnemonic = constExpr->get_bitVector().toHex(); hasher_.insert(mnemonic); return; } } }
void colorTable(BinQGUI* instance, const std::vector<int >& addInstr, const std::vector<int >& minusInst, vector_start_at_one<SgNode*>& insnsA, vector_start_at_one<SgNode*>& insnsB ) { if (instance==NULL) return; const char* results [] = {"PLUS", "MINUS"}; std::vector<QColor> colors; colors.push_back( QColor(233,150,122) ); colors.push_back( QColor(135,206,255) ); for( unsigned int choice = 0; choice < sizeof(results)/sizeof(char*) ; choice++ ) { std::string currentName(results[choice]); const std::vector< int >& currentResults = ( choice == 0 ? addInstr : minusInst ); QColor& color = colors[choice]; for (unsigned int k=0;k<currentResults.size();++k) { int insnNr = currentResults[k]; SgAsmInstruction* instA = choice == 1 ? isSgAsmInstruction(insnsA[insnNr]) : NULL; SgAsmInstruction* instB = choice == 0 ? isSgAsmInstruction(insnsB[insnNr]) :NULL; #if 0 cerr << choice << " Found " << currentName << " in A (a:" << a <<",b:"<<b<<") : " << endl << " " << RoseBin_support::HexToString(instA->get_address()) << " " << instA->get_mnemonic() <<endl << " " << RoseBin_support::HexToString(instB->get_address()) << " " << instB->get_mnemonic() <<endl; #endif int myPosA=0; int myPosB=0; if(choice == 1) { for(size_t i=0; i < instance->itemsFileA.size(); i++ ) { SgAsmStatement* stmts = isSgAsmStatement(instance->itemsFileA[i]->statement); // ROSE_ASSERT(stmts); SgAsmInstruction* inst = isSgAsmInstruction(stmts); if (inst && inst->get_address()==instA->get_address()) { myPosA=instance->itemsFileA[i]->row; // instance->itemsFileA[i]->plus=true; instance->itemsFileA[i]->bg=color; #if 0 SgNode* node = instance->itemsFileA[i]->statement; ROSE_ASSERT(node); rose_addr_t rt = instance->itemsFileA[i]->addr; ROSE_ASSERT(rt==instA->get_address()); // delete instance->itemsFileA[i]->bg=QColor(255,0,0); QColor col = instance->itemsFileA[i]->bg; string cols = col.name().toStdString(); // instance->codeTableWidget->setBgColor(instance->itemsFileA[i]->bg,0,i); cerr << "Node " << node->class_name() << " address: " << RoseBin_support::HexToString(instA->get_address()) << " color : " << cols << endl; #endif for (int j=1;j<instance->maxrows;j++) { instance->codeTableWidget->setBgColor(instance->itemsFileA[i]->bg,j,i); } } } } else for(size_t i=0; i < instance->itemsFileB.size(); i++ ) { SgNode* stmts = instance->itemsFileB[i]->statement; SgAsmInstruction* inst = isSgAsmInstruction(stmts); if (inst && inst->get_address()==instB->get_address()) { myPosB=instance->itemsFileB[i]->row; instance->itemsFileB[i]->bg=color; for (int j=1;j<instance->maxrows;j++) instance->codeTableWidget2->setBgColor(instance->itemsFileB[i]->bg,j,i); } } std::string resultsString ="%1 Found " + currentName + " in A (a:%2,b:%3) (a:%4,b:%5) %6 %7 "; QString res = QString( resultsString.c_str()) .arg(k) .arg(insnNr) .arg(insnNr) .arg(myPosA) .arg(myPosB) .arg(QString(RoseBin_support::HexToString(choice == 1 ? instA->get_address() : instB->get_address()).c_str())) .arg(QString( choice == 1 ? instA->get_mnemonic().c_str() : instB->get_mnemonic().c_str())); instance->analysisResult->append(res); } } // if (instance) // instance->updateByteItemList(); }
void RoseBin_FlowAnalysis::checkControlFlow( SgAsmInstruction* binInst, int functionSize, int countDown, string& currentFunctionName, int func_nr) { //cerr << "check control flow" << endl; while (!worklist_forthisfunction.empty()) { SgAsmInstruction* binInst = worklist_forthisfunction.top(); worklist_forthisfunction.pop(); ROSE_ASSERT(binInst); countDown--; int address = binInst->get_address(); ostringstream addrhex; addrhex << hex << setw(8) << address ; ROSE_ASSERT(g_algo->info); vector <VirtualBinCFG::CFGEdge> vec; if (forward_analysis) { vec = binInst->cfgBinOutEdges(g_algo->info); if (isSgAsmx86Instruction(binInst) && isSgAsmx86Instruction(binInst)->get_kind() == x86_call) { // vec.push_back(VirtualBinCFG::CFGEdge(VirtualBinCFG::CFGNode(binInst), VirtualBinCFG::CFGNode(g_algo->info->getInstructionAtAddress(binInst->get_address() + binInst->get_raw_bytes().size())), g_algo->info)); } } else vec = binInst->cfgBinInEdges(g_algo->info); string name = binInst->get_mnemonic(); // if (RoseBin_support::DEBUG_MODE()) // cout << " " << addrhex.str() << " " << func_nr << " :: " << functionSize << // "/" << countDown << " ---------- next CFG instruction : " << name << " vecSize : " << vec.size() << endl; for (int i=0; i < (int)vec.size(); i++) { VirtualBinCFG::CFGEdge edge = vec[i]; VirtualBinCFG::CFGNode cfg_target = edge.target(); VirtualBinCFG::CFGNode cfg_source = edge.source(); if (!forward_analysis) { cfg_target = edge.source(); cfg_source = edge.target(); } SgAsmInstruction* bin_target = isSgAsmInstruction(cfg_target.getNode()); SgAsmInstruction* thisbin = isSgAsmInstruction(cfg_source.getNode()); ROSE_ASSERT(thisbin); SgAsmx86Instruction* thisbinX86 = isSgAsmx86Instruction(thisbin); ROSE_ASSERT (thisbinX86); string src_mnemonic = thisbin->get_mnemonic(); int src_address = thisbin->get_address(); if (analysisName=="callgraph") src_address = funcDecl->get_address(); ostringstream addrhex_s; addrhex_s << hex << setw(8) << src_address ; SgGraphNode* src =NULL; string hexStr = addrhex_s.str(); if (analysisName!="callgraph") { vector<SgGraphNode*> sources; vizzGraph->checkIfGraphNodeExists(hexStr, sources); vector<SgGraphNode*>::const_iterator src_it = sources.begin(); for (;src_it!=sources.end();++src_it) { // should only be one node! adapted to new interface src = *src_it; } if (src==NULL) { // src= vizzGraph->createNode (src_mnemonic, typeNode, src_address, vizzGraph->graph->get_graph_id(), false, thisbin); src= addCFNode (src_mnemonic, typeNode, src_address, false, thisbin); string unp_name = unparseInstructionWithAddress(thisbin); src->append_properties(SgGraph::name,unp_name); if (analysisName=="dfa") src->append_properties(SgGraph::dfa_standard,unp_name); } ROSE_ASSERT(src); if (thisbinX86->get_kind() == x86_call) { uint64_t returnAddr = thisbinX86->get_address() + thisbinX86->get_raw_bytes().size(); ROSE_ASSERT(g_algo->info); SgAsmInstruction* retInsn = g_algo->info->getInstructionAtAddress(returnAddr); if (retInsn) { //worklist_forthisfunction.push(retInsn); //ostringstream tgthex_s; //tgthex_s << hex << setw(8) << returnAddr ; //string tgtStr = tgthex_s.str(); //SgGraphNode* tgt = vizzGraph->checkIfGraphNodeExists(tgtStr); // tps (25 Aug 2008) : this line seems broken! //string mne = retInsn->get_mnemonic(); //if (!tgt) {tgt = vizzGraph->createNode(mne, typeNode, returnAddr, vizzGraph->graph->get_graph_id(), false, retInsn);} // cerr << " ------> Creating return edge : " << thisbinX86->get_address() << " " << returnAddr << endl; // vizzGraph->createEdge( typeEdge, vizzGraph->graph->get_graph_id(), src, thisbinX86->get_address(), tgt, returnAddr); } } } else if (analysisName=="callgraph") { // These are special cases that annotate the call graph (nodes) // so that the visualization can pick up the properties and color correctly ROSE_ASSERT(g_algo->info); if (thisbinX86->get_kind() == x86_jmp) { if (thisbinX86->cfgBinOutEdges(g_algo->info).empty()) { funcDeclNode->append_properties(SgGraph::nodest_jmp,RoseBin_support::ToString("nodest_jmp")); } } else if (thisbinX86->get_kind() == x86_call) { //cerr << "CallGRAPH: Found call : " << // RoseBin_support::HexToString(VirtualBinCFG::CFGNode(thisbinX86).getNode()->get_address()) << " to " << // RoseBin_support::HexToString(VirtualBinCFG::CFGNode(g_algo->info->getInstructionAtAddress(thisbinX86->get_address() + thisbinX86->get_raw_bytes().size())).getNode()->get_address()) << endl; vector<VirtualBinCFG::CFGEdge> dests = thisbinX86->cfgBinOutEdges(g_algo->info); dests.push_back(VirtualBinCFG::CFGEdge(VirtualBinCFG::CFGNode(thisbinX86), VirtualBinCFG::CFGNode(g_algo->info->getInstructionAtAddress(thisbinX86->get_address() + thisbinX86->get_raw_bytes().size())), g_algo->info)); if (!dests.empty()) { SgAsmNode* parent = isSgAsmNode(dests[0].target().getNode()->get_parent()); if (!db) parent = isSgAsmNode(parent->get_parent()); if (parent) { SgAsmFunction* funcdestparent = isSgAsmFunction(parent); string trg_func_name = funcdestparent->get_name(); if (trg_func_name==currentFunctionName) { funcDeclNode->append_properties(SgGraph::itself_call,RoseBin_support::ToString("itself_call")); } } } else { funcDeclNode->append_properties(SgGraph::nodest_call,RoseBin_support::ToString("nodest_call")); //cerr << " no destination found for call " << addrhex.str() << endl; } } else if (thisbinX86->get_kind() == x86_int) { funcDeclNode->append_properties(SgGraph::interrupt,RoseBin_support::ToString("interrupt")); } } if (bin_target!=NULL) { string trg_func_name = ""; int trg_func_address =1; string hexStrf = ""; SgAsmFunction* funcDeclparent=NULL; if (analysisName=="callgraph") { SgAsmNode* parent = dynamic_cast<SgAsmNode*>(bin_target->get_parent()); if (parent==NULL) continue; if (!db) parent = isSgAsmNode(parent->get_parent()); ROSE_ASSERT(parent); funcDeclparent = isSgAsmFunction(parent); ROSE_ASSERT(funcDeclparent); trg_func_name = funcDeclparent->get_name(); trg_func_address = funcDeclparent->get_address(); ostringstream addrhex_tf; addrhex_tf << hex << setw(8) << trg_func_address ; hexStrf = addrhex_tf.str(); //cerr << " CALLGRAPH TARGET PARENT : " << hexStrf << endl; } string trg_mnemonic = bin_target->get_mnemonic(); int trg_address = bin_target->get_address(); ostringstream addrhex_t; addrhex_t << hex << setw(8) << trg_address ; if (RoseBin_support::DEBUG_MODE()) cout << " OUTEDGES TO: vec[" << i << "/" << vec.size() << "] :" << addrhex_t.str() << " " << trg_mnemonic << endl; string hexStr = addrhex_t.str(); SgGraphNode* trg=NULL; vector<SgGraphNode*> targets; if (analysisName=="callgraph") vizzGraph->checkIfGraphNodeExists(hexStrf, targets); else vizzGraph->checkIfGraphNodeExists(hexStr, targets); vector<SgGraphNode*>::const_iterator src_it = targets.begin(); for (;src_it!=targets.end();++src_it) { // should only be one node! adapted to new interface trg = *src_it; } //ROSE_ASSERT(trg); bool target_visited = false; // DQ (4/23/2009): We want the type defined in the base class. // rose_hash::unordered_map <string, SgAsmInstruction*>::iterator vis = local_visited.find(hexStr); // CH (4/9/2010): Use boost::unordered instead //#ifndef _MSCx_VER #if 1 rose_hash::unordered_map <string, SgAsmInstruction*>::iterator vis = local_visited.find(hexStr); #else rose_hash::unordered_map <string, SgAsmInstruction*,rose_hash::hash_string>::iterator vis = local_visited.find(hexStr); #endif if (vis!=local_visited.end()) target_visited=true; if (trg==NULL) { if (analysisName=="callgraph") { // cerr << " >>> TARGET FUNC NAME " << trg_func_name << endl; //trg = vizzGraph->createNode (trg_func_name, typeNode, trg_func_address, vizzGraph->graph->get_graph_id(),false, funcDeclparent); trg = addCFNode (trg_func_name, typeNode, trg_func_address,false, funcDeclparent); } else { //trg = vizzGraph->createNode (trg_mnemonic, typeNode, trg_address, vizzGraph->graph->get_graph_id(),false, bin_target); trg = addCFNode (trg_mnemonic, typeNode, trg_address, false, bin_target); } string unp_name = unparseInstructionWithAddress(bin_target); //cout << " (target==NULL) unparse name : " << unp_name << endl; trg->append_properties(SgGraph::name,unp_name); if (analysisName=="dfa") trg->append_properties(SgGraph::dfa_standard,unp_name); } else { string unp_name = unparseInstructionWithAddress(bin_target); //cout << " unparse name : " << unp_name << endl; trg->append_properties(SgGraph::name,unp_name); if (analysisName=="dfa") trg->append_properties(SgGraph::dfa_standard,unp_name); } ROSE_ASSERT(trg); local_visited[hexStr] = bin_target; string name=""; if (analysisName=="callgraph") name = RoseBin_support::ToString(src_address)+RoseBin_support::ToString(trg_func_address); else name = RoseBin_support::ToString(src_address)+RoseBin_support::ToString(trg_address); bool exists = vizzGraph->checkIfDirectedGraphEdgeExists(src, trg); if (!exists) { if (analysisName=="callgraph") { if (currentFunctionName!=trg_func_name && thisbinX86->get_kind() != x86_ret) { // SgDirectedGraphEdge* edge = vizzGraph->createEdge( typeEdge, vizzGraph->graph->get_graph_id(), funcDeclNode, src_address, trg, trg_func_address); SgDirectedGraphEdge* edge = vizzGraph->addDirectedEdge( funcDeclNode, trg, typeEdge); //cerr << "CallGraph : create edge : " << RoseBin_support::HexToString(src_address) << " to func : " << RoseBin_support::HexToString(trg_func_address) << endl; vizzGraph->setProperty(SgGraph::type, edge, RoseBin_support::ToString(SgGraph::cfg)); } } else { //string addr = RoseBin_support::HexToString(binInst->get_address()); //if (addr==" 8048392" || addr==" 80482fd") // cerr << " >>>>>>>>>> found " << addr << " -- target_address : " << RoseBin_support::HexToString(trg_address) << endl; // SgDirectedGraphEdge* edge =vizzGraph->createEdge( typeEdge, vizzGraph->graph->get_graph_id(), src, src_address, trg, trg_address); SgDirectedGraphEdge* edge = vizzGraph->addDirectedEdge( src, trg, typeEdge); vizzGraph->setProperty(SgGraph::type, edge, RoseBin_support::ToString(SgGraph::cfg)); } } if (analysisName!="callgraph") { // handle return edges SgAsmStatementPtrList sources = thisbin->get_sources(); SgAsmStatementPtrList::iterator it = sources.begin(); for (;it!=sources.end();++it) { SgAsmInstruction* instT = isSgAsmInstruction(*it); //cerr << " This node is called from : " << instT->get_address() << endl; ostringstream addr_t; addr_t << hex << setw(8) << instT->get_address() ; SgGraphNode* trg =NULL; string hexStr = addr_t.str(); vector<SgGraphNode*> targets; vizzGraph->checkIfGraphNodeExists(hexStr, targets); vector<SgGraphNode*>::const_iterator src_it = targets.begin(); for (;src_it!=targets.end();++src_it) { // should only be one node! adapted to new interface trg = *src_it; } //trg= vizzGraph->checkIfGraphNodeExists(hexStr); if (trg==NULL) { string hexa = RoseBin_support::HexToString(instT->get_address()); hexa = hexa.substr(1,hexa.size()); string name = "0x"+hexa+":"+instT->get_mnemonic(); //trg= vizzGraph->createNode (name, typeNode, instT->get_address(), vizzGraph->graph->get_graph_id(), false, instT); trg= addCFNode(name, typeNode, instT->get_address(), false, instT); } bool exists = vizzGraph->checkIfDirectedGraphEdgeExists( trg,src); if (!exists) { bool same = sameParents(trg,src); if (!same) { SgDirectedGraphEdge* edge =vizzGraph->addDirectedEdge( trg, src, typeEdge); //SgDirectedGraphEdge* edge =vizzGraph->createEdge( typeEdge, vizzGraph->graph->get_graph_id(), trg, instT->get_address(), src, src_address); vizzGraph->setProperty(SgGraph::type, edge, RoseBin_support::ToString(SgGraph::cfg)); } } } } if (!target_visited) { // check if target is in the same function!!! SgAsmNode* block = bin_target; if (!db) block = isSgAsmNode(bin_target->get_parent()); ROSE_ASSERT(block); SgAsmFunction* funcPar = isSgAsmFunction(block->get_parent()); if (funcPar) { string nameFunc = funcPar->get_name(); if (nameFunc==currentFunctionName) { //checkControlFlow(bin_target, functionSize, countDown, currentFunctionName); worklist_forthisfunction.push(bin_target); } } else { if (RoseBin_support::DEBUG_MODE()) cerr << " ERROR:: Target Instruction has no parent! " << bin_target->class_name() << endl; } } // if visited } else { nr_target_missed++; if (binInst) if (RoseBin_support::DEBUG_MODE()) cerr << " WARNING:: no target found for " << RoseBin_support::HexToString(binInst->get_address()) << " " << binInst->class_name() << endl; } } } // if (RoseBin_support::DEBUG_MODE()) // cout << " ------------------------ done with instr: " << name << " " << addrhex.str() << endl; }
/**************************************************** * traverse the binary AST ****************************************************/ void RoseBin_FlowAnalysis::visit(SgNode* node) { // cerr << " traversing node " << node->class_name() << endl; if (isSgAsmFunction(node) ) { SgAsmFunction* binDecl = isSgAsmFunction(node); string name = binDecl->get_name(); ostringstream addrhex; addrhex << hex << setw(8) << binDecl->get_address() ; if (name=="") { name=addrhex.str(); binDecl->set_name(name); } SgAsmStatement* stat = NULL; // SgAsmStatementPtrList& list = binDecl->get_statementList(); vector<SgAsmInstruction*> list; FindInstructionsVisitor vis; AstQueryNamespace::querySubTree(binDecl, std::bind2nd( vis, &list )); int sizeList = list.size(); if (sizeList==0) { //cerr << " this function is empty!! " << endl; return; } //if ((func_nr % 1)==0) // if (RoseBin_support::DEBUG_MODE()) // cout << analysisName << " Func Nr: " << (++func_nr) << " blocks:" << // sizeList << " ***************** checking function : " << name << endl; if (forward_analysis) { stat = list.front(); } else { // get the last instruction in a function (backward control flow) stat = list.back(); } ROSE_ASSERT(stat); // if (RoseBin_support::DEBUG_MODE()) //cout << ">>>>>>>>>>>>>. checking statement in function : " << name << " .. " << stat->class_name() << endl; if (isSgAsmInstruction(stat)) { SgAsmInstruction* inst = isSgAsmInstruction(stat); ROSE_ASSERT(inst); // check the control flow of the first instruction in a function string typeFunction ="function"; SgGraphNode* src=NULL; if (analysisName=="callgraph") { // src = vizzGraph->createNode (name, typeFunction, binDecl->get_address(), vizzGraph->graph->get_graph_id(), false, binDecl); src = addCFNode (name, typeFunction, binDecl->get_address(), false, binDecl); } else { //src = vizzGraph->createNode (name, typeFunction, binDecl->get_address(), vizzGraph->graph->get_graph_id(), true, binDecl); //cerr << ">> adding node (f) src: " << RoseBin_support::HexToString(binDecl->get_address()) << endl; src = addCFNode (name, typeFunction, binDecl->get_address(), true, binDecl); string mnemonic=inst->get_mnemonic(); //SgGraphNode* trg = vizzGraph->createNode (mnemonic, typeNode, inst->get_address(), vizzGraph->graph->get_graph_id(),false, inst); //cerr << ">> adding node (first) trg: " << RoseBin_support::HexToString(inst->get_address()) << endl; SgGraphNode* trg = addCFNode (mnemonic, typeNode, inst->get_address(), false, inst); string unp_name = unparseInstructionWithAddress(inst); trg->append_properties(SgGraph::name,unp_name); if (analysisName=="dfa") trg->append_properties(SgGraph::dfa_standard,unp_name); //cerr << "Create edge " << endl; // SgDirectedGraphEdge* edge = vizzGraph->createEdge ( typeFunction, vizzGraph->graph->get_graph_id(), src, binDecl->get_address(), trg, inst->get_address()); SgDirectedGraphEdge* edge = vizzGraph->addDirectedEdge ( src, trg, typeFunction); vizzGraph->setProperty(SgGraph::type, edge, RoseBin_support::ToString(SgGraph::cfg)); } local_visited.clear(); worklist_forthisfunction.push(inst); funcDecl = binDecl; funcDeclNode = src; checkControlFlow(inst, sizeList, sizeList, name, func_nr); } else { if (RoseBin_support::DEBUG_MODE()) cerr << "This is not an Instruction " << endl; } } }