/* * Converts blocks to functions (is not part of Jeremiahs disassembler - and also IDA) * deprecated! */ void RoseBin_FlowAnalysis::convertBlocksToFunctions(SgAsmNode* globalNode) { vector<SgNode*> tree =NodeQuery::querySubTree(globalNode, V_SgAsmBlock); vector<SgNode*>::iterator itV = tree.begin(); //cerr << " ObjDump-BinRose:: Converting Blocks To Functions" << endl; for (;itV!=tree.end();itV++) { SgAsmBlock* block = isSgAsmBlock(*itV); if (block && block!=globalNode) { uint64_t addr = block->get_address(); isSgAsmBlock(globalNode)->remove_statement(block); block->set_parent(NULL); SgAsmFunction* func = new SgAsmFunction(addr, RoseBin_support::HexToString(addr)); ROSE_ASSERT(g_algo->info); g_algo->info->returnTargets[func].insert(g_algo->info->returnTargets[block].begin(), g_algo->info->returnTargets[block].end()); isSgAsmBlock(globalNode)->append_statement(func); func->set_parent(globalNode); vector <SgNode*> vec =block->get_traversalSuccessorContainer(); for (unsigned int itf = 0; itf < vec.size() ; itf++) { SgAsmInstruction* finst = isSgAsmInstruction(vec[itf]); finst->set_parent(func); func->append_statement(finst); } block->remove_children(); } } // string filename="_binary_tree_func.dot"; //AST_BIN_Traversal* trav = new AST_BIN_Traversal(); //trav->run(globalNode, filename); }
/**************************************************** * process all functions in the DB ****************************************************/ void RoseBin_DB_IDAPRO::process_functions_query(MYSQL* conn, MYSQL_RES* res_set, SgAsmBlock* globalBlock, list<string> functionFilter) { // get the functions rememberFunctions.clear(); //int counter=0; char* q = (char*)"SELECT * FROM functions_1 order by address"; if (RoseBin_support::DEBUG_MODE()) cout << "\n>> QUERY:: " << q << "\n" << endl; res_set = process_query(conn,q); if (res_set == NULL) { print_problemWithResults(conn); } else { MYSQL_ROW row; long address=0; string name = (char*)""; int type=-1; string name_md5 =(char*)""; while ((row = mysql_fetch_row(res_set))!=NULL) { for (unsigned int i=0; i<mysql_num_fields(res_set);i++) { char* ret=(char*)""; if (row[i] ==NULL) { ret = (char*)"<NULL>"; if (i==0) address = -1; if (i==1) name = ret; if (i==2) type= -1; if (i==3) name_md5= ret; } else { ret= row[i]; if (i==0) address = atoi(ret); if (i==1) name = ret; if (i==2) type= atoi(ret); if (i==3) name_md5= ret; } } // demangling ***************************************************** // we need to demangle this function name, so // we can correspond it with the source name char *newName;// = new char[size*2]; int status; size_t length; newName = abi::__cxa_demangle(name.c_str(), 0, &length,&status); // cerr << "converting name : " << name << " status: " << status <<endl; if (status==0) { name =(char*)""; bool found_bracket=false; for (unsigned int i=0; i<length;i++) { if (newName[i]=='(') found_bracket=true; if (found_bracket==false) name += newName[i]; } if (RoseBin_support::DEBUG_MODE()) cout << " demangling name to " << name << endl; } name = getName(name); RoseBin_support::checkText(name); //cerr << " checking for function : " << name << endl; // demangling ***************************************************** // filter : we filter away all kind of functions that are not // relevant == slicing of binaries, relevant = source AST functions // if (functionFilter.size()>0) { // list<string>::iterator filterMe = functionFilter.begin(); // bool skip=true; if (!functionFilter.empty() && std::find(functionFilter.begin(), functionFilter.end(), name) == functionFilter.end()) { continue; } #if 0 for (filterMe;filterMe!=functionFilter.end();++filterMe) { string name_list = *filterMe; // cerr << " comparing strings : " << name_list << " and " << name << endl; if (name_list==name) { // if (name.find(name_list)!=string::npos) skip=false; } } if (skip) continue; #endif // } //make sure we dont get too many nodes, so the visualization works for testing // find me : counter //counter++; //if (counter>50) // break; // -------------------------------------------------------------------------- if (RoseBin_support::DEBUG_MODE()) { ostringstream addrhex; addrhex << hex << setw(8) << address ; cout << ">> creating function : " << address << " " << addrhex.str() << " - " << name << " - " << type << endl; } SgAsmFunction* fd = new SgAsmFunction(); fd->set_address(address); fd->set_name(name); globalBlock->append_statement(fd); fd->set_parent(globalBlock); // added a block between function and instruction to conform to jeremiahs code //SgAsmBlock* block = new SgAsmBlock(); //fd->append_statement(block); //block->set_parent(fd); rememberFunctions[address]= fd ; } // while } // if (res_set==NULL) checkError(conn,res_set); }
/* * 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 }