# MAME, Ghidra & Apollo notes ## Getting gdb working with MAME patch at the end of this doc to mame, to fix side effects. Also tells mame to listen to INADDR_ANY, and not just localhost. Docker container with gdb-multiarch (works on arm64 macs with `colima` + docker): ``` docker run --net host --rm --name multiarch skysider/multiarch-docker ``` Then create a "gdb" binary script somewhere on localhost that contains the following and make it executable: ``` #!/bin/sh docker exec -it multiarch gdb-multiarch --nh -i mi2 -iex "target remote host.docker.internal:23946" -iex "set endian big" $* ``` This is the script you'll tell Ghidra to use. Edit `~/.ssh/config`, and add: ``` Host localhost RequestTTY force ``` Run MAME with `-debug -debugger gdbstub`, i.e.: ``` ./dn3500d dn3500 -uimodekey F12 -window -nomax -mouse -oslog -disk1 dn3500_sr10.4.awd -skip_gameinfo -sound none -debug -debugger gdbstub ``` In Ghidra, open the debugger tool. Select `Debugger > Debug domain_os_blah > in GDB via SSH`. Set `localhost` as the host, set your gdb script path, and hit Connect. Ghidra will pop up another dialog box asking you for a program to debug. I just hit Cancel here, since gdb is going to ignore any `file` etc commands. You should now be stopped. Finally, you need to map `domain_os` (or whatever) in manually. Open the Modules window, hit the little document icon to create a manual mapping, hit +, leave RAM at 0 base and set the address to `0xf0000000`. NOTE: this assumes that your domain_os has proper mappings set, as created by the apollo map file reader python script. Hit Apply. At this point you should be able to set breakpoints at kernel addresses; e.g. navigate to `KDB_$INIT`, right click and select "Toggle Breakpoint". Hit the green "go" arrow in the debugger window. You should be able to interact with MAME normally; once you `EX DOMAIN_OS`, the debugger should stop at your breakpoint. ### mame patch ``` diff --git src/mame/apollo/apollo.cpp src/mame/apollo/apollo.cpp index 74b7734551f..ed695ab215c 100644 --- src/mame/apollo/apollo.cpp +++ src/mame/apollo/apollo.cpp @@ -262,6 +262,9 @@ uint32_t apollo_state::apollo_instruction_hook(offs_t offset) void apollo_state::apollo_bus_error() { + if (machine().side_effects_disabled()) + return; + m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE); m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE); @@ -275,9 +278,11 @@ void apollo_state::cpu_space_map(address_map &map) u16 apollo_state::apollo_irq_acknowledge(offs_t offset) { - m_maincpu->set_input_line(offset+1, CLEAR_LINE); - - MLOG2(("apollo_irq_acknowledge: interrupt level=%d", offset+1)); + if (!machine().side_effects_disabled()) + { + m_maincpu->set_input_line(offset+1, CLEAR_LINE); + MLOG2(("apollo_irq_acknowledge: interrupt level=%d", offset+1)); + } if (offset+1 == 6) return apollo_pic_get_vector(); @@ -473,6 +478,8 @@ uint32_t apollo_state::apollo_unmapped_r(offs_t offset, uint32_t mem_mask) m68000_base_device *m68k = m_maincpu; + const bool side_effects_disabled = machine().side_effects_disabled(); + if ((address & 0xfff00000) == 0xfa800000 && VERBOSE < 2) { // ? } else if ((address & 0xfff00ff7) == 0xfd800000 && VERBOSE < 2) { @@ -487,12 +494,16 @@ uint32_t apollo_state::apollo_unmapped_r(offs_t offset, uint32_t mem_mask) // omit logging for Bus error test address in DN3500 boot prom and self_test } else if (address == 0x0000ac00 && VERBOSE < 2) { // omit logging for Bus error test address in DN3000 boot prom - } else { + } else if (!side_effects_disabled) { SLOG1(("unmapped memory dword read from %08x with mask %08x (ir=%04x)", address , mem_mask, m68k->state_int(M68K_IR))); } - /* unmapped; access causes a bus error */ - apollo_bus_error(); + if (!side_effects_disabled) + { + /* unmapped; access causes a bus error */ + apollo_bus_error(); + } + return 0xffffffff; } @@ -500,8 +511,11 @@ void apollo_state::apollo_unmapped_w(offs_t offset, uint32_t data, uint32_t mem_ { SLOG(("unmapped memory dword write to %08x = %08x & %08x", offset * 4, data, mem_mask)); - /* unmapped; access causes a bus error */ - apollo_bus_error(); + if (!machine().side_effects_disabled()) + { + /* unmapped; access causes a bus error */ + apollo_bus_error(); + } } /*************************************************************************** diff --git src/osd/modules/debugger/debuggdbstub.cpp src/osd/modules/debugger/debuggdbstub.cpp index 409b6fa3bbb..5fea1462405 100644 --- src/osd/modules/debugger/debuggdbstub.cpp +++ src/osd/modules/debugger/debuggdbstub.cpp @@ -474,6 +474,7 @@ static const std::map<std::string, const gdb_register_map &> gdb_register_maps = { "arm7_le", gdb_register_map_arm7 }, { "r4600", gdb_register_map_r4600 }, { "ppc601", gdb_register_map_ppc601 }, + { "m68030", gdb_register_map_m68020pmmu }, { "m68020pmmu", gdb_register_map_m68020pmmu }, { "m68000", gdb_register_map_m68000 }, { "z80", gdb_register_map_z80 }, @@ -777,12 +787,12 @@ void debug_gdbstub::wait_for_debugger(device_t &device, bool firststop) osd_printf_info("gdbstub: could not find register [%s]\n", reg.gdb_name); } -#if 0 +#if 0 for ( const auto &reg: m_gdb_registers ) osd_printf_info(" %3d (%d) %d %d [%s]\n", reg.gdb_regnum, reg.state_index, reg.gdb_bitsize, reg.gdb_type, reg.gdb_name); #endif - std::string socket_name = string_format("socket.localhost:%d", m_debugger_port); + std::string socket_name = string_format("socket.0.0.0.0:%d", m_debugger_port); std::error_condition const filerr = m_socket.open(socket_name); if ( filerr ) fatalerror("gdbstub: failed to start listening on port %d\n", m_debugger_port); ```