//--- // fxos.passes.print: Print disassembly //--- #include #include namespace FxOS { PrintPass::PrintPass(Disassembly &disasm): DisassemblyPass(disasm) { /* Default parameter set */ hide_resolved_pcjump = false; hide_resolved_pcrel = false; hide_movpc_address = Hide_MovPC_Never; } void PrintPass::run(void) { for(auto &pair: m_disasm.instructions()) { analyze(pair.first, pair.second); } } void PrintPass::analyze(uint32_t pc, ConcreteInstruction &ci) { Instruction const &i = ci.inst; /* Mnemonic */ static std::map suffixes = { { 1, ".b" }, { 2, ".w" }, { 4, ".l" } }; std::string mnemonic = i.mnemonic + suffixes[i.opsize]; if(i.args.size()) mnemonic += std::string(8 - mnemonic.size(), ' '); printf(" %08x: %04x %s", pc, ci.inst.opcode, mnemonic.c_str()); /* Arguments */ for(size_t n = 0; n < i.args.size(); n++) { auto &a = i.args[n]; Location &l = ci.args[n].location; std::optional v = ci.args[n].value; if(n) printf(", "); if(a.kind == Argument::PcJump) { if(!l || !hide_resolved_pcjump) printf("%s", a.str().c_str()); if(l) printf("<%s>", l.str().c_str()); } else if(a.kind == Argument::PcRel) { pcrel(pc, a, l, v); } else { printf("%s", a.str().c_str()); } } printf("\n"); } void PrintPass::pcrel(uint32_t pc, Argument const &a, Location const &l, std::optional v) { if(!l || !hide_resolved_pcrel) { printf("%s", a.str().c_str()); } if(!l || !RelConstDomain().is_constant(l)) return; auto reg_code = MemoryRegion::region_for(pc); auto reg_data = MemoryRegion::region_for(l.uval); bool hma = hide_movpc_address; bool same_region = (reg_code && reg_code == reg_data); if(!v || hma == Hide_MovPC_Never || (hma == Hide_MovPC_Region && !same_region)) { printf("<%s>", l.str().c_str()); if(v) printf("(%s)", v->str().c_str()); } else if(v) { printf("%s", v->str().c_str()); } } } /* namespace FxOS */