int main(int argc, char *argv[]) { // Parse command-line int argno=1; for (/*void*/; argno<argc && '-'==argv[argno][0]; ++argno) { if (!strcmp(argv[argno], "--")) { ++argno; break; } else { std::cerr <<argv[0] <<": unrecognized switch: " <<argv[argno] <<"\n"; exit(1); } } if (argno+1!=argc) { std::cerr <<"usage: " <<argv[0] <<" [SWITCHES] [--] SPECIMEN\n"; exit(1); } std::string specimen_name = argv[argno++]; // Open the file rose_addr_t start_va = 0; MemoryMap map; size_t file_size = map.insertFile(specimen_name, start_va); map.at(start_va).limit(file_size).changeAccess(MemoryMap::EXECUTABLE, 0); // Try to disassemble every byte, and print the CALL/FARCALL targets InstructionMap insns; size_t nerrors=0; Disassembler *disassembler = new DisassemblerX86(4); for (rose_addr_t offset=0; offset<file_size; ++offset) { try { rose_addr_t insn_va = start_va + offset; if (SgAsmX86Instruction *insn = isSgAsmX86Instruction(disassembler->disassembleOne(&map, insn_va))) insns[insn_va] = insn; } catch (const Disassembler::Exception &e) { ++nerrors; } } // Partition those instructions into basic blocks and functions Partitioner partitioner; SgAsmBlock *gblock = partitioner.partition(NULL, insns, &map); // Print addresses of functions struct T1: AstSimpleProcessing { void visit(SgNode *node) { if (SgAsmFunction *func = isSgAsmFunction(node)) std::cout <<StringUtility::addrToString(func->get_entry_va()) <<"\n"; } }; T1().traverse(gblock, preorder); std::cerr <<specimen_name <<": " <<insns.size() <<" instructions; " <<nerrors <<" errors\n"; return 0; }
int main(int argc, char *argv[]) { // Parse command-line int argno=1; for (/*void*/; argno<argc && '-'==argv[argno][0]; ++argno) { if (!strcmp(argv[argno], "--")) { ++argno; break; } else { std::cerr <<argv[0] <<": unrecognized switch: " <<argv[argno] <<"\n"; exit(1); } } if (argno+1!=argc) { std::cerr <<"usage: " <<argv[0] <<" [SWITCHES] [--] SPECIMEN\n"; exit(1); } std::string specimen_name = argv[argno++]; // Open the file rose_addr_t start_va = 0; MemoryMap map; size_t file_size = map.insertFile(specimen_name, start_va); map.at(start_va).limit(file_size).changeAccess(MemoryMap::EXECUTABLE, 0); // Try to disassemble every byte, and print the CALL/FARCALL targets size_t ninsns=0, nerrors=0; Disassembler *disassembler = new DisassemblerX86(4); for (rose_addr_t offset=0; offset<file_size; ++offset) { try { rose_addr_t insn_va = start_va + offset; SgAsmX86Instruction *insn = isSgAsmX86Instruction(disassembler->disassembleOne(&map, insn_va)); if (insn && (x86_call==insn->get_kind() || x86_farcall==insn->get_kind())) { ++ninsns; rose_addr_t target_va; if (insn->getBranchTarget(&target_va)) std::cout <<StringUtility::addrToString(insn_va) <<": " <<StringUtility::addrToString(target_va) <<"\n"; } } catch (const Disassembler::Exception &e) { ++nerrors; } } std::cerr <<specimen_name <<": " <<ninsns <<" instructions; " <<nerrors <<" errors\n"; return 0; }
int main(int argc, char *argv[]) { ROSE_INITIALIZE; Diagnostics::initAndRegister(&::mlog, "tool"); // Parse command-line P2::Engine engine; Settings settings; std::vector<std::string> specimen = parseCommandLine(argc, argv, engine, settings); if (specimen.empty()) { ::mlog[FATAL] <<"no specimen supplied on command-line; see --help\n"; exit(1); } // Load specimen into ROSE's simulated memory if (!engine.parseContainers(specimen.front())) { ::mlog[FATAL] <<"cannot parse specimen binary container\n"; exit(1); } Disassembler *disassembler = engine.obtainDisassembler(); if (!disassembler) { ::mlog[FATAL] <<"no disassembler for this architecture\n"; exit(1); } const RegisterDescriptor REG_IP = disassembler->instructionPointerRegister(); ASSERT_require2(REG_IP.is_valid(), "simulation must know what register serves as the instruction pointer"); // Single-step the specimen natively in a debugger and show each instruction. BinaryDebugger debugger(specimen); while (!debugger.isTerminated()) { uint64_t ip = debugger.readRegister(REG_IP).toInteger(); uint8_t buf[16]; // 16 should be large enough for any instruction size_t nBytes = debugger.readMemory(ip, sizeof buf, buf); if (0 == nBytes) { ::mlog[ERROR] <<"cannot read memory at " <<StringUtility::addrToString(ip) <<"\n"; } else if (SgAsmInstruction *insn = disassembler->disassembleOne(buf, ip, nBytes, ip)) { std::cout <<unparseInstructionWithAddress(insn) <<"\n"; } else { ::mlog[ERROR] <<"cannot disassemble instruction at " <<StringUtility::addrToString(ip) <<"\n"; } debugger.singleStep(); } std::cout <<debugger.howTerminated(); }
int main(int argc, char *argv[]) { std::ios_base::sync_with_stdio(true); std::string hostname = "localhost"; short port = 32002; /* Process command-line arguments. ROSE will do most of the work, but we need to look for the --debugger switch. */ for (int argno=1; argno<argc; argno++) { if (!strncmp(argv[argno], "--debugger=", 11)) { char *colon = strchr(argv[argno]+11, ':'); if (colon) { hostname = std::string(argv[argno]+11, colon-(argv[argno]+11)); char *rest; port = strtol(colon+1, &rest, 0); if (rest && *rest) { fprintf(stderr, "invalid argument for --debugger=HOST:PORT switch\n"); exit(1); } } else { hostname = argv[argno]+11; } memmove(argv+argno, argv+argno+1, (argc-(argno+1))*sizeof(*argv)); --argc; break; } } fprintf(stderr, "Parsing and disassembling executable...\n"); SgProject *project = frontend(argc, argv); /* Connect to debugger */ fprintf(stderr, "Connecting to debugger at %s:%d\n", hostname.c_str(), port); Debugger dbg(hostname, port); /* Choose an interpretation */ SgAsmInterpretation *interp = isSgAsmInterpretation(NodeQuery::querySubTree(project, V_SgAsmInterpretation).back()); assert(interp); Disassembler *disassembler = Disassembler::lookup(interp)->clone(); assert(disassembler!=NULL); fprintf(stderr, "Setting break points...\n"); int status __attribute__((unused)) = dbg.setbp(0, 0xffffffff); assert(status>=0); fprintf(stderr, "Starting executable...\n"); uint64_t nprocessed = 0; dbg.cont(); /* Advance to the first breakpoint. */ while (1) { nprocessed++; unsigned char insn_buf[15]; size_t nread = dbg.memory(dbg.rip(), sizeof insn_buf, insn_buf); SgAsmInstruction *insn = NULL; try { insn = disassembler->disassembleOne(insn_buf, dbg.rip(), nread, dbg.rip(), NULL); } catch(const Disassembler::Exception &e) { std::cerr <<"disassembler exception: " <<e <<"\n"; } if (!insn) { dbg.cont(); continue; } /* Trace instructions */ fprintf(stderr, "[%07"PRIu64"] 0x%08"PRIx64": %s\n", nprocessed, insn->get_address(), unparseInstruction(insn).c_str()); /* Single step to cause the instruction to be executed remotely. Then compare our state with the remote state. */ dbg.step(); } exit(1); /*FIXME*/ }