void TwoBit::after_predict(unsigned long ip, unsigned long nextIP, bool success) { Disassembler disAssem; unsigned int type = disAssem.typeOfInst(ip, pid); branchTargetBuffer[TWO_BIT_getBTBOffset(ip)] = nextIP; if(InstType(type) == CND_JMP) { if(success) { if(state[TWO_BIT_getBTBOffset(ip)] == TT) state[TWO_BIT_getBTBOffset(ip)] = TT; else if(state[TWO_BIT_getBTBOffset(ip)] == T) state[TWO_BIT_getBTBOffset(ip)] = TT; else if(state[TWO_BIT_getBTBOffset(ip)] == N) state[TWO_BIT_getBTBOffset(ip)] = T; else if(state[TWO_BIT_getBTBOffset(ip)] == NN) state[TWO_BIT_getBTBOffset(ip)] = N; } else { if(state[TWO_BIT_getBTBOffset(ip)] == TT) state[TWO_BIT_getBTBOffset(ip)] = T; else if(state[TWO_BIT_getBTBOffset(ip)] == T) state[TWO_BIT_getBTBOffset(ip)] = N; else if(state[TWO_BIT_getBTBOffset(ip)] == N) state[TWO_BIT_getBTBOffset(ip)] = NN; else if(state[TWO_BIT_getBTBOffset(ip)] == NN) state[TWO_BIT_getBTBOffset(ip)] = NN; } } }
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, const char* argv[]) { if (argc != 3) { std::cerr << "Wrong number of parameters. Should be 2." << std::endl; return 0; } Disassembler disassembler; if (disassembler.LoadAssembly(argv[2])) disassembler.Disassemble(std::cout); 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[]) { 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(); }
void armv_end(void* codestart, u32 cycl) { //Normal block end //cycle counter rv //pop registers & return assembler->Subs(w27, w27, cycl); ptrdiff_t offset = reinterpret_cast<uintptr_t>(arm_exit) - assembler->GetBuffer()->GetStartAddress<uintptr_t>(); Label arm_exit_label; assembler->BindToOffset(&arm_exit_label, offset); assembler->B(&arm_exit_label, mi); //statically predicted as not taken offset = reinterpret_cast<uintptr_t>(arm_dispatch) - assembler->GetBuffer()->GetStartAddress<uintptr_t>(); Label arm_dispatch_label; assembler->BindToOffset(&arm_dispatch_label, offset); assembler->B(&arm_dispatch_label); assembler->FinalizeCode(); verify(assembler->GetBuffer()->GetCursorOffset() <= assembler->GetBuffer()->GetCapacity()); vmem_platform_flush_cache( codestart, assembler->GetBuffer()->GetEndAddress<void*>(), codestart, assembler->GetBuffer()->GetEndAddress<void*>()); icPtr += assembler->GetBuffer()->GetSizeInBytes(); #if 0 Instruction* instr_start = (Instruction *)codestart; Instruction* instr_end = assembler->GetBuffer()->GetEndAddress<Instruction*>(); Decoder decoder; Disassembler disasm; decoder.AppendVisitor(&disasm); Instruction* instr; for (instr = instr_start; instr < instr_end; instr += kInstructionSize) { decoder.Decode(instr); printf("arm64 arec\t %p:\t%s\n", reinterpret_cast<void*>(instr), disasm.GetOutput()); } #endif delete assembler; assembler = NULL; }
void TwoBit::do_predict(unsigned long ip, BranchResult& result) { Disassembler disAssem; unsigned int type = disAssem.typeOfInst(ip, pid); if(InstType(type) == CALL || InstType(type) == RETURN || InstType(type) == JMP) { result.setTorF(true); result.setJmpAddress(branchTargetBuffer[TWO_BIT_getBTBOffset(ip)]); } else { if(state[TWO_BIT_getBTBOffset(ip)] == TT || state[TWO_BIT_getBTBOffset(ip)] == T) { result.setTorF(true); result.setJmpAddress(branchTargetBuffer[TWO_BIT_getBTBOffset(ip)]); } else { result.setTorF(false); } } }
static void test_instr(Disassembler &disassembler, const char *inBuf, size_t len, const std::string &expectedOpCode, TestHarness &harness) { std::ostringstream out; std::istringstream in(std::string(inBuf, len)); try { disassembler.disassemble(&in, &out); } catch (...) { harness.assertAlways(expectedOpCode); return; } std::string outString = out.str(); trim_left(outString); trim_right(outString); harness.assertTrue(outString == expectedOpCode, expectedOpCode); }
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*/ }
int main(int argc, char** argv) { try { std::map<std::string, std::string> engines; ObjectFactory<std::string, Engine> engineFactory; ENGINE("groovie", "Groovie", Groovie::GroovieEngine); ENGINE("kyra2", "Legend of Kyrandia: Hand of Fate", Kyra::Kyra2Engine); ENGINE("scummv6", "SCUMM v6", Scumm::v6::Scummv6Engine); po::options_description visible("Options"); visible.add_options() ("help,h", "Produce this help message.") ("engine,e", po::value<std::string>(), "Engine the script originates from.") ("list,l", "List the supported engines.") ("dump-disassembly,d", po::value<std::string>()->implicit_value(""), "Dump the disassembly to a file. Leave out filename to output to stdout.") ("dump-graph,g", po::value<std::string>()->implicit_value(""), "Output the control flow graph in dot format to a file. Leave out filename to output to stdout.") ("only-disassembly,D", "Stops after disassembly. Implies -d.") ("only-graph,G", "Stops after control flow graph has been generated. Implies -g.") ("show-unreachable,u", "Show the address and contents of unreachable groups in the script.") ("variant,v", po::value<std::string>()->default_value(""), "Tell the engine that the script is from a specific variant. To see a list of variants supported by a specific engine, use the -h option and the -e option together.") ("no-stack-effect,s", "Leave out the stack effect when printing raw instructions."); po::options_description args(""); args.add(visible).add_options() ("input-file", po::value<std::string>(), "Input file"); po::positional_options_description fileArg; fileArg.add("input-file", -1); po::variables_map vm; try { // FIXME: If specified as the last parameter before the input file name, -d currently requires a filename to specified. -d must be specified earlier than that if outputting to stdout. po::store(po::command_line_parser(argc, argv).options(args).positional(fileArg).run(), vm); po::notify(vm); } catch (std::exception& e) { std::cout << e.what() << std::endl; } if (vm.count("list")) { std::cout << "Available engines:" << "\n"; std::map<std::string, std::string>::iterator it; for (it = engines.begin(); it != engines.end(); it++) std::cout << (*it).first << " " << (*it).second << "\n"; return 0; } if (vm.count("help") || !vm.count("input-file")) { std::cout << "Usage: " << argv[0] << " [option...] file" << "\n"; std::cout << visible << "\n"; if (vm.count("engine") && engines.find(vm["engine"].as<std::string>()) != engines.end()) { Engine *engine = engineFactory.create(vm["engine"].as<std::string>()); std::vector<std::string> variants; engine->getVariants(variants); if (variants.empty()) { std::cout << engines[vm["engine"].as<std::string>()] << " does not use variants.\n"; } else { std::cout << "Supported variants for " << engines[vm["engine"].as<std::string>()] << ":\n"; for (std::vector<std::string>::iterator i = variants.begin(); i != variants.end(); ++i) { std::cout << " " << *i << "\n"; } } delete engine; std::cout << "\n"; } std::cout << "Note: If outputting to stdout, -d or -g must NOT be specified immediately before the input file.\n"; return 1; } if (!vm.count("engine")) { std::cout << "Engine must be specified.\n"; return 2; } else if (engines.find(vm["engine"].as<std::string>()) == engines.end()) { std::cout << "Unknown engine.\n"; return 2; } if (vm.count("no-stack-effect")) { setOutputStackEffect(false); } Engine *engine = engineFactory.create(vm["engine"].as<std::string>()); engine->_variant = vm["variant"].as<std::string>(); std::string inputFile = vm["input-file"].as<std::string>(); // Disassembly InstVec insts; Disassembler *disassembler = engine->getDisassembler(insts); disassembler->open(inputFile.c_str()); disassembler->disassemble(); if (vm.count("dump-disassembly")) { std::streambuf *buf; std::ofstream of; if (vm["dump-disassembly"].as<std::string>() != "") { of.open(vm["dump-disassembly"].as<std::string>().c_str()); buf = of.rdbuf(); } else { buf = std::cout.rdbuf(); } std::ostream out(buf); disassembler->dumpDisassembly(out); } if (!engine->supportsCodeFlow() || vm.count("only-disassembly") || insts.empty()) { if (!vm.count("dump-disassembly")) { disassembler->dumpDisassembly(std::cout); } delete disassembler; delete engine; return 0; } delete disassembler; // Control flow analysis ControlFlow *cf = new ControlFlow(insts, engine); cf->createGroups(); Graph g = cf->analyze(); if (vm.count("dump-graph")) { std::streambuf *buf; std::ofstream of; if (vm["dump-graph"].as<std::string>() != "") { of.open(vm["dump-graph"].as<std::string>().c_str()); buf = of.rdbuf(); } else { buf = std::cout.rdbuf(); } std::ostream out(buf); boost::write_graphviz(out, g, boost::make_label_writer(get(boost::vertex_name, g)), boost::makeArrowheadWriter(get(boost::edge_attribute, g)), GraphProperties(engine, g)); } if (!engine->supportsCodeGen() || vm.count("only-graph")) { if (!vm.count("dump-graph")) { boost::write_graphviz(std::cout, g, boost::make_label_writer(get(boost::vertex_name, g)), boost::makeArrowheadWriter(get(boost::edge_attribute, g)), GraphProperties(engine, g)); } delete cf; delete engine; return 0; } // Post-processing of CFG engine->postCFG(insts, g); // Code generation CodeGenerator *cg = engine->getCodeGenerator(std::cout); cg->generate(g); if (vm.count("show-unreachable")) { std::vector<GroupPtr> unreachable; VertexRange vr = boost::vertices(g); for (VertexIterator v = vr.first; v != vr.second; ++v) { GroupPtr gr = boost::get(boost::vertex_name, g, *v); if (gr->_stackLevel == -1) unreachable.push_back(gr); } if (!unreachable.empty()) { for (size_t i = 0; i < unreachable.size(); i++) { if (i == 0) { if (unreachable.size() == 1) std::cout << boost::format("\n%d unreachable group detected.\n") % unreachable.size(); else std::cout << boost::format("\n%d unreachable groups detected.\n") % unreachable.size(); } std::cout << "Group " << (i + 1) << ":\n"; ConstInstIterator inst = unreachable[i]->_start; do { std::cout << *inst; } while (inst++ != unreachable[i]->_end); std::cout << "----------\n"; } } } // Free memory delete cf; delete cg; delete engine; } catch (UnknownOpcodeException &e) { std::cerr << "ERROR: " << e.what() << "\n"; return 3; } catch (std::exception &e) { std::cerr << "ERROR: " << e.what() << "\n"; return 4; } return 0; }
Error ClangExpressionParser::DisassembleFunction (Stream &stream, ExecutionContext &exe_ctx, RecordingMemoryManager *jit_memory_manager) { lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); const char *name = m_expr.FunctionName(); Error ret; ret.Clear(); lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS; lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS; std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end(); for (pos = m_jitted_functions.begin(); pos < end; pos++) { if (strstr(pos->m_name.c_str(), name)) { func_local_addr = pos->m_local_addr; func_remote_addr = pos->m_remote_addr; } } if (func_local_addr == LLDB_INVALID_ADDRESS) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", name); return ret; } if(log) log->Printf("Found function, has local address 0x%llx and remote address 0x%llx", (uint64_t)func_local_addr, (uint64_t)func_remote_addr); std::pair <lldb::addr_t, lldb::addr_t> func_range; func_range = jit_memory_manager->GetRemoteRangeForLocal(func_local_addr); if (func_range.first == 0 && func_range.second == 0) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't find code range for function %s", name); return ret; } if(log) log->Printf("Function's code range is [0x%llx-0x%llx]", func_range.first, func_range.second); if (!exe_ctx.target) { ret.SetErrorToGenericError(); ret.SetErrorString("Couldn't find the target"); } lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second - func_remote_addr, 0)); Error err; exe_ctx.process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err); if (!err.Success()) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error")); return ret; } ArchSpec arch(exe_ctx.target->GetArchitecture()); Disassembler *disassembler = Disassembler::FindPlugin(arch); if (disassembler == NULL) { ret.SetErrorToGenericError(); ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName()); return ret; } if (!exe_ctx.process) { ret.SetErrorToGenericError(); ret.SetErrorString("Couldn't find the process"); return ret; } DataExtractor extractor(buffer_sp, exe_ctx.process->GetByteOrder(), exe_ctx.target->GetArchitecture().GetAddressByteSize()); if (log) { log->Printf("Function data has contents:"); extractor.PutToLog (log.get(), 0, extractor.GetByteSize(), func_remote_addr, 16, DataExtractor::TypeUInt8); } disassembler->DecodeInstructions (Address (NULL, func_remote_addr), extractor, 0, UINT32_MAX); InstructionList &instruction_list = disassembler->GetInstructionList(); uint32_t bytes_offset = 0; for (uint32_t instruction_index = 0, num_instructions = instruction_list.GetSize(); instruction_index < num_instructions; ++instruction_index) { Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index).get(); instruction->Dump (&stream, true, &extractor, bytes_offset, &exe_ctx, true); stream.PutChar('\n'); bytes_offset += instruction->GetByteSize(); } return ret; }
int main (int argc, char *argv[]) { unsigned long ip; Disassembler* disAssem = new Disassembler; InfoRegs infoRegs; struct timeval startTime; struct timeval endTime; int opt; unsigned long numOfLimitInst = 0; unsigned long numOfBranchInst = 0; bool limitInst = false; char** temp = NULL; bool debugOn = false; bool rawOn = false; bool loadOn = false; /* ** This program is started with the PID of the target process. */ while((opt = getopt(argc, argv, ":i:drl:")) != -1) { switch(opt) { case 'i': numOfLimitInst = strtoul(optarg, temp, 0); limitInst = true; break; case 'd': debugOn = true; break; case 'r': rawOn = true; break; case 'l': loadOn = true; workLoadParsing(argv[optind - 1]); for(int k = 0; ; k++) { if(workLoad[k] == NULL) break; else printf("%s\n", workLoad[k]); } break; } } try { if(!loadOn) throw 1; } catch (int ex) { errExit("Not WorkLoad"); } struct sigaction act; act.sa_handler = int_handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGINT, &act, NULL); // select profiled program Tracer tracer(workLoad[0], &workLoad[0]); try { tracer.traceStart(); } catch(int exept) { errExit("trace start"); } // set Simulator Simul bSim(tracer.getChildPid(), disAssem, &workLoad[0]); pbSim = &bSim; // set predictor bSim.setPredictor(new NotTaken()); bSim.setPredictor(new TwoBit()); bSim.setPredictor(new Correlate()); bSim.setPredictor(new GShare()); bSim.setPredictor(new GShareRet()); gettimeofday(&startTime, NULL); /* ** Loop now, tracing the child */ while (1) { /* ** Ok, now we will continue the child, but set the single step bit in ** the psw. This will cause the child to exeute just one instruction and ** trap us again. The wait(2) catches the trap. */ try { tracer.traceSingleStep(infoRegs); ip = infoRegs.getRIP(); } catch(int except) { if(errno == ESRCH) { cout << "Target Process is terminated...." << endl; break; } errMsg("Single step"); break; } try { bSim.runSimulation(ip); } catch(int execpt) { errMsg("runSimulation\n"); } if(debugOn) { try { disAssem->showInst(ip, tracer.getChildPid()); } catch(int ex) { errMsg("showInst"); } } if(limitInst) { if(disAssem->typeOfInst(ip, tracer.getChildPid())) { numOfBranchInst++; if(numOfBranchInst >= numOfLimitInst) break; } } } gettimeofday(&endTime, NULL); long endSec = (long)endTime.tv_sec * 1000000 + endTime.tv_usec; long startSec = (long)startTime.tv_sec * 1000000 + startTime.tv_usec; bSim.setTime(endSec - startSec); bSim.printResult(rawOn); return 0; }
bool Disassembler::Disassemble ( Debugger &debugger, const ArchSpec &arch, const ExecutionContext &exe_ctx, const AddressRange &disasm_range, uint32_t num_mixed_context_lines, bool show_bytes, Stream &strm ) { if (disasm_range.GetByteSize()) { Disassembler *disassembler = Disassembler::FindPlugin(arch); if (disassembler) { AddressRange range(disasm_range); Process *process = exe_ctx.process; // If we weren't passed in a section offset address range, // try and resolve it to something if (range.GetBaseAddress().IsSectionOffset() == false) { if (process && process->IsAlive()) { process->ResolveLoadAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress()); } else if (exe_ctx.target) { exe_ctx.target->GetImages().ResolveFileAddress (range.GetBaseAddress().GetOffset(), range.GetBaseAddress()); } } DataExtractor data; size_t bytes_disassembled = disassembler->ParseInstructions (&exe_ctx, range, data); if (bytes_disassembled == 0) { return false; } else { // We got some things disassembled... size_t num_instructions = disassembler->GetInstructionList().GetSize(); uint32_t offset = 0; SymbolContext sc; SymbolContext prev_sc; AddressRange sc_range; if (num_mixed_context_lines) strm.IndentMore (); Address addr(range.GetBaseAddress()); // We extract the section to make sure we don't transition out // of the current section when disassembling const Section *addr_section = addr.GetSection(); Module *range_module = range.GetBaseAddress().GetModule(); for (size_t i=0; i<num_instructions; ++i) { Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i); if (inst) { addr_t file_addr = addr.GetFileAddress(); if (addr_section == NULL || addr_section->ContainsFileAddress (file_addr) == false) { if (range_module) range_module->ResolveFileAddress (file_addr, addr); else if (exe_ctx.target) exe_ctx.target->GetImages().ResolveFileAddress (file_addr, addr); addr_section = addr.GetSection(); } prev_sc = sc; if (addr_section) { Module *module = addr_section->GetModule(); uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); if (resolved_mask) { if (prev_sc.function != sc.function || prev_sc.symbol != sc.symbol) { if (prev_sc.function || prev_sc.symbol) strm.EOL(); strm << sc.module_sp->GetFileSpec().GetFilename(); if (sc.function) strm << '`' << sc.function->GetMangled().GetName(); else if (sc.symbol) strm << '`' << sc.symbol->GetMangled().GetName(); strm << ":\n"; } if (num_mixed_context_lines && !sc_range.ContainsFileAddress (addr)) { sc.GetAddressRange (eSymbolContextEverything, sc_range); if (sc != prev_sc) { if (offset != 0) strm.EOL(); sc.DumpStopContext(&strm, process, addr); if (sc.comp_unit && sc.line_entry.IsValid()) { debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file, sc.line_entry.line, num_mixed_context_lines, num_mixed_context_lines, num_mixed_context_lines ? "->" : "", &strm); } } } } else { sc.Clear(); } } if (num_mixed_context_lines) strm.IndentMore (); strm.Indent(); size_t inst_byte_size = inst->GetByteSize(); inst->Dump(&strm, &addr, show_bytes ? &data : NULL, offset, exe_ctx, show_bytes); strm.EOL(); offset += inst_byte_size; addr.SetOffset (addr.GetOffset() + inst_byte_size); if (num_mixed_context_lines) strm.IndentLess (); } else { break; } } if (num_mixed_context_lines) strm.IndentLess (); } } return true; } return false; }
int main(int argc, char** argv) { if (argc != 2 ) { fprintf(stderr, "Invalid input to [MIPSsim]\n"); printf("Usage: MIPSsim [input file name]\n"); return 1; } // FILE *fp = fopen(INPUTFILE, "r"); FILE *fp =fopen(argv[1], "r"); if(!fp){ fprintf(stderr, "Can't open input file"); return 1; } FILE *out_dis = fopen(OUTPUT_DIS, "w"); char line[INSTRUCTION_LENGTH + 1]; bool is_instruction = true; int address = INITIAL_COM_ADDR; char out[100]; Disassembler disassembler; map<MEMORY,int> inital_mem; MEMORY data_addr_start = -1; MEMORY data_addr_end; while(fscanf(fp,"%s\n",&line) != -1){ assert(strlen(line) == INSTRUCTION_LENGTH); if(is_instruction){ char head[3] = {line[0],line[1]}; if(strcmp(head, "01") == 0){ disassembler.disassemble(1, address, line, out); fprintf(out_dis, "%s\n",out); //printf("%s\n", out); if(strcmp(line, BREAK_CODE) == 0) is_instruction = false; } else if (strcmp(head, "11") == 0) { disassembler.disassemble(2, address, line, out); //printf("%s\n", out); fprintf(out_dis, "%s\n",out); } } else { //printf("%s\t%d\t%d\n",line,address,disassembler.ImmediateTransform(line,INSTRUCTION_LENGTH)); int num = disassembler.SignedImmediateTransform(line,INSTRUCTION_LENGTH); fprintf(out_dis,"%s\t%d\t%d\n",line,address, num); inital_mem[address] = num; if (data_addr_start == -1) { data_addr_start = address; } } address += 4; } data_addr_end = address - 4; // for (map<MEMORY, char*>::iterator it = disassembler.result.begin(); it != disassembler.result.end(); it++) { // printf("%d:%s\n", it->first, it->second); // } fclose(fp); fclose(out_dis); //simulation Console console(INITIAL_COM_ADDR, data_addr_start/4,data_addr_end/4, OUTPUT_SIM); map<MEMORY, int>::iterator it; for (it = inital_mem.begin(); it != inital_mem.end(); it++) { console.memory_set(it->first/4, it->second); } while (console.PC != FLAG_COM_ADDR) { console.execute(disassembler.result[console.PC]); // printf("%d\n", console.PC); } }
virtual bool PostInit() override { auto func_base = (uintptr_t)this->GetFuncAddr(); auto l_is_call_to_addr = [](const auto& insn, void *addr){ if (insn.ID() != X86_INS_CALL) return false; auto operands = insn.Operands(); if (operands.size() != 1) return false; auto op0 = operands[0]; if (op0.Type() != X86_OP_IMM || op0.Imm_U32() != (uintptr_t)addr) return false; return true; }; auto l_is_push_imm32_arg = [](const auto& insn, uint32_t esp_off, uint32_t imm_val){ if (insn.ID() != X86_INS_MOV) return false; auto operands = insn.Operands(); if (operands.size() != 2) return false; auto op0 = operands[0]; if (op0.Type() != X86_OP_MEM || op0.Size() != 4 || op0.Mem_Seg() != X86_REG_INVALID || op0.Mem_Base() != X86_REG_ESP || op0.Mem_Index() != X86_REG_INVALID || op0.Mem_Disp() != esp_off) return false; auto op1 = operands[1]; if (op1.Type() != X86_OP_IMM || op1.Size() != 4 || op1.Imm_U32() != imm_val) return false; return true; }; auto l_is_test_al = [](const auto& insn){ if (insn.ID() != X86_INS_TEST) return false; auto operands = insn.Operands(); if (operands.size() != 2) return false; auto op0 = operands[0]; if (op0.Type() != X86_OP_REG || op0.Reg() != X86_REG_AL) return false; auto op1 = operands[1]; if (op1.Type() != X86_OP_REG || op1.Reg() != X86_REG_AL) return false; return true; }; auto l_is_jcc_imm = [](const auto& insn){ switch (insn.ID()) { case X86_INS_JAE: case X86_INS_JA: case X86_INS_JBE: case X86_INS_JB: case X86_INS_JE: case X86_INS_JGE: case X86_INS_JG: case X86_INS_JLE: case X86_INS_JL: case X86_INS_JNE: case X86_INS_JNO: case X86_INS_JNP: case X86_INS_JNS: case X86_INS_JO: case X86_INS_JP: case X86_INS_JS: break; default: return false; } auto operands = insn.Operands(); if (operands.size() != 1) return false; auto op0 = operands[0]; if (op0.Type() != X86_OP_IMM) return false; return true; }; void *call_target = AddrManager::GetAddr("CTFPlayer::IsPlayerClass"); if (call_target == nullptr) return false; Disassembler<true> disasm; auto result = disasm.Disassemble(func_base, s_DisasmLimit); auto it_arg4 = result.end(); auto it_call = result.end(); auto it_test = result.end(); auto it_jcc = result.end(); for (auto i = result.begin(); i != result.end(); ++i) { // auto insn = *i; // uintptr_t off = insn.Addr() - func_base; // if (off >= 0x5e2 && off < 0x600) { // DevMsg("\n+0x%03x: %s %s\n", off, insn.MnemonicStr(), insn.OperandStr()); // // DevMsg("Bytes:"); // for (auto byte : insn.Bytes()) { // DevMsg(" %02X", byte); // } // DevMsg("\n"); // } /* find the call to CTFPlayer::IsPlayerClass */ if (l_is_call_to_addr(*i, call_target)) { it_call = i; DevMsg("Found call @ +0x%03x\n", (*it_call).Addr() - func_base); for (auto j = i - 1; j >= i - 4 && j != result.begin(); --j) { if (it_arg4 == result.end() && l_is_push_imm32_arg(*j, 0x4, TF_CLASS_ENGINEER)) { it_arg4 = j; DevMsg("Found arg4 @ +0x%03x\n", (*it_arg4).Addr() - func_base); } } for (auto j = i + 1; j <= i + 1 && j != result.end(); ++j) { if (it_test == result.end() && l_is_test_al(*j)) { it_test = j; DevMsg("Found test @ +0x%03x\n", (*it_test).Addr() - func_base); } } for (auto j = i + 2; j <= i + 2 && j != result.end(); ++j) { if (it_jcc == result.end() && l_is_jcc_imm(*j)) { it_jcc = j; DevMsg("Found jcc @ +0x%03x\n", (*it_jcc).Addr() - func_base); } } } } #if 0 bool result = disasm.IterateRange(this->GetFuncAddr(), s_DisasmLimit, [=](const InstructionDetailed& insn){ uint32_t off = insn.Addr() - (uintptr_t)this->GetFuncAddr(); if (off >= 0x5e2 && off < 0x600) { DevMsg("\n+0x%03x: %s %s\n", off, insn.MnemonicStr(), insn.OperandStr()); DevMsg("Bytes:"); for (auto byte : insn.Bytes()) { DevMsg(" %02X", byte); } DevMsg("\n"); } /* DevMsg("Insn @ %s+0x%03x: mnemonic '%s' opcode '%s'\n", this->GetFuncName(), (insn.Addr() - (uintptr_t)this->GetFuncAddr()), insn.MnemonicStr(), insn.OperandStr()); if (insn.ID() != X86_INS_CALL) return true; DevMsg("Call @ %s+0x%03x: mnemonic '%s' opcode '%s'\n", this->GetFuncName(), (insn.Addr() - (uintptr_t)this->GetFuncAddr()), insn.MnemonicStr(), insn.OperandStr()); DevMsg("Bytes:"); for (auto byte : insn.Bytes()) { DevMsg(" %02X", byte); } DevMsg("\n");*/ return true; // TODO: return false if we find what we're looking for // also set m_bFound // also set m_FuncOff // also set up m_Buf and m_Mask }); DevMsg("PostInit: result is %d, error is '%s'\n", result, disasm.ErrorString()); #endif // TODO: return false upon failure return true; }
void ThreadPlanAssemblyTracer::Log() { Stream *stream = GetLogStream(); if (!stream) return; RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); lldb::addr_t pc = reg_ctx->GetPC(); ProcessSP process_sp(m_thread.GetProcess()); Address pc_addr; bool addr_valid = false; uint8_t buffer[16] = {0}; // Must be big enough for any single instruction addr_valid = process_sp->GetTarget().GetSectionLoadList().ResolveLoadAddress( pc, pc_addr); pc_addr.Dump(stream, &m_thread, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress); stream->PutCString(" "); Disassembler *disassembler = GetDisassembler(); if (disassembler) { Status err; process_sp->ReadMemory(pc, buffer, sizeof(buffer), err); if (err.Success()) { DataExtractor extractor(buffer, sizeof(buffer), process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); bool data_from_file = false; if (addr_valid) disassembler->DecodeInstructions(pc_addr, extractor, 0, 1, false, data_from_file); else disassembler->DecodeInstructions(Address(pc), extractor, 0, 1, false, data_from_file); InstructionList &instruction_list = disassembler->GetInstructionList(); const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize(); if (instruction_list.GetSize()) { const bool show_bytes = true; const bool show_address = true; Instruction *instruction = instruction_list.GetInstructionAtIndex(0).get(); const FormatEntity::Entry *disassemble_format = m_thread.GetProcess() ->GetTarget() .GetDebugger() .GetDisassemblyFormat(); instruction->Dump(stream, max_opcode_byte_size, show_address, show_bytes, nullptr, nullptr, nullptr, disassemble_format, 0); } } } const ABI *abi = process_sp->GetABI().get(); TypeFromUser intptr_type = GetIntPointerType(); if (abi && intptr_type.IsValid()) { ValueList value_list; const int num_args = 1; for (int arg_index = 0; arg_index < num_args; ++arg_index) { Value value; value.SetValueType(Value::eValueTypeScalar); // value.SetContext (Value::eContextTypeClangType, // intptr_type.GetOpaqueQualType()); value.SetCompilerType(intptr_type); value_list.PushValue(value); } if (abi->GetArgumentValues(m_thread, value_list)) { for (int arg_index = 0; arg_index < num_args; ++arg_index) { stream->Printf( "\n\targ[%d]=%llx", arg_index, value_list.GetValueAtIndex(arg_index)->GetScalar().ULongLong()); if (arg_index + 1 < num_args) stream->PutCString(", "); } } } RegisterValue reg_value; for (uint32_t reg_num = 0, num_registers = reg_ctx->GetRegisterCount(); reg_num < num_registers; ++reg_num) { const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex(reg_num); if (reg_ctx->ReadRegister(reg_info, reg_value)) { assert(reg_num < m_register_values.size()); if (m_register_values[reg_num].GetType() == RegisterValue::eTypeInvalid || reg_value != m_register_values[reg_num]) { if (reg_value.GetType() != RegisterValue::eTypeInvalid) { stream->PutCString("\n\t"); reg_value.Dump(stream, reg_info, true, false, eFormatDefault); } } m_register_values[reg_num] = reg_value; } } stream->EOL(); stream->Flush(); }
ISADisassembler::ISADisassembler(Disassembler& _disassembler, cxuint outBufSize) : disassembler(_disassembler), startOffset(0), labelStartOffset(0), dontPrintLabelsAfterCode(false), output(outBufSize, _disassembler.getOutput()) { }