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

}
Example #2
0
/****************************************************
 * 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

}