BinaryAnalysis::Disassembler::AddressSet SgAsmX86Instruction::getSuccessors(const std::vector<SgAsmInstruction*>& insns, bool *complete, const MemoryMap::Ptr &initial_memory) { Stream debug(mlog[DEBUG]); using namespace Rose::BinaryAnalysis::InstructionSemantics2; if (debug) { debug <<"SgAsmX86Instruction::getSuccessors(" <<StringUtility::addrToString(insns.front()->get_address()) <<" for " <<insns.size() <<" instruction" <<(1==insns.size()?"":"s") <<"):" <<"\n"; } BinaryAnalysis::Disassembler::AddressSet successors = SgAsmInstruction::getSuccessors(insns, complete); /* If we couldn't determine all the successors, or a cursory analysis couldn't narrow it down to a single successor then * we'll do a more thorough analysis now. In the case where the cursory analysis returned a complete set containing two * successors, a thorough analysis might be able to narrow it down to a single successor. We should not make special * assumptions about CALL and FARCALL instructions -- their only successor is the specified address operand. */ if (!*complete || successors.size()>1) { const RegisterDictionary *regdict; if (SgAsmInterpretation *interp = SageInterface::getEnclosingNode<SgAsmInterpretation>(this)) { regdict = RegisterDictionary::dictionary_for_isa(interp); } else { switch (get_baseSize()) { case x86_insnsize_16: regdict = RegisterDictionary::dictionary_i286(); break; case x86_insnsize_32: regdict = RegisterDictionary::dictionary_pentium4(); break; case x86_insnsize_64: regdict = RegisterDictionary::dictionary_amd64(); break; default: ASSERT_not_reachable("invalid x86 instruction size"); } } const RegisterDescriptor IP = regdict->findLargestRegister(x86_regclass_ip, 0); PartialSymbolicSemantics::RiscOperatorsPtr ops = PartialSymbolicSemantics::RiscOperators::instance(regdict); ops->set_memory_map(initial_memory); BaseSemantics::DispatcherPtr cpu = DispatcherX86::instance(ops, IP.get_nbits(), regdict); try { BOOST_FOREACH (SgAsmInstruction *insn, insns) { cpu->processInstruction(insn); SAWYER_MESG(debug) <<" state after " <<insn->toString() <<"\n" <<*ops; } BaseSemantics::SValuePtr ip = ops->readRegister(IP); if (ip->is_number()) { successors.clear(); successors.insert(ip->get_number()); *complete = true; } } catch(const BaseSemantics::Exception &e) {
BinaryAnalysis::Disassembler::AddressSet SgAsmM68kInstruction::getSuccessors(const std::vector<SgAsmInstruction*>& insns, bool *complete, const BinaryAnalysis::MemoryMap::Ptr &initial_memory) { using namespace Rose::BinaryAnalysis::InstructionSemantics2; Stream debug(mlog[DEBUG]); if (debug) { debug <<"SgAsmM68kInstruction::getSuccessors(" <<StringUtility::addrToString(insns.front()->get_address()) <<" for " <<insns.size() <<" instruction" <<(1==insns.size()?"":"s") <<"):" <<"\n"; } BinaryAnalysis::Disassembler::AddressSet successors = SgAsmInstruction::getSuccessors(insns, complete); // If we couldn't determine all the successors, or a cursory analysis couldn't narrow it down to a single successor then // we'll do a more thorough analysis now. In the case where the cursory analysis returned a complete set containing two // successors, a thorough analysis might be able to narrow it down to a single successor. We should not make special // assumptions about function call instructions -- their only successor is the specified address operand. */ if (!*complete || successors.size()>1) { using namespace Rose::BinaryAnalysis::InstructionSemantics2::PartialSymbolicSemantics; const RegisterDictionary *regdict = RegisterDictionary::dictionary_coldfire_emac(); RiscOperatorsPtr ops = RiscOperators::instance(regdict); ops->set_memory_map(initial_memory); DispatcherM68kPtr dispatcher = DispatcherM68k::instance(ops, 32); try { for (size_t i=0; i<insns.size(); ++i) { dispatcher->processInstruction(insns[i]); if (debug) debug << " state after " <<insns[i]->toString() <<"\n" <<*ops; } SValuePtr ip = SValue::promote(ops->readRegister(dispatcher->REG_PC)); if (ip->is_number()) { successors.clear(); successors.insert(ip->get_number()); *complete = true; /*this is the complete set of successors*/ } } catch(const BaseSemantics::Exception& e) { /* Abandon entire basic block if we hit an instruction that's not implemented. */ debug <<e <<"\n"; } } if (debug) { debug <<" successors:"; BOOST_FOREACH (rose_addr_t va, successors) debug <<" " <<StringUtility::addrToString(va); debug <<(*complete?"":"...") <<"\n"; } return successors; }
/** Return control flow successors. See base class for full documentation. */ BinaryAnalysis::Disassembler::AddressSet SgAsmX86Instruction::getSuccessors(const std::vector<SgAsmInstruction*>& insns, bool *complete, const MemoryMap *initial_memory) { using namespace rose::BinaryAnalysis::InstructionSemantics; Stream debug(mlog[DEBUG]); if (debug) { debug <<"SgAsmX86Instruction::getSuccessors(" <<StringUtility::addrToString(insns.front()->get_address()) <<" for " <<insns.size() <<" instruction" <<(1==insns.size()?"":"s") <<"):" <<"\n"; } BinaryAnalysis::Disassembler::AddressSet successors = SgAsmInstruction::getSuccessors(insns, complete); /* If we couldn't determine all the successors, or a cursory analysis couldn't narrow it down to a single successor then * we'll do a more thorough analysis now. In the case where the cursory analysis returned a complete set containing two * successors, a thorough analysis might be able to narrow it down to a single successor. We should not make special * assumptions about CALL and FARCALL instructions -- their only successor is the specified address operand. */ if (!*complete || successors.size()>1) { #if 0 /* Use the most robust semantic analysis available. Warning: this can be very slow, especially when an SMT solver is * involved! */ # if defined(ROSE_YICES) || defined(ROSE_HAVE_LIBYICES) YicesSolver yices; if (yices.available_linkage() & YicesSolver::LM_LIBRARY) { yices.set_linkage(YicesSolver::LM_LIBRARY); } else { yices.set_linkage(YicesSolver::LM_EXECUTABLE); } SMTSolver *solver = &yices; # else SMTSolver *solver = NULL; # endif if (debug && solver) solver->set_debug(stderr); typedef SymbolicSemantics::Policy<> Policy; typedef SymbolicSemantics::ValueType<32> RegisterType; typedef X86InstructionSemantics<Policy, SymbolicSemantics::ValueType> Semantics; Policy policy(solver); #else typedef PartialSymbolicSemantics::Policy<> Policy; typedef PartialSymbolicSemantics::ValueType<32> RegisterType; typedef X86InstructionSemantics<Policy, PartialSymbolicSemantics::ValueType> Semantics; Policy policy; policy.set_map(initial_memory); #endif try { Semantics semantics(policy); for (size_t i=0; i<insns.size(); i++) { SgAsmX86Instruction* insn = isSgAsmX86Instruction(insns[i]); semantics.processInstruction(insn); if (debug) { debug << " state after " <<unparseInstructionWithAddress(insn) <<"\n" <<policy.get_state(); } } const RegisterType &newip = policy.get_ip(); if (newip.is_known()) { successors.clear(); successors.insert(newip.known_value()); *complete = true; /*this is the complete set of successors*/ } } catch(const Semantics::Exception& e) { /* Abandon entire basic block if we hit an instruction that's not implemented. */ debug <<e <<"\n"; } catch(const Policy::Exception& e) { /* Abandon entire basic block if the semantics policy cannot handle the instruction. */ debug <<e <<"\n"; } } if (debug) { debug <<" successors:"; for (BinaryAnalysis::Disassembler::AddressSet::const_iterator si=successors.begin(); si!=successors.end(); ++si) debug <<" " <<StringUtility::addrToString(*si); debug <<(*complete?"":"...") <<"\n"; } return successors; }