From 54a79ca4b44c7e325b52c1154c924981f83c1003 Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Mon, 17 Feb 2020 22:47:09 +0100 Subject: [PATCH] add support for flexible location specifiers --- fxos/disassembly.cpp | 85 ++++++++++++++++++++++++++++++++++++++++-- fxos/fxos-cli.h | 2 +- fxos/main.cpp | 22 ++++------- include/fxos/symbols.h | 2 + lib/symbols.cpp | 10 +++++ 5 files changed, 102 insertions(+), 19 deletions(-) diff --git a/fxos/disassembly.cpp b/fxos/disassembly.cpp index e3ffdda..5629e91 100644 --- a/fxos/disassembly.cpp +++ b/fxos/disassembly.cpp @@ -14,7 +14,7 @@ using namespace FxOS; using namespace FxOS::Log; -void disassembly(Library &library, Target &target, uint32_t ref, +int disassembly(Library &library, Target &target, char const *ref, std::vector passes) { Disassembly disasm(target); @@ -24,6 +24,81 @@ void disassembly(Library &library, Target &target, uint32_t ref, if(target.covers(MemoryRegion::ROM)) os = std::make_unique(target); + uint32_t address; + int syscall_id; + int len = 0; + + /* Parse different flavors of references. %: syscall */ + if(sscanf(ref, "%%%x", &syscall_id) == 1) + { + 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); + } + /* Pure hexa: address */ + else if(sscanf(ref, "%x%n", &address, &len) == 1 && !ref[len]) + { + } + /* Anything else: look up symbols */ + else + { + bool found = false; + std::string name = ref; + Symbol sym; + + for(auto const &symtable: library.sym_tables()) + { + std::optional s = symtable.lookup(name); + if(!s) continue; + + found = true; + sym = *s; + break; + } + + if(!found) + { + log(ERR "cannot interpret '%s' (not syscall id, not " + "address, and no such symbol in library)",ref); + return 1; + } + + switch(sym.type) + { + case Symbol::Syscall: + 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(sym.value); + break; + + case Symbol::Address: + address = sym.value; + break; + } + } + for(auto pass: passes) { auto start = timer_start(); @@ -32,17 +107,17 @@ void disassembly(Library &library, Target &target, uint32_t ref, if(pass == "cfg") { CfgPass p(disasm); - p.run(ref); + p.run(address); } else if(pass == "pcrel") { PcrelPass p(disasm); - p.run(ref); + p.run(address); } else if(pass == "syscall") { SyscallPass p(disasm, os.get()); - p.run(ref); + p.run(address); } else if(pass == "print") { @@ -59,4 +134,6 @@ void disassembly(Library &library, Target &target, uint32_t ref, } log(LOG "%s", timer_format(timer_end(start))); } + + return 0; } diff --git a/fxos/fxos-cli.h b/fxos/fxos-cli.h index e478280..7ef85fc 100644 --- a/fxos/fxos-cli.h +++ b/fxos/fxos-cli.h @@ -17,7 +17,7 @@ void show_library(FxOS::Library &library, bool targets, bool asmtables); void os_info(FxOS::Target &target); /* Disassemble */ -void disassembly(FxOS::Library &library, FxOS::Target &target, uint32_t ref, +int disassembly(FxOS::Library &library, FxOS::Target &target, char const *ref, std::vector passes); #endif /* FXOS_CLI_H */ diff --git a/fxos/main.cpp b/fxos/main.cpp index 9452d8e..464225f 100644 --- a/fxos/main.cpp +++ b/fxos/main.cpp @@ -68,8 +68,6 @@ Location specifiers: Disassembly options: -p Execute the specified comma-separated list of passes - --load Read additional documentation from - --load Read additional documentation recursively from Available passes: cfg Build the control flow graph (always required) @@ -329,8 +327,7 @@ int main_disassembly(int argc, char **argv) loadconfig(lib); Target target; - char const *refstr; - uint32_t ref; + char const *ref; if(!file.size()) { @@ -344,8 +341,8 @@ int main_disassembly(int argc, char **argv) target = Target(lib.targets().at(tname), lib.paths()); - refstr = argv[optind + 2]; - log(LOG "Disassembling target %s at %s", tname, refstr); + ref = argv[optind + 2]; + log(LOG "Disassembling target %s at %s", tname, ref); } else @@ -356,14 +353,13 @@ int main_disassembly(int argc, char **argv) target.bind_region(MemoryRegion::ROM, romfile); target.bind_region(MemoryRegion::ROM_P2, romfile); - refstr = argv[optind + 1]; - log(LOG "Disassembling file %s at %s", file, refstr); + ref = argv[optind + 1]; + log(LOG "Disassembling file %s at %s", file, ref); } - sscanf(refstr, "%x", &ref); try { - disassembly(lib, target, ref, passes); + return disassembly(lib, target, ref, passes); } catch(LangError &e) { @@ -375,8 +371,6 @@ int main_disassembly(int argc, char **argv) log(ERR "%08x[%d]: %s", e.addr(), e.size(), e.what()); return 1; } - - return 0; } #define UN __attribute__((unused)) @@ -399,8 +393,8 @@ int main(int argc, char **argv) return main_info(argc, argv); else if(cmd == "disasm") return main_disassembly(argc, argv); - else if(cmd == "analyze") - return main_analyze(argc, argv); +// else if(cmd == "analyze") +// return main_analyze(argc, argv); else if(cmd == "-?" || cmd == "-h" || cmd == "--help") usage(0); diff --git a/include/fxos/symbols.h b/include/fxos/symbols.h index 9b3ebf1..d66377a 100644 --- a/include/fxos/symbols.h +++ b/include/fxos/symbols.h @@ -38,6 +38,8 @@ struct SymbolTable /* Query a value for a certain type of symbol */ std::optional query(Symbol::Type type, uint32_t value) const; + /* Lookup the symbol behind a given name */ + std::optional lookup(std::string name) const; }; } /* namespace FxOS */ diff --git a/lib/symbols.cpp b/lib/symbols.cpp index 576b93c..bb44d6f 100644 --- a/lib/symbols.cpp +++ b/lib/symbols.cpp @@ -18,4 +18,14 @@ std::optional SymbolTable::query(Symbol::Type type, return std::nullopt; } +std::optional SymbolTable::lookup(std::string name) const +{ + for(auto &sym: symbols) + { + if(sym.name == name) return sym; + } + + return std::nullopt; +} + } /* namespace FxOS */