/* * 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); }
/* * This function removes blocks, so functions contain only instructions * deprecated! */ void RoseBin_FlowAnalysis::flattenBlocks(SgAsmNode* globalNode) { vector<SgNode*> tree =NodeQuery::querySubTree(globalNode, V_SgAsmBlock); vector<SgNode*>::iterator itV = tree.begin(); //cerr << " ObjDump-BinRose:: Removing Blocks " << endl; for (;itV!=tree.end();itV++) { SgAsmBlock* block = isSgAsmBlock(*itV); if (block && block!=globalNode) { SgAsmFunction* func = isSgAsmFunction(block->get_parent()); if (func) { ROSE_ASSERT(g_algo->info); g_algo->info->returnTargets[func].insert(g_algo->info->returnTargets[block].begin(), g_algo->info->returnTargets[block].end()); 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); } func->remove_statement(block); } } } }
/**************************************************** * process all instructions in the DB * add the instructions to the blocks ****************************************************/ void RoseBin_DB_IDAPRO::process_instruction_query(MYSQL* conn, MYSQL_RES* res_set) { rememberInstructions.clear(); // get the functions // char* q = (char*)"SELECT * FROM instructions_1"; char *q = (char*)"select *, (select parent_function from basic_blocks_1 where id = i.basic_block_id and (i.address - parent_function) >= 0 and (i.address - parent_function) = (select min(i.address - parent_function) from basic_blocks_1 where id = i.basic_block_id and (i.address - parent_function) >= 0) ) as i_f from instructions_1 i order by i.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; string mnemonic=(char*)""; uint64_t address=0; int basic_block=-1; int sequence =-1; string data=(char*)""; int i_func; 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) basic_block = -1; if (i==2) mnemonic = ret; if (i==3) sequence = -1; if (i==4) data=ret; if (i==5) i_func= -1; } else { ret= row[i]; if (i==0) address = atoi(ret); if (i==1) basic_block = atoi(ret); if (i==2) mnemonic = ret; if (i==3) sequence = atoi(ret); if (i==4) data=ret; if (i==5) i_func = atoi(ret); } } // patched to adjust to objdump , Apr 26 2007 if (mnemonic ==(char*)"retn") mnemonic = (char*)"ret"; if (RoseBin_support::DEBUG_MODE()) { ostringstream addrhex; addrhex << hex << setw(8) << address ; cout << ">> creating instruction : " << addrhex.str() << " " << address << " - " << basic_block << " - " << mnemonic << " - " << sequence << endl; } // check if it is an instruction or if it appears in the callgraph, // if it is in the callgraph, one wants to create a BinaryCall instead // append the instruction to its function rose_hash::unordered_map <int, SgAsmFunction* >::iterator func_it = rememberFunctions.find(i_func); SgAsmFunction* func = NULL; // for (func_it; func_it!=rememberFunctions.end(); ++func_it) { if (func_it != rememberFunctions.end()) { func = func_it->second; } else { if (i_func!=-1) cerr << " ERROR : cant find the function i_func : " << i_func << " in rememberFunctions for instruction : " << mnemonic << endl; } SgAsmInstruction* instruction = NULL; instruction = createInstruction(address, func, mnemonic); // instruction = new SgAsmInstruction(address,bb,mnemonic,""); // Sep 29, tps : commented the following line out, since the function was removed. //instruction->set_raw_bytes(data); ROSE_ASSERT(instruction); SgAsmOperandList* operandList = new SgAsmOperandList(); instruction->set_operandList(operandList); operandList->set_parent(instruction); ostringstream hexaddr; hexaddr << hex << setw(8) << address ; if (RoseBin_support::DEBUG_MODE()) cout << " .rememberInstruction " << instruction->class_name() << " at : " << address << " hex: " << hexaddr.str() << endl; rememberInstructions[address]= instruction ; if (func) { // get the block in the func and append to it to conform to jeremiah func->append_statement(instruction); instruction->set_parent(func); //vector <SgNode*> blockVec =func->get_traversalSuccessorContainer(); //SgAsmBlock* block = isSgAsmBlock(blockVec[0]); //ROSE_ASSERT(block); //block->append_statement(instruction); //instruction->set_parent(block); ROSE_ASSERT(instruction->get_parent()); //SgAsmNode* nInst = (SgAsmNode*) instruction; //nInst->set_parent(func); ostringstream addrhex; addrhex << hex << setw(8) << i_func ; if (RoseBin_support::DEBUG_MODE()) cout << ">> appended instruction to function: " << func->get_name() << " addr " << addrhex.str() << " " << address << endl; } else { if (i_func!=-1) { cerr << " ERROR :: could not append instruction to function : " << endl; //exit(0); } } } // 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 }