/*
 * 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);
      }

    }
  }


}
Esempio n. 3
0
/****************************************************
 * 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

}