From 12e6cd45a47e3a90d96619a435948255bfb4d489 Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Sun, 20 Aug 2023 18:52:34 +0200 Subject: [PATCH] _am: add search for OS main menu function --- shell/a.cpp | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) diff --git a/shell/a.cpp b/shell/a.cpp index aa14315..404479e 100644 --- a/shell/a.cpp +++ b/shell/a.cpp @@ -142,6 +142,103 @@ void _ads(Session &session) ad_disassemble_all(space, addresses, true); } +//--- +// am +//--- + +static void _am_cg_main_menu_function(VirtualSpace &vspace) +{ + OS *os = vspace.os_analysis(); + if(!os) { + FxOS_log(ERR, "no OS analysis"); + return; + } + + if(os->syscall_count() < 0x1e58) { + FxOS_log(ERR, "less than 0x1e58 syscalls"); + return; + } + + uint32_t sc_addr = os->syscall(0x1e58); + fmt::print("syscall %%1e58 found at 0x{:08x}\n", sc_addr); + + /* Check up to 150 instructions to find the call to the internal function + SaveAndOpenMainMenu(). This call is in a widget of the shape + + mov.l GetkeyToMainFunctionReturnFlag, rX + mov #3, rY + bsr SaveAndOpenMainMenu + mov.b rY, @rX + bra + nop */ + for(int i = 0; i < 150; i++) { + uint16_t i0 = vspace.read_u16(sc_addr + 2 * (i + 0)); + uint16_t i1 = vspace.read_u16(sc_addr + 2 * (i + 1)); + uint16_t i2 = vspace.read_u16(sc_addr + 2 * (i + 2)); + uint16_t i3 = vspace.read_u16(sc_addr + 2 * (i + 3)); + uint16_t i4 = vspace.read_u16(sc_addr + 2 * (i + 4)); + uint16_t i5 = vspace.read_u16(sc_addr + 2 * (i + 5)); + + /* Match: mov.l @(disp, pc), rX */ + if((i0 & 0xf000) != 0xd000) + continue; + int rX = (i0 >> 8) & 0x0f; + + /* Match: mov #3, rY */ + if((i1 & 0xf0ff) != 0xe003) + continue; + int rY = (i1 >> 8) & 0x0f; + + /* Match: bsr @(disp, pc) */ + if((i2 & 0xf000) != 0xb000) + continue; + int disp = (i2 & 0x0fff); + + /* Match: mov.b rX, @rY */ + if((i3 != 0x2000 + (rX << 8) + (rY << 4))) + continue; + + /* Match: bra @(_, pc) */ + if((i4 & 0xf000) != 0xa000) + continue; + + /* Match: nop */ + if(i5 != 0x0009) + continue; + + /* Return the target of the bsr instruction */ + uint32_t fun_addr = sc_addr + 2*(i+2) + 4 + disp * 2; + + fmt::print("found widget at 0x{:08x}\n", sc_addr + 2 * i); + fmt::print("rX = r{}, rY = r{}, disp = {}\n", rX, rY, disp); + fmt::print("main menu function address: 0x{:08x}\n", fun_addr); + } +} + +static std::string parse_am(Session &session, Parser &parser) +{ + if(!session.current_space) + return ""; + + std::string name = parser.symbol(); + parser.end(); + + return name; +} + +void _am(Session &session, std::string name) +{ + if(!session.current_space) { + FxOS_log(ERR, "am: no virtual space"); + return; + } + + if(name == "cg_main_menu_function") + _am_cg_main_menu_function(*session.current_space); + else + FxOS_log(ERR, "am: unknown misc. command '%s'", name); +} + //--- // Command definitions //--- @@ -174,3 +271,16 @@ Disassembles all syscalls entries using ad, which stores the results in the current virtual space's main disassembly. Unlike ad, this commands continues even if some syscalls fail to disassemble. )"); + +static ShellCommand _am_cmd( + "am", + [](Session &s, Parser &p) { + auto name = parse_am(s, p); + _am(s, name); + }, + [](Session &s, Parser &p) { parse_am(s, p); }, + "Analysis: Misc functions", R"( +am + +Runs miscellaneous analysis functions; commonly used for prototyping. +)");