Beispiel #1
0
BtorTranslationPolicy::BtorTranslationPolicy(BtorTranslationHooks* hooks, uint32_t minNumStepsToFindError, uint32_t maxNumStepsToFindError, SgProject* proj): problem(), hooks(hooks), regdict(NULL) {
  assert (minNumStepsToFindError >= 1); // Can't find an error on the first step
  assert (maxNumStepsToFindError < 0xFFFFFFFFU); // Prevent overflows
  assert (minNumStepsToFindError <= maxNumStepsToFindError || maxNumStepsToFindError == 0);
  makeRegMap(origRegisterMap, "");
  makeRegMapZero(newRegisterMap);
  isValidIp = false_();
  validIPs.clear();
  Comp stepCount = problem.build_var(32, "stepCount_saturating_at_" + boost::lexical_cast<std::string>(maxNumStepsToFindError + 1));
  addNext(stepCount, ite(problem.build_op_eq(stepCount, number<32>(maxNumStepsToFindError + 1)), number<32>(maxNumStepsToFindError + 1), problem.build_op_inc(stepCount)));
  resetState = problem.build_op_eq(stepCount, zero(32));
  errorsEnabled =
    problem.build_op_and(
      problem.build_op_ugte(stepCount, number<32>(minNumStepsToFindError)),
      (maxNumStepsToFindError == 0 ?
       true_() :
       problem.build_op_ulte(stepCount, number<32>(maxNumStepsToFindError))));
  {
    vector<SgNode*> functions = NodeQuery::querySubTree(proj, V_SgAsmFunction);
    for (size_t i = 0; i < functions.size(); ++i) {
      functionStarts.push_back(isSgAsmFunction(functions[i])->get_address());
      // fprintf(stderr, "functionStarts 0x%"PRIx64"\n", isSgAsmFunction(functions[i])->get_address());
    }
  }
  {
    vector<SgNode*> blocks = NodeQuery::querySubTree(proj, V_SgAsmBlock);
    for (size_t i = 0; i < blocks.size(); ++i) {
      SgAsmBlock* b = isSgAsmBlock(blocks[i]);
      if (!b->get_statementList().empty() && isSgAsmx86Instruction(b->get_statementList().front())) {
        blockStarts.push_back(b->get_address());
        // fprintf(stderr, "blockStarts 0x%"PRIx64"\n", b->get_address());
      }
    }
  }
  {
    vector<SgNode*> calls = NodeQuery::querySubTree(proj, V_SgAsmx86Instruction);
    for (size_t i = 0; i < calls.size(); ++i) {
      SgAsmx86Instruction* b = isSgAsmx86Instruction(calls[i]);
      if (b->get_kind() != x86_call) continue;
      returnPoints.push_back(b->get_address() + b->get_raw_bytes().size());
      // fprintf(stderr, "returnPoints 0x%"PRIx64"\n", b->get_address() + b->get_raw_bytes().size());
    }
  }
  {
    vector<SgNode*> instructions = NodeQuery::querySubTree(proj, V_SgAsmx86Instruction);
    for (size_t i = 0; i < instructions.size(); ++i) {
      SgAsmx86Instruction* b = isSgAsmx86Instruction(instructions[i]);
      validIPs.push_back(b->get_address());
    }
  }
}
SgAsmInstruction*
RoseBin_FlowAnalysis::resolveFunction(SgAsmInstruction* instx, bool hasStopCondition) {
  SgAsmx86Instruction* inst = isSgAsmx86Instruction(instx);
  if (inst==NULL) return NULL;
  ROSE_ASSERT(g_algo->info);
  SgAsmInstruction* nextFlow = inst->cfgBinFlowOutEdge(g_algo->info);
  // if current node is not a controltransfer node (e.g. jmp, ret, ...),
  // then there should be a flow to a next node
  //  SgAsmx86ControlTransferInstruction* contrlInst = isSgAsmx86ControlTransferInstruction(inst);
  if (nextFlow==NULL &&
      hasStopCondition==false) { // && !isSgAsmx86Jmp(inst)) {
    // in this case, we have a ordinary node that should be connected to the next block
    // now lets find the next block and create a function for these two blocks
    uint64_t addrInst = inst->get_address();
    uint64_t size = (inst->get_raw_bytes()).size();
    uint64_t nextAddr = addrInst+size;
    rose_hash::unordered_map <uint64_t, SgAsmInstruction* >::const_iterator it2 =
      rememberInstructions.find(nextAddr);
    if (it2!=rememberInstructions.end()) {
      // found the next instruction
      nextFlow = isSgAsmInstruction(it2->second);
      //if (RoseBin_support::DEBUG_MODE())
      //        cout << " function resolution: resolving next : " << nextFlow->class_name() << "    this : "
      //             << unparser->unparseInstruction(inst) << endl;
    }
  }

  else if (nextFlow==NULL &&
           hasStopCondition==false && inst->get_kind() == x86_jmp) {
    // in this case we want to connect to the destination
    ROSE_ASSERT(g_algo->info);
    nextFlow = inst->cfgBinFlowOutEdge(g_algo->info);
    //if (RoseBin_support::DEBUG_MODE())
    // cerr << " function resolution: resolving jump " << nextFlow << "  this : " << inst->class_name() << endl;
  } else {
    if (RoseBin_support::DEBUG_MODE())
      if (!(inst->get_kind() == x86_nop || inst->get_kind() == x86_ret))
        cerr << " WARNING: function resolution::  cant resolve :  " << inst->class_name() << "(" << unparseInstruction(inst) << ")" << endl;
  }

  return nextFlow;
}
void
RoseBin_FlowAnalysis::process_jumps() {
    if (RoseBin_support::DEBUG_MODE())
      cerr << "\n >>>>>>>>> processing jumps ... " << endl;
  rose_hash::unordered_map <uint64_t, SgAsmInstruction* >::iterator it;
  for (it=rememberInstructions.begin();it!=rememberInstructions.end();++it) {
    SgAsmx86Instruction* inst = isSgAsmx86Instruction(it->second);
    if (inst->get_kind() == x86_call) {
      //cerr << "Found call at " << std::hex << inst->get_address() << endl;
      SgAsmx86Instruction* target = isSgAsmx86Instruction(process_jumps_get_target(inst));
      if (target) {
        //cerr << "Target is " << std::hex << target->get_address() << endl;
        // inst->get_targets().push_back(target);
        // we set the sources (for each node)
        ROSE_ASSERT(g_algo->info);
        g_algo->info->incomingEdges[target].insert(inst->get_address());
        // tps: changed this algorithm so that it runs in
        // linear time!
        ROSE_ASSERT (target->get_parent());
        if (target->get_parent()) {
          // ROSE_ASSERT(target->get_parent());
          SgAsmNode* b_b = target;
          if (!db)
            b_b = isSgAsmNode(target->get_parent());
          ROSE_ASSERT(b_b);
          SgAsmFunction* b_func = isSgAsmFunction(b_b->get_parent());

          if (b_func) {
            // (16/Oct/07) tps: this is tricky, it appears that sometimes the target can
            // be just a jmp to a new location, so we should forward this information to the correct
            // function.
            // Therefore we need to check if the current function has a return statement.
            // If not, we want to forward this information.
            if (target->get_kind() == x86_jmp) {
              //cerr << " >>>>>>>> found a jmp target - number of children: " << b_func->get_traversalSuccessorContainer().size() << endl;
              if (b_func->get_numberOfTraversalSuccessors()==1) {
                SgAsmx86Instruction* target2 = isSgAsmx86Instruction(process_jumps_get_target(inst));
                if (target2) {
                  b_b = target2;
                  if (!db)
                    b_b = isSgAsmNode(target2->get_parent());
                  b_func = isSgAsmFunction(b_b->get_parent());
                }
              }
            }


            if (inst->get_parent()) {
              //cerr << "Inst has a parent" << endl;
              if (inst->get_comment()=="")
                inst->set_comment(""+b_func->get_name());
              ROSE_ASSERT(g_algo->info);
              SgAsmInstruction* inst_after = g_algo->info->getInstructionAtAddress(inst->get_address() + inst->get_raw_bytes().size()); // inst->cfgBinFlowOutEdge(info);
              if (inst_after) {
                //cerr << "Added dest " << std::hex << isSgAsmStatement(inst_after)->get_address() << " for function" << endl;
                b_func->append_dest(isSgAsmStatement(inst_after));
              }
            }
          } else {
            if (RoseBin_support::DEBUG_MODE())
            cerr << " NO FUNCTION DETECTED ABOVE BLOCK . " << endl;
          }

        } else {
          if (RoseBin_support::DEBUG_MODE())
            cerr << "   WARNING :: process_jumps: target has no parent ... i.e. no FunctionDeclaration to it " <<
            target->class_name() << endl;
        }
      } else {
        if (inst)
          if (RoseBin_support::DEBUG_MODE())
            cerr << "    WARNING :: process_jumps: No target found for node " << RoseBin_support::HexToString(inst->get_address())
                 << "   " << inst->get_mnemonic() << endl;
      }
    } else {

      // might be a jmp
      SgAsmx86Instruction* target = isSgAsmx86Instruction(process_jumps_get_target(inst));
      if (target) {
        // inst->get_targets().push_back(target);
        // we set the sources (for each node)
        ROSE_ASSERT(g_algo->info);
        g_algo->info->incomingEdges[target].insert(inst->get_address());
      }
    }
  }
  //cerr << "\n >>>>>>>>> processing jumps ... done. " << endl;

  //  cerr << "\n >>>>>>>>> resolving RET jumps ... " << endl;
  rose_hash::unordered_map <uint64_t, SgAsmInstruction* >::iterator it2;
  for (it2=rememberInstructions.begin();it2!=rememberInstructions.end();++it2) {
    //int id = it2->first;
    SgAsmx86Instruction* target = isSgAsmx86Instruction(it2->second);
    ROSE_ASSERT (target);
#if 1
    if (target->get_kind() == x86_ret) {
      SgAsmNode* b_b = target;
      if (!db)
        b_b = isSgAsmNode(target->get_parent());
      SgAsmFunction* parent = isSgAsmFunction(b_b->get_parent());
      if (parent) {
        //ROSE_ASSERT(parent);
        std::vector <SgAsmStatement*> dest_list = parent->get_dest();
        for (size_t i = 0; i < dest_list.size(); ++i) {
          ROSE_ASSERT (isSgAsmInstruction(dest_list[i]));
          //cerr << "Adding ret target " << std::hex << dest_list[i]->get_address() << " to " << std::hex << target->get_address() << endl;
          //info->indirectJumpAndReturnTargets[target].insert(dest_list[i]->get_address());
          ROSE_ASSERT(g_algo->info);
          g_algo->info->incomingEdges[isSgAsmInstruction(dest_list[i])].insert(target->get_address());
        }

        std::vector <SgAsmStatement*>::iterator it3 = dest_list.begin();
        for (; it3!=dest_list.end();++it3) {
          SgAsmInstruction* dest = isSgAsmInstruction(*it3);
          if (dest) {
            dest->append_sources(target);
            //cerr << " appending source to " << dest->get_address() << "   target: " << target->get_address() << endl;
          }
        } // for
      } else { // if parent
        if (RoseBin_support::DEBUG_MODE())
          cerr << "   ERROR :: RET jumps :: no parent found for ret : " << target->class_name() << endl;
        //exit (0);
      }
    } // if ret
#endif
  }
  if (RoseBin_support::DEBUG_MODE())
    cerr << " >>>>>>>>> resolving RET jumps ... done." << endl;
}