diff --git a/shell/d.cpp b/shell/d.cpp index 79aacb6..cf96982 100644 --- a/shell/d.cpp +++ b/shell/d.cpp @@ -69,72 +69,78 @@ static void disassemble(Session &session, Disassembly &disasm, // d //--- -static uint32_t parse_d(Session &session, Parser &parser) +struct _d_args +{ + std::optional address; + std::optional range; +}; + +static _d_args parse_d(Session &session, Parser &parser) { if(!session.current_space) - return 0; + return {}; + uint32_t address = session.current_space->cursor; - if(!parser.at_end()) - address = parser.expr(session.current_space); + if(!parser.at_end()) { + Token t = parser.lookahead(); + + try { + Range range = parser.range(session.current_space); + parser.end(); + return {{}, range}; + } + catch(...) { + address = parser.expr(session.current_space, t); + } + } parser.end(); - return address; + return {address, {}}; } -void _d(Session &session, uint32_t address) +void _d(Session &session, std::optional address_opt, + std::optional range_opt) { if(!session.current_space) return; FxOS::Disassembly disasm(*session.current_space); - if(address & 1) { - fmt::print("address 0x{:08x} is odd, starting at 0x{:08x}\n", address, - address + 1); - address++; + if(address_opt.has_value()) { + uint32_t address = address_opt.value(); + + if(address & 1) { + fmt::print("address 0x{:08x} is odd, starting at 0x{:08x}\n", + address, address + 1); + address++; + } + + disassemble(session, disasm, + {"cfg", "pcrel", /*"constprop",*/ "syscall", "print"}, address); } + else if(range_opt.has_value()) { + Range range = range_opt.value(); + if(range.start & 1) { + fmt::print("address 0x{:08x} is odd, starting at 0x{:08x}\n", + range.start, range.start + 1); + range.start++; + } + if(range.end & 1) { + fmt::print("address 0x{:08x} is odd, ending at 0x{:08x}\n", + range.end, range.end - 1); + range.end--; + } - disassemble(session, disasm, - {"cfg", "pcrel", /*"constprop",*/ "syscall", "print"}, address); -} + if(range.start >= range.end) + return; -//--- -// dr -//--- + /* Load the block into memory */ + for(uint32_t pc = range.start; pc < range.end; pc += 2) + disasm.getInstructionAt(pc, true); -static Range parse_dr(Session &session, Parser &parser) -{ - Range range = parser.range(session.current_space); - parser.end(); - return range; -} - -void _dr(Session &session, Range range) -{ - if(!session.current_space) - return; - FxOS::Disassembly disasm(*session.current_space); - - if(range.start & 1) { - fmt::print("address 0x{:08x} is odd, starting at 0x{:08x}\n", - range.start, range.start + 1); - range.start++; + disassemble(session, disasm, + {"pcrel", /*"constprop",*/ "syscall", "print"}, -1); } - if(range.end & 1) { - fmt::print("address 0x{:08x} is odd, ending at 0x{:08x}\n", range.end, - range.end - 1); - range.end--; - } - - if(range.start >= range.end) - return; - - /* Load the block into memory */ - for(uint32_t pc = range.start; pc < range.end; pc += 2) - disasm.getInstructionAt(pc, true); - - disassemble( - session, disasm, {"pcrel", /*"constprop",*/ "syscall", "print"}, -1); } //--- @@ -142,9 +148,13 @@ void _dr(Session &session, Range range) //--- static ShellCommand _d_cmd( - "d", [](Session &s, Parser &p) { _d(s, parse_d(s, p)); }, + "d", + [](Session &s, Parser &p) { + auto args = parse_d(s, p); + _d(s, args.address, args.range); + }, [](Session &s, Parser &p) { parse_d(s, p); }, "Disassemble", R"( -d [
] +d [] Disassembles code starting at the specified address, exploring branches until function terminators, invalid instructions, or dynamically-computed jumps. The @@ -159,15 +169,3 @@ The following disassembler passes are run: pcrel Computes PC-relative addresses (eg mov.l, mova, bf, bra...) syscall Annotates uses of syscall table entries with the syscall number )"); - -static ShellCommand _dr_cmd( - "dr", [](Session &s, Parser &p) { _dr(s, parse_dr(s, p)); }, - [](Session &s, Parser &p) { parse_dr(s, p); }, "Disassemble Range", R"( -dr [] - -Disassembles an explicit region of memory. This is similar to d, except that -the disassembled code is pre-loaded from the region instead of being explored -by the cfg pass. See d? for more information. - -Like d, this command does not extend the virtual space's main disassembly. -)"); diff --git a/shell/parser.cpp b/shell/parser.cpp index 1fa09a2..8c81f27 100644 --- a/shell/parser.cpp +++ b/shell/parser.cpp @@ -304,9 +304,14 @@ void Parser::accept_options() // Parsing rules for expressions //--- -long Parser::atom() +long Parser::atom(std::optional token) { - Token t = expect({'$', '(', '-', T::SYMBOL, T::NUM, T::SYSCALL}); + Token t; + + if(token.has_value()) + t = token.value(); + else + t = expect({'$', '(', '-', T::SYMBOL, T::NUM, T::SYSCALL}); if(t.type == T::SYMBOL) { /* TODO: Specify the space that symbols are taken from */ @@ -390,10 +395,10 @@ long Parser::term() return v; } -long Parser::expr(VirtualSpace *space) +long Parser::expr(VirtualSpace *space, std::optional token) { m_expr_space = space; - long val = atom(); + long val = atom(token); m_expr_space = nullptr; return val; } diff --git a/shell/parser.h b/shell/parser.h index 9de9771..92dc0e7 100644 --- a/shell/parser.h +++ b/shell/parser.h @@ -141,7 +141,7 @@ public: /* Read a numerical constant, or an expression. Expression uses the space to access the program counter and query symbol values */ long num(); - long expr(VirtualSpace *space); + long expr(VirtualSpace *space, std::optional token={}); /* Read a range; again $ and symbols are interpreted. If (before) and (after) are both specified, a single value will also be accepted, and the range [value+before, value.after) will be returned. */ @@ -191,7 +191,7 @@ private: /* Parsing rules for expressions */ long term(); long factor(); - long atom(); + long atom(std::optional token={}); /* true if we're completing a partial command, false if we're parsing a finished one */