int main(int argc, char *argv[]) { Diagnostics::initialize(); ::mlog = Diagnostics::Facility("tool", Diagnostics::destination); Diagnostics::mfacilities.insertAndAdjust(::mlog); // Parse the command-line Partitioner2::Engine engine; std::vector<std::string> specimenNames = parseCommandLine(argc, argv, engine); if (specimenNames.empty()) throw std::runtime_error("no specimen specified; see --help"); // Load specimen into memory MemoryMap map = engine.loadSpecimens(specimenNames); // Configure instruction semantics Partitioner2::Partitioner partitioner = engine.createPartitioner(); Disassembler *disassembler = engine.obtainDisassembler(); const RegisterDictionary *regdict = disassembler->get_registers(); if (disassembler->dispatcher() == NULL) throw std::runtime_error("no instruction semantics for this architecture"); BaseSemantics::RiscOperatorsPtr ops = InstructionSemantics2::ConcreteSemantics::RiscOperators::instance(regdict); BaseSemantics::DispatcherPtr cpu = disassembler->dispatcher()->create(ops); ConcreteSemantics::MemoryState::promote(ops->currentState()->memoryState())->memoryMap(map); // Find starting address rose_addr_t va = 0; if (settings.startVa) { va = *settings.startVa; } else if (engine.isaName() == "coldfire") { // Use the interrupt vector to initialize the stack pointer and instruction pointer. uint32_t sp, ip; if (4 != map.at(0).limit(4).read((uint8_t*)&sp).size()) throw std::runtime_error("cannot read stack pointer at address 0x00000000"); ops->writeRegister(disassembler->stackPointerRegister(), ops->number_(32, ByteOrder::be_to_host(sp))); if (4 != map.at(4).limit(4).read((uint8_t*)&ip).size()) throw std::runtime_error("cannot read instruction pointer at address 0x00000004"); va = ByteOrder::be_to_host(ip); } else if (!map.atOrAfter(0).require(MemoryMap::EXECUTABLE).next().assignTo(va)) { throw std::runtime_error("no starting address specified and none marked executable"); } ops->writeRegister(disassembler->instructionPointerRegister(), ops->number_(32, va)); // Execute map.dump(::mlog[INFO]); while (1) { va = ops->readRegister(disassembler->instructionPointerRegister())->get_number(); SgAsmInstruction *insn = partitioner.instructionProvider()[va]; SAWYER_MESG(::mlog[TRACE]) <<unparseInstructionWithAddress(insn, NULL, regdict) <<"\n"; try { cpu->processInstruction(insn); } catch (const BaseSemantics::Exception &e) { ::mlog[WARN] <<e <<"\n"; } } // std::cout <<"Final state:\n"; // std::cout <<*ops->currentState(); }
/* Analyze a single interpretation a block at a time */ static void analyze_interp(SgAsmInterpretation *interp) { /* Get the set of all instructions except instructions that are part of left-over blocks. */ struct AllInstructions: public SgSimpleProcessing, public std::map<rose_addr_t, SgAsmX86Instruction*> { void visit(SgNode *node) { SgAsmX86Instruction *insn = isSgAsmX86Instruction(node); SgAsmFunction *func = SageInterface::getEnclosingNode<SgAsmFunction>(insn); if (func && 0==(func->get_reason() & SgAsmFunction::FUNC_LEFTOVERS)) insert(std::make_pair(insn->get_address(), insn)); } } insns; insns.traverse(interp, postorder); while (!insns.empty()) { std::cout <<"=====================================================================================\n" <<"=== Starting a new basic block ===\n" <<"=====================================================================================\n"; AllInstructions::iterator si = insns.begin(); SgAsmX86Instruction *insn = si->second; insns.erase(si); BaseSemantics::RiscOperatorsPtr operators = make_ops(); BaseSemantics::Formatter formatter; formatter.set_suppress_initial_values(); formatter.set_show_latest_writers(do_usedef); BaseSemantics::DispatcherPtr dispatcher; if (do_trace) { // Enable RiscOperators tracing, but turn off a bunch of info that makes comparisons with a known good answer // difficult. Sawyer::Message::PrefixPtr prefix = Sawyer::Message::Prefix::instance(); prefix->showProgramName(false); prefix->showThreadId(false); prefix->showElapsedTime(false); prefix->showFacilityName(Sawyer::Message::Prefix::NEVER); prefix->showImportance(false); Sawyer::Message::UnformattedSinkPtr sink = Sawyer::Message::StreamSink::instance(std::cout); sink->prefix(prefix); sink->defaultPropertiesNS().useColor = false; TraceSemantics::RiscOperatorsPtr trace = TraceSemantics::RiscOperators::instance(operators); trace->stream().destination(sink); trace->stream().enable(); dispatcher = DispatcherX86::instance(trace, 32); } else { dispatcher = DispatcherX86::instance(operators, 32); } operators->set_solver(make_solver()); // The fpstatus_top register must have a concrete value if we'll use the x86 floating-point stack (e.g., st(0)) if (const RegisterDescriptor *REG_FPSTATUS_TOP = regdict->lookup("fpstatus_top")) { BaseSemantics::SValuePtr st_top = operators->number_(REG_FPSTATUS_TOP->get_nbits(), 0); operators->writeRegister(*REG_FPSTATUS_TOP, st_top); } #if SEMANTIC_DOMAIN == SYMBOLIC_DOMAIN BaseSemantics::SValuePtr orig_esp; if (do_test_subst) { // Only request the orig_esp if we're going to use it later because it causes an esp value to be instantiated // in the state, which is printed in the output, and thus changes the answer. BaseSemantics::RegisterStateGeneric::promote(operators->get_state()->get_register_state())->initialize_large(); orig_esp = operators->readRegister(*regdict->lookup("esp")); std::cout <<"Original state:\n" <<*operators; } #endif /* Perform semantic analysis for each instruction in this block. The block ends when we no longer know the value of * the instruction pointer or the instruction pointer refers to an instruction that doesn't exist or which has already * been processed. */ while (1) { /* Analyze current instruction */ std::cout <<"\n" <<unparseInstructionWithAddress(insn) <<"\n"; try { dispatcher->processInstruction(insn); # if 0 /*DEBUGGING [Robb P. Matzke 2013-05-01]*/ show_state(operators); // for comparing RegisterStateGeneric with the old RegisterStateX86 output # else std::cout <<(*operators + formatter); # endif } catch (const BaseSemantics::Exception &e) { std::cout <<e <<"\n"; } /* Never follow CALL instructions */ if (insn->get_kind()==x86_call || insn->get_kind()==x86_farcall) break; /* Get next instruction of this block */ BaseSemantics::SValuePtr ip = operators->readRegister(dispatcher->findRegister("eip")); if (!ip->is_number()) break; rose_addr_t next_addr = ip->get_number(); si = insns.find(next_addr); if (si==insns.end()) break; insn = si->second; insns.erase(si); } // Test substitution on the symbolic state. #if SEMANTIC_DOMAIN == SYMBOLIC_DOMAIN if (do_test_subst) { SymbolicSemantics::SValuePtr from = SymbolicSemantics::SValue::promote(orig_esp); BaseSemantics::SValuePtr newvar = operators->undefined_(32); newvar->set_comment("frame_pointer"); SymbolicSemantics::SValuePtr to = SymbolicSemantics::SValue::promote(operators->add(newvar, operators->number_(32, 4))); std::cout <<"Substituting from " <<*from <<" to " <<*to <<"\n"; SymbolicSemantics::RiscOperators::promote(operators)->substitute(from, to); std::cout <<"Substituted state:\n" <<(*operators+formatter); } #endif } }
int main(int argc, char *argv[]) { ROSE_INITIALIZE; Diagnostics::initAndRegister(&::mlog, "tool"); parseCommandLine(argc, argv); // Create the machine state const RegisterDictionary *registers = RegisterDictionary::dictionary_amd64(); const RegisterDescriptor EAX = *registers->lookup("eax"); SmtSolverPtr solver; BaseSemantics::RiscOperatorsPtr ops = SymbolicSemantics::RiscOperators::instance(registers, solver); ops->currentState()->memoryState()->set_byteOrder(ByteOrder::ORDER_LSB); // Initialize the machine state with some writes and get the string representation. BaseSemantics::SValuePtr eax = ops->number_(32, 1234); ops->writeRegister(EAX, eax); BaseSemantics::SValuePtr addr0 = ops->number_(32, 0x1000); BaseSemantics::SValuePtr mem0 = ops->number_(8, 123); ops->writeMemory(RegisterDescriptor(), addr0, mem0, ops->boolean_(true)); std::ostringstream s0; s0 <<*ops; // Peek at parts of the state that exist BaseSemantics::SValuePtr v1 = ops->peekRegister(EAX, ops->undefined_(32)); ASSERT_always_not_null(v1); ASSERT_always_require(v1->must_equal(eax, solver)); BaseSemantics::SValuePtr mem1 = ops->peekMemory(RegisterDescriptor(), addr0, ops->undefined_(8)); ASSERT_always_not_null(mem1); ASSERT_always_require(mem1->must_equal(mem0, solver)); std::ostringstream s1; s1 <<*ops; ASSERT_always_require2(s0.str() == s1.str(), s1.str()); // Peek at parts of the state that don't exist const RegisterDescriptor EBX = *registers->lookup("ebx"); BaseSemantics::SValuePtr ebx = ops->undefined_(32); BaseSemantics::SValuePtr v2 = ops->peekRegister(EBX, ebx); ASSERT_always_not_null(v2); ASSERT_always_require(v2->must_equal(ebx, solver)); BaseSemantics::SValuePtr addr2 = ops->number_(32, 0x2000); BaseSemantics::SValuePtr mem2init = ops->undefined_(8); BaseSemantics::SValuePtr mem2 = ops->peekMemory(RegisterDescriptor(), addr2, mem2init); ASSERT_always_not_null(mem2); ASSERT_always_require(mem2->must_equal(mem2init, solver)); std::ostringstream s2; s2 <<*ops; ASSERT_always_require2(s0.str() == s2.str(), s2.str()); // Peek at parts of the state that partly exist. const RegisterDescriptor RAX = *registers->lookup("rax"); BaseSemantics::SValuePtr zero64 = ops->number_(64, 0); BaseSemantics::SValuePtr v3 = ops->peekRegister(RAX, zero64); ASSERT_always_not_null(v3); ASSERT_always_require(v3->must_equal(ops->number_(64, 1234), solver)); BaseSemantics::SValuePtr zero32 = ops->number_(32, 0); BaseSemantics::SValuePtr mem3ans = ops->number_(32, 123); BaseSemantics::SValuePtr mem3 = ops->peekMemory(RegisterDescriptor(), addr0, zero32); ASSERT_always_not_null(mem3); ASSERT_always_require(mem3->must_equal(mem3ans, solver)); std::ostringstream s3; s3 <<*ops; ASSERT_always_require2(s0.str() == s3.str(), s3.str()); std::cout <<s3.str(); }