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(); }
static void listInstructions(const InstructionProvider::Ptr &insns, const MemoryMap &map, const FunctionByAddress &code1, FunctionByAddress &code2) { std::ostream &out = std::cout; static const size_t insnWidth = 110; rose_addr_t va1 = code1.hull().least(); rose_addr_t va2 = code2.hull().least(); rose_addr_t va = std::min(va1, va2); rose_addr_t expectedVa = va; AsmUnparser unparser; while (va<=code1.hull().greatest() || va<=code2.hull().greatest()) { // Address and contents if (va != expectedVa) out <<"\n"; // visual cue that addresses are not sequential here std::ostringstream ss; size_t size; if (!map.at(va).require(MemoryMap::EXECUTABLE).exists()) { ss <<StringUtility::addrToString(va) <<": " <<(map.at(va).exists() ? "not executable" : "not mapped"); size = 1; } else if (SgAsmInstruction *insn = (*insns)[va]) { unparser.unparse(ss, insn); size = insn->get_size(); } else { ss <<StringUtility::addrToString(va) <<": bad instruction"; size = 1; } std::vector<std::string> lines = StringUtility::split('\n', ss.str()); while (lines.size()>0 && lines[lines.size()-1]=="") lines.pop_back(); for (size_t i=0; i<lines.size(); ++i) { if (i+1 < lines.size()) { out <<lines[i] <<"\n"; } else { out <<std::setw(insnWidth) <<std::left <<lines[i]; } } // Functions owning Sawyer::Optional<rose_addr_t> f1 = code1.getOptional(va); Sawyer::Optional<rose_addr_t> f2 = code2.getOptional(va); out <<"\t" <<std::setw(10) <<std::left <<(f1 ? StringUtility::addrToString(*f1) : std::string("none")); out <<"\t" <<std::setw(10) <<std::left <<(f2 ? StringUtility::addrToString(*f2) : std::string("none")); out <<" " <<(f1.isEqual(f2) ? "" : "<---") <<"\n"; // Advance address pointer rose_addr_t next = va + size; expectedVa = next; FunctionByAddress::ConstIntervalIterator i1 = code1.upperBound(va); if (i1!=code1.nodes().end() && i1->least() < next) next = i1->least(); FunctionByAddress::ConstIntervalIterator i2 = code2.upperBound(va); if (i2!=code2.nodes().end() && i2->least() < next) next = i2->least(); if (!map.atOrAfter(next).next().assignTo(va)) break; } }
int main(int argc, char *argv[]) { Diagnostics::initialize(); BinaryAnalysis::Partitioner2::Engine engine; Settings settings; std::vector<std::string> specimenNames = parseCommandLine(argc, argv, engine, settings /*in,out*/); BinaryAnalysis::MagicNumber analyzer; analyzer.maxBytesToCheck(settings.maxBytes); MemoryMap map = engine.loadSpecimens(specimenNames); map.dump(mlog[INFO]); size_t step = std::max(size_t(1), settings.step); AddressInterval limits = settings.limits.isEmpty() ? map.hull() : (settings.limits & map.hull()); Sawyer::Container::IntervalSet<AddressInterval> addresses(map); addresses.intersect(limits); size_t nPositions = addresses.size() / step; mlog[INFO] <<"approximately " <<StringUtility::plural(nPositions, "positions") <<" to check\n"; { Sawyer::ProgressBar<size_t> progress(nPositions, mlog[INFO], "positions"); for (rose_addr_t va=limits.least(); va<=limits.greatest() && map.atOrAfter(va).next().assignTo(va); va+=step, ++progress) { std::string magicString = analyzer.identify(map, va); if (magicString!="data") { // runs home to Momma when it gets confused uint8_t buf[8]; size_t nBytes = map.at(va).limit(sizeof buf).read(buf).size(); std::cout <<StringUtility::addrToString(va) <<" |" <<leadingBytes(buf, nBytes) <<" | " <<magicString <<"\n"; } if (va==limits.greatest()) break; // prevent overflow at top of address space } } }
// class method size_t SRecord::dump(const MemoryMap &map, std::ostream &out, size_t addrSize) { ASSERT_require(2==addrSize || 3==addrSize || 4==addrSize); SRecord::Type type = SREC_NONE; switch (addrSize) { case 2: type = SREC_DATA16; break; case 3: type = SREC_DATA24; break; case 4: type = SREC_DATA32; break; } size_t nRecords = 0; rose_addr_t va = 0; static const size_t maxBytesPerRecord = 28; // common value so each S-Record fits on an 80-character screen uint8_t buffer[maxBytesPerRecord]; while (map.atOrAfter(va).next().assignTo(va)) { size_t nread = map.at(va).limit(maxBytesPerRecord).read(buffer).size(); ASSERT_require(nread>0); // since map.next() returned true SRecord srec(type, va, buffer, nread); out <<srec <<"\n"; va += nread; ++nRecords; } return nRecords; }