#include "fxos-cli.h" #include #include #include #include #include #include #include #include #include #include using namespace FxOS; using namespace FxOS::Log; int disassembly(Library &library, Target &target, char const *ref, std::vector passes) { Disassembly disasm(target); /* Observe the target only if it has an OS mapped */ std::unique_ptr os; if(target.covers(MemoryRegion::ROM)) os = std::make_unique(target); uint32_t address; int syscall_id; int len = 0; enum { RefNone=0, RefSyscall, RefAddress } reftype = RefNone; /* Parse different flavors of references. %: syscall */ if(sscanf(ref, "%%%x", &syscall_id) == 1) reftype = RefSyscall; /* Pure hexa: address */ else if(sscanf(ref, "%x%n", &address, &len) == 1 && !ref[len]) reftype = RefAddress; /* Anything else: look up symbols */ else { std::string name = ref; for(auto const &symtable: library.sym_tables()) { std::optional sym = symtable.lookup(name); if(!sym) continue; if(sym->type == Symbol::Syscall) reftype = RefSyscall, syscall_id = sym->value; if(sym->type == Symbol::Address) reftype = RefAddress, address = sym->value; break; } } /* Now try to load the address for this reference */ if(reftype == RefSyscall) { if(!os) { log(ERR "cannot disassemble syscall %s: target does " "not have an OS mapped", ref); return 1; } if(syscall_id >= os->syscall_count()) { log(ERR "this OS only has %#x syscalls", os->syscall_count()); return 1; } address = os->syscall(syscall_id); } else if(reftype == RefAddress) { if(address & 1) { log(WRN "address %08x is odd, will start at %08x", address, address+1); address++; } } else { log(ERR "cannot interpret '%s' (not a syscall id, not an " "address, and no such symbol in library)", ref); return 1; } for(auto pass: passes) { auto start = timer_start(); log(LOG "Running pass %s...\\", pass); if(pass == "cfg") { CfgPass p(disasm); p.run(address); } else if(pass == "pcrel") { PcrelPass p(disasm); p.run(); } else if(pass == "syscall") { SyscallPass p(disasm, os.get()); p.run(); } else if(pass == "print") { PrintPass p(disasm, library.sym_tables()); p.promote_pcjump_loc = PrintPass::Promote; p.promote_pcrel_loc = PrintPass::Promote; p.promote_pcrel_value = PrintPass::Promote; p.promote_syscall = PrintPass::Promote; p.promote_syscallname = PrintPass::Append; p.promote_symbol = PrintPass::Append; p.run(); } log(LOG "%s", timer_format(timer_end(start))); } return 0; }