summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/debugger/debuggdbstub.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/osd/modules/debugger/debuggdbstub.cpp')
-rw-r--r--src/osd/modules/debugger/debuggdbstub.cpp1021
1 files changed, 716 insertions, 305 deletions
diff --git a/src/osd/modules/debugger/debuggdbstub.cpp b/src/osd/modules/debugger/debuggdbstub.cpp
index 4c7e4e3707e..729280f2134 100644
--- a/src/osd/modules/debugger/debuggdbstub.cpp
+++ b/src/osd/modules/debugger/debuggdbstub.cpp
@@ -7,15 +7,26 @@
//============================================================
#include "emu.h"
+#include "debug_module.h"
+
#include "debug/debugcon.h"
#include "debug/debugcpu.h"
+#include "debug/points.h"
#include "debug/textbuf.h"
-#include "debug_module.h"
#include "debugger.h"
+
#include "modules/lib/osdobj_common.h"
#include "modules/osdmodule.h"
+#include "fileio.h"
+
#include <cinttypes>
+#include <string_view>
+
+
+namespace osd {
+
+namespace {
//-------------------------------------------------------------------------
#define MAX_PACKET_SIZE 16384
@@ -37,71 +48,85 @@ static const char *const gdb_register_type_str[] = {
struct gdb_register_map
{
const char *arch;
- const char *feature;
- struct gdb_register_description
+ struct gdb_feature
{
- const char *state_name;
- const char *gdb_name;
- bool stop_packet;
- gdb_register_type gdb_type;
- int override_bitsize;
-
- gdb_register_description(const char *_state_name=nullptr, const char *_gdb_name=nullptr, bool _stop_packet=false, gdb_register_type _gdb_type=TYPE_INT, int _override_bitsize=-1)
- : state_name(_state_name)
- , gdb_name(_gdb_name)
- , stop_packet(_stop_packet)
- , gdb_type(_gdb_type)
- , override_bitsize(_override_bitsize)
+ const char *feature_name;
+ struct gdb_register_description
+ {
+ const char *state_name;
+ const char *gdb_name;
+ bool stop_packet;
+ gdb_register_type gdb_type;
+ int override_bitsize;
+
+ gdb_register_description(const char *_state_name = nullptr, const char *_gdb_name = nullptr, bool _stop_packet = false, gdb_register_type _gdb_type = TYPE_INT, int _override_bitsize = -1)
+ : state_name(_state_name)
+ , gdb_name(_gdb_name)
+ , stop_packet(_stop_packet)
+ , gdb_type(_gdb_type)
+ , override_bitsize(_override_bitsize)
+ {
+ }
+ };
+ std::vector<gdb_register_description> registers;
+
+ gdb_feature(const char *_feature_name, std::initializer_list<gdb_register_description> _registers)
+ : feature_name(_feature_name)
+ , registers(_registers)
{
}
};
- std::vector<gdb_register_description> registers;
+ std::vector<gdb_feature> features;
};
//-------------------------------------------------------------------------
static const gdb_register_map gdb_register_map_i486 =
{
"i386",
- "org.gnu.gdb.i386.core",
{
- { "EAX", "eax", false, TYPE_INT },
- { "ECX", "ecx", false, TYPE_INT },
- { "EDX", "edx", false, TYPE_INT },
- { "EBX", "ebx", false, TYPE_INT },
- { "ESP", "esp", true, TYPE_DATA_POINTER },
- { "EBP", "ebp", true, TYPE_DATA_POINTER },
- { "ESI", "esi", false, TYPE_INT },
- { "EDI", "edi", false, TYPE_INT },
- { "EIP", "eip", true, TYPE_CODE_POINTER },
- { "EFLAGS", "eflags", false, TYPE_INT }, // TODO describe bitfield
- { "CS", "cs", false, TYPE_INT },
- { "SS", "ss", false, TYPE_INT },
- { "DS", "ds", false, TYPE_INT },
- { "ES", "es", false, TYPE_INT },
- { "FS", "fs", false, TYPE_INT },
- { "GS", "gs", false, TYPE_INT },
- // TODO fix x87 registers!
- // The x87 registers are just plain wrong for a few reasons:
- // - The st* registers use a dummy variable in i386_device, so we
- // don't retrieve the real value (also the bitsize is wrong);
- // - The seg/off/op registers don't seem to be exported in the
- // state.
- { "ST0", "st0", false, TYPE_I387_EXT },
- { "ST1", "st1", false, TYPE_I387_EXT },
- { "ST2", "st2", false, TYPE_I387_EXT },
- { "ST3", "st3", false, TYPE_I387_EXT },
- { "ST4", "st4", false, TYPE_I387_EXT },
- { "ST5", "st5", false, TYPE_I387_EXT },
- { "ST6", "st6", false, TYPE_I387_EXT },
- { "ST7", "st7", false, TYPE_I387_EXT },
- { "x87_CW", "fctrl", false, TYPE_INT },
- { "x87_SW", "fstat", false, TYPE_INT },
- { "x87_TAG", "ftag", false, TYPE_INT },
- { "EAX", "fiseg", false, TYPE_INT },
- { "EAX", "fioff", false, TYPE_INT },
- { "EAX", "foseg", false, TYPE_INT },
- { "EAX", "fooff", false, TYPE_INT },
- { "EAX", "fop", false, TYPE_INT },
+ {
+ "org.gnu.gdb.i386.core",
+ {
+ { "EAX", "eax", false, TYPE_INT },
+ { "ECX", "ecx", false, TYPE_INT },
+ { "EDX", "edx", false, TYPE_INT },
+ { "EBX", "ebx", false, TYPE_INT },
+ { "ESP", "esp", true, TYPE_DATA_POINTER },
+ { "EBP", "ebp", true, TYPE_DATA_POINTER },
+ { "ESI", "esi", false, TYPE_INT },
+ { "EDI", "edi", false, TYPE_INT },
+ { "EIP", "eip", true, TYPE_CODE_POINTER },
+ { "EFLAGS", "eflags", false, TYPE_INT }, // TODO describe bitfield
+ { "CS", "cs", false, TYPE_INT },
+ { "SS", "ss", false, TYPE_INT },
+ { "DS", "ds", false, TYPE_INT },
+ { "ES", "es", false, TYPE_INT },
+ { "FS", "fs", false, TYPE_INT },
+ { "GS", "gs", false, TYPE_INT },
+ // TODO fix x87 registers!
+ // The x87 registers are just plain wrong for a few reasons:
+ // - The st* registers use a dummy variable in i386_device, so we
+ // don't retrieve the real value (also the bitsize is wrong);
+ // - The seg/off/op registers don't seem to be exported in the
+ // state.
+ { "ST0", "st0", false, TYPE_I387_EXT },
+ { "ST1", "st1", false, TYPE_I387_EXT },
+ { "ST2", "st2", false, TYPE_I387_EXT },
+ { "ST3", "st3", false, TYPE_I387_EXT },
+ { "ST4", "st4", false, TYPE_I387_EXT },
+ { "ST5", "st5", false, TYPE_I387_EXT },
+ { "ST6", "st6", false, TYPE_I387_EXT },
+ { "ST7", "st7", false, TYPE_I387_EXT },
+ { "x87_CW", "fctrl", false, TYPE_INT },
+ { "x87_SW", "fstat", false, TYPE_INT },
+ { "x87_TAG", "ftag", false, TYPE_INT },
+ { "EAX", "fiseg", false, TYPE_INT },
+ { "EAX", "fioff", false, TYPE_INT },
+ { "EAX", "foseg", false, TYPE_INT },
+ { "EAX", "fooff", false, TYPE_INT },
+ { "EAX", "fop", false, TYPE_INT },
+ }
+ }
}
};
@@ -109,25 +134,29 @@ static const gdb_register_map gdb_register_map_i486 =
static const gdb_register_map gdb_register_map_arm7 =
{
"arm",
- "org.gnu.gdb.arm.core",
{
- { "R0", "r0", false, TYPE_INT },
- { "R1", "r1", false, TYPE_INT },
- { "R2", "r2", false, TYPE_INT },
- { "R3", "r3", false, TYPE_INT },
- { "R4", "r4", false, TYPE_INT },
- { "R5", "r5", false, TYPE_INT },
- { "R6", "r6", false, TYPE_INT },
- { "R7", "r7", false, TYPE_INT },
- { "R8", "r8", false, TYPE_INT },
- { "R9", "r9", false, TYPE_INT },
- { "R10", "r10", false, TYPE_INT },
- { "R11", "r11", false, TYPE_INT },
- { "R12", "r12", false, TYPE_INT },
- { "R13", "sp", true, TYPE_DATA_POINTER },
- { "R14", "lr", true, TYPE_INT },
- { "R15", "pc", true, TYPE_CODE_POINTER },
- { "CPSR", "cpsr", false, TYPE_INT }, // TODO describe bitfield
+ {
+ "org.gnu.gdb.arm.core",
+ {
+ { "R0", "r0", false, TYPE_INT },
+ { "R1", "r1", false, TYPE_INT },
+ { "R2", "r2", false, TYPE_INT },
+ { "R3", "r3", false, TYPE_INT },
+ { "R4", "r4", false, TYPE_INT },
+ { "R5", "r5", false, TYPE_INT },
+ { "R6", "r6", false, TYPE_INT },
+ { "R7", "r7", false, TYPE_INT },
+ { "R8", "r8", false, TYPE_INT },
+ { "R9", "r9", false, TYPE_INT },
+ { "R10", "r10", false, TYPE_INT },
+ { "R11", "r11", false, TYPE_INT },
+ { "R12", "r12", false, TYPE_INT },
+ { "R13", "sp", true, TYPE_DATA_POINTER },
+ { "R14", "lr", true, TYPE_INT },
+ { "R15", "pc", true, TYPE_CODE_POINTER },
+ { "CPSR", "cpsr", false, TYPE_INT }, // TODO describe bitfield
+ }
+ }
}
};
@@ -135,46 +164,50 @@ static const gdb_register_map gdb_register_map_arm7 =
static const gdb_register_map gdb_register_map_ppc601 =
{
"powerpc:common",
- "org.gnu.gdb.power.core",
{
- { "R0", "r0", false, TYPE_INT },
- { "R1", "r1", false, TYPE_INT },
- { "R2", "r2", false, TYPE_INT },
- { "R3", "r3", false, TYPE_INT },
- { "R4", "r4", false, TYPE_INT },
- { "R5", "r5", false, TYPE_INT },
- { "R6", "r6", false, TYPE_INT },
- { "R7", "r7", false, TYPE_INT },
- { "R8", "r8", false, TYPE_INT },
- { "R9", "r9", false, TYPE_INT },
- { "R10", "r10", false, TYPE_INT },
- { "R11", "r11", false, TYPE_INT },
- { "R12", "r12", false, TYPE_INT },
- { "R13", "r13", false, TYPE_INT },
- { "R14", "r14", false, TYPE_INT },
- { "R15", "r15", false, TYPE_INT },
- { "R16", "r16", false, TYPE_INT },
- { "R17", "r17", false, TYPE_INT },
- { "R18", "r18", false, TYPE_INT },
- { "R19", "r19", false, TYPE_INT },
- { "R20", "r20", false, TYPE_INT },
- { "R21", "r21", false, TYPE_INT },
- { "R22", "r22", false, TYPE_INT },
- { "R23", "r23", false, TYPE_INT },
- { "R24", "r24", false, TYPE_INT },
- { "R25", "r25", false, TYPE_INT },
- { "R26", "r26", false, TYPE_INT },
- { "R27", "r27", false, TYPE_INT },
- { "R28", "r28", false, TYPE_INT },
- { "R29", "r29", false, TYPE_INT },
- { "R30", "r30", false, TYPE_INT },
- { "R31", "r31", false, TYPE_INT },
- { "PC", "pc", true, TYPE_CODE_POINTER },
- { "MSR", "msr", false, TYPE_INT },
- { "CR", "cr", false, TYPE_INT },
- { "LR", "lr", true, TYPE_CODE_POINTER },
- { "CTR", "ctr", false, TYPE_INT },
- { "XER", "xer", false, TYPE_INT },
+ {
+ "org.gnu.gdb.power.core",
+ {
+ { "R0", "r0", false, TYPE_INT },
+ { "R1", "r1", false, TYPE_INT },
+ { "R2", "r2", false, TYPE_INT },
+ { "R3", "r3", false, TYPE_INT },
+ { "R4", "r4", false, TYPE_INT },
+ { "R5", "r5", false, TYPE_INT },
+ { "R6", "r6", false, TYPE_INT },
+ { "R7", "r7", false, TYPE_INT },
+ { "R8", "r8", false, TYPE_INT },
+ { "R9", "r9", false, TYPE_INT },
+ { "R10", "r10", false, TYPE_INT },
+ { "R11", "r11", false, TYPE_INT },
+ { "R12", "r12", false, TYPE_INT },
+ { "R13", "r13", false, TYPE_INT },
+ { "R14", "r14", false, TYPE_INT },
+ { "R15", "r15", false, TYPE_INT },
+ { "R16", "r16", false, TYPE_INT },
+ { "R17", "r17", false, TYPE_INT },
+ { "R18", "r18", false, TYPE_INT },
+ { "R19", "r19", false, TYPE_INT },
+ { "R20", "r20", false, TYPE_INT },
+ { "R21", "r21", false, TYPE_INT },
+ { "R22", "r22", false, TYPE_INT },
+ { "R23", "r23", false, TYPE_INT },
+ { "R24", "r24", false, TYPE_INT },
+ { "R25", "r25", false, TYPE_INT },
+ { "R26", "r26", false, TYPE_INT },
+ { "R27", "r27", false, TYPE_INT },
+ { "R28", "r28", false, TYPE_INT },
+ { "R29", "r29", false, TYPE_INT },
+ { "R30", "r30", false, TYPE_INT },
+ { "R31", "r31", false, TYPE_INT },
+ { "PC", "pc", true, TYPE_CODE_POINTER },
+ { "MSR", "msr", false, TYPE_INT },
+ { "CR", "cr", false, TYPE_INT },
+ { "LR", "lr", true, TYPE_CODE_POINTER },
+ { "CTR", "ctr", false, TYPE_INT },
+ { "XER", "xer", false, TYPE_INT },
+ }
+ }
}
};
@@ -182,43 +215,78 @@ static const gdb_register_map gdb_register_map_ppc601 =
static const gdb_register_map gdb_register_map_r4600 =
{
"mips",
- "org.gnu.gdb.mips.cpu",
{
- { "zero", "r0", false, TYPE_INT, 32 },
- { "at", "r1", false, TYPE_INT, 32 },
- { "v0", "r2", false, TYPE_INT, 32 },
- { "v1", "r3", false, TYPE_INT, 32 },
- { "a0", "r4", false, TYPE_INT, 32 },
- { "a1", "r5", false, TYPE_INT, 32 },
- { "a2", "r6", false, TYPE_INT, 32 },
- { "a3", "r7", false, TYPE_INT, 32 },
- { "t0", "r8", false, TYPE_INT, 32 },
- { "t1", "r9", false, TYPE_INT, 32 },
- { "t2", "r10", false, TYPE_INT, 32 },
- { "t3", "r11", false, TYPE_INT, 32 },
- { "t4", "r12", false, TYPE_INT, 32 },
- { "t5", "r13", false, TYPE_INT, 32 },
- { "t6", "r14", false, TYPE_INT, 32 },
- { "t7", "r15", false, TYPE_INT, 32 },
- { "s0", "r16", false, TYPE_INT, 32 },
- { "s1", "r17", false, TYPE_INT, 32 },
- { "s2", "r18", false, TYPE_INT, 32 },
- { "s3", "r19", false, TYPE_INT, 32 },
- { "s4", "r20", false, TYPE_INT, 32 },
- { "s5", "r21", false, TYPE_INT, 32 },
- { "s6", "r22", false, TYPE_INT, 32 },
- { "s7", "r23", false, TYPE_INT, 32 },
- { "t8", "r24", false, TYPE_INT, 32 },
- { "t9", "r25", false, TYPE_INT, 32 },
- { "k0", "r26", false, TYPE_INT, 32 },
- { "k1", "r27", false, TYPE_INT, 32 },
- { "gp", "r28", false, TYPE_INT, 32 },
- { "sp", "r29", false, TYPE_INT, 32 },
- { "fp", "r30", false, TYPE_INT, 32 },
- { "ra", "r31", false, TYPE_INT, 32 },
- { "LO", "lo", false, TYPE_INT, 32 },
- { "HI", "hi", false, TYPE_INT, 32 },
- { "PC", "pc", true, TYPE_CODE_POINTER, 32 },
+ {
+ "org.gnu.gdb.mips.cpu",
+ {
+ { "zero", "r0", false, TYPE_INT, 32 },
+ { "at", "r1", false, TYPE_INT, 32 },
+ { "v0", "r2", false, TYPE_INT, 32 },
+ { "v1", "r3", false, TYPE_INT, 32 },
+ { "a0", "r4", false, TYPE_INT, 32 },
+ { "a1", "r5", false, TYPE_INT, 32 },
+ { "a2", "r6", false, TYPE_INT, 32 },
+ { "a3", "r7", false, TYPE_INT, 32 },
+ { "t0", "r8", false, TYPE_INT, 32 },
+ { "t1", "r9", false, TYPE_INT, 32 },
+ { "t2", "r10", false, TYPE_INT, 32 },
+ { "t3", "r11", false, TYPE_INT, 32 },
+ { "t4", "r12", false, TYPE_INT, 32 },
+ { "t5", "r13", false, TYPE_INT, 32 },
+ { "t6", "r14", false, TYPE_INT, 32 },
+ { "t7", "r15", false, TYPE_INT, 32 },
+ { "s0", "r16", false, TYPE_INT, 32 },
+ { "s1", "r17", false, TYPE_INT, 32 },
+ { "s2", "r18", false, TYPE_INT, 32 },
+ { "s3", "r19", false, TYPE_INT, 32 },
+ { "s4", "r20", false, TYPE_INT, 32 },
+ { "s5", "r21", false, TYPE_INT, 32 },
+ { "s6", "r22", false, TYPE_INT, 32 },
+ { "s7", "r23", false, TYPE_INT, 32 },
+ { "t8", "r24", false, TYPE_INT, 32 },
+ { "t9", "r25", false, TYPE_INT, 32 },
+ { "k0", "r26", false, TYPE_INT, 32 },
+ { "k1", "r27", false, TYPE_INT, 32 },
+ { "gp", "r28", false, TYPE_INT, 32 },
+ { "sp", "r29", false, TYPE_INT, 32 },
+ { "fp", "r30", false, TYPE_INT, 32 },
+ { "ra", "r31", false, TYPE_INT, 32 },
+ { "LO", "lo", false, TYPE_INT, 32 },
+ { "HI", "hi", false, TYPE_INT, 32 },
+ { "PC", "pc", true, TYPE_CODE_POINTER, 32 },
+ }
+ }
+ }
+};
+
+//-------------------------------------------------------------------------
+static const gdb_register_map gdb_register_map_m68030 =
+{
+ "m68k",
+ {
+ {
+ "org.gnu.gdb.m68k.core",
+ {
+ { "D0", "d0", false, TYPE_INT },
+ { "D1", "d1", false, TYPE_INT },
+ { "D2", "d2", false, TYPE_INT },
+ { "D3", "d3", false, TYPE_INT },
+ { "D4", "d4", false, TYPE_INT },
+ { "D5", "d5", false, TYPE_INT },
+ { "D6", "d6", false, TYPE_INT },
+ { "D7", "d7", false, TYPE_INT },
+ { "A0", "a0", false, TYPE_INT },
+ { "A1", "a1", false, TYPE_INT },
+ { "A2", "a2", false, TYPE_INT },
+ { "A3", "a3", false, TYPE_INT },
+ { "A4", "a4", false, TYPE_INT },
+ { "A5", "a5", false, TYPE_INT },
+ { "A6", "fp", true, TYPE_INT },
+ { "SP", "sp", true, TYPE_INT },
+ { "SR", "ps", false, TYPE_INT }, // NOTE GDB named it ps, but it's actually sr
+ { "CURPC","pc", true, TYPE_CODE_POINTER },
+ }
+ }
}
};
@@ -226,26 +294,62 @@ static const gdb_register_map gdb_register_map_r4600 =
static const gdb_register_map gdb_register_map_m68020pmmu =
{
"m68k",
- "org.gnu.gdb.m68k.core",
{
- { "D0", "d0", false, TYPE_INT },
- { "D1", "d1", false, TYPE_INT },
- { "D2", "d2", false, TYPE_INT },
- { "D3", "d3", false, TYPE_INT },
- { "D4", "d4", false, TYPE_INT },
- { "D5", "d5", false, TYPE_INT },
- { "D6", "d6", false, TYPE_INT },
- { "D7", "d7", false, TYPE_INT },
- { "A0", "a0", false, TYPE_INT },
- { "A1", "a1", false, TYPE_INT },
- { "A2", "a2", false, TYPE_INT },
- { "A3", "a3", false, TYPE_INT },
- { "A4", "a4", false, TYPE_INT },
- { "A5", "a5", false, TYPE_INT },
- { "A6", "fp", true, TYPE_INT },
- { "A7", "sp", true, TYPE_INT },
- { "SR", "ps", false, TYPE_INT }, // NOTE GDB named it ps, but it's actually sr
- { "PC", "pc", true, TYPE_CODE_POINTER },
+ {
+ "org.gnu.gdb.m68k.core",
+ {
+ { "D0", "d0", false, TYPE_INT },
+ { "D1", "d1", false, TYPE_INT },
+ { "D2", "d2", false, TYPE_INT },
+ { "D3", "d3", false, TYPE_INT },
+ { "D4", "d4", false, TYPE_INT },
+ { "D5", "d5", false, TYPE_INT },
+ { "D6", "d6", false, TYPE_INT },
+ { "D7", "d7", false, TYPE_INT },
+ { "A0", "a0", false, TYPE_INT },
+ { "A1", "a1", false, TYPE_INT },
+ { "A2", "a2", false, TYPE_INT },
+ { "A3", "a3", false, TYPE_INT },
+ { "A4", "a4", false, TYPE_INT },
+ { "A5", "a5", false, TYPE_INT },
+ { "A6", "fp", true, TYPE_INT },
+ { "SP", "sp", true, TYPE_INT },
+ { "SR", "ps", false, TYPE_INT }, // NOTE GDB named it ps, but it's actually sr
+ { "CURPC","pc", true, TYPE_CODE_POINTER },
+ }
+ }
+ }
+};
+
+//-------------------------------------------------------------------------
+static const gdb_register_map gdb_register_map_m68000 =
+{
+ "m68k",
+ {
+ {
+ "org.gnu.gdb.m68k.core",
+ {
+ { "D0", "d0", false, TYPE_INT },
+ { "D1", "d1", false, TYPE_INT },
+ { "D2", "d2", false, TYPE_INT },
+ { "D3", "d3", false, TYPE_INT },
+ { "D4", "d4", false, TYPE_INT },
+ { "D5", "d5", false, TYPE_INT },
+ { "D6", "d6", false, TYPE_INT },
+ { "D7", "d7", false, TYPE_INT },
+ { "A0", "a0", false, TYPE_INT },
+ { "A1", "a1", false, TYPE_INT },
+ { "A2", "a2", false, TYPE_INT },
+ { "A3", "a3", false, TYPE_INT },
+ { "A4", "a4", false, TYPE_INT },
+ { "A5", "a5", false, TYPE_INT },
+ { "A6", "fp", true, TYPE_INT },
+ { "SP", "sp", true, TYPE_INT },
+ { "SR", "ps", false, TYPE_INT }, // NOTE GDB named it ps, but it's actually sr
+ { "CURPC","pc", true, TYPE_CODE_POINTER },
+ //NOTE m68-elf-gdb complains about fpcontrol register not present but 68000 doesn't have floating point so...
+ }
+ }
}
};
@@ -253,20 +357,24 @@ static const gdb_register_map gdb_register_map_m68020pmmu =
static const gdb_register_map gdb_register_map_z80 =
{
"z80",
- "mame.z80",
{
- { "AF", "af", false, TYPE_INT },
- { "BC", "bc", false, TYPE_INT },
- { "DE", "de", false, TYPE_INT },
- { "HL", "hl", false, TYPE_INT },
- { "AF2", "af'", false, TYPE_INT },
- { "BC2", "bc'", false, TYPE_INT },
- { "DE2", "de'", false, TYPE_INT },
- { "HL2", "hl'", false, TYPE_INT },
- { "IX", "ix", false, TYPE_INT },
- { "IY", "iy", false, TYPE_INT },
- { "SP", "sp", true, TYPE_DATA_POINTER },
- { "PC", "pc", true, TYPE_CODE_POINTER },
+ {
+ "mame.z80",
+ {
+ { "AF", "af", false, TYPE_INT },
+ { "BC", "bc", false, TYPE_INT },
+ { "DE", "de", false, TYPE_INT },
+ { "HL", "hl", false, TYPE_INT },
+ { "AF2", "af'", false, TYPE_INT },
+ { "BC2", "bc'", false, TYPE_INT },
+ { "DE2", "de'", false, TYPE_INT },
+ { "HL2", "hl'", false, TYPE_INT },
+ { "IX", "ix", false, TYPE_INT },
+ { "IY", "iy", false, TYPE_INT },
+ { "SP", "sp", true, TYPE_DATA_POINTER },
+ { "PC", "pc", true, TYPE_CODE_POINTER },
+ }
+ }
}
};
@@ -274,14 +382,270 @@ static const gdb_register_map gdb_register_map_z80 =
static const gdb_register_map gdb_register_map_m6502 =
{
"m6502",
- "mame.m6502",
{
- { "A", "a", false, TYPE_INT },
- { "X", "x", false, TYPE_INT },
- { "Y", "y", false, TYPE_INT },
- { "P", "p", false, TYPE_INT },
- { "PC", "pc", true, TYPE_CODE_POINTER },
- { "SP", "sp", true, TYPE_DATA_POINTER },
+ {
+ "mame.m6502",
+ {
+ { "A", "a", false, TYPE_INT },
+ { "X", "x", false, TYPE_INT },
+ { "Y", "y", false, TYPE_INT },
+ { "P", "p", false, TYPE_INT },
+ { "SP", "sp", true, TYPE_DATA_POINTER },
+ { "PC", "pc", true, TYPE_CODE_POINTER },
+ }
+ }
+ }
+};
+
+
+//-------------------------------------------------------------------------
+static const gdb_register_map gdb_register_map_m6809 =
+{
+ "m6809",
+ {
+ {
+ "mame.m6809",
+ {
+ { "A", "a", false, TYPE_INT },
+ { "B", "b", false, TYPE_INT },
+ { "D", "d", false, TYPE_INT },
+ { "X", "x", false, TYPE_INT },
+ { "Y", "y", false, TYPE_INT },
+ { "U", "u", true, TYPE_DATA_POINTER },
+ { "PC", "pc", true, TYPE_CODE_POINTER },
+ { "S", "s", true, TYPE_DATA_POINTER },
+ { "CC", "cc", false, TYPE_INT }, // TODO describe bitfield
+ { "DP", "dp", false, TYPE_INT },
+ }
+ }
+ }
+};
+
+
+//-------------------------------------------------------------------------
+static const gdb_register_map gdb_register_map_score7 =
+{
+ "score7",
+ {
+ {
+ "mame.score7",
+ {
+ { "r0", "r0", true, TYPE_DATA_POINTER },
+ { "r1", "r1", false, TYPE_INT },
+ { "r2", "r2", false, TYPE_INT },
+ { "r3", "r3", false, TYPE_INT },
+ { "r4", "r4", false, TYPE_INT },
+ { "r5", "r5", false, TYPE_INT },
+ { "r6", "r6", false, TYPE_INT },
+ { "r7", "r7", false, TYPE_INT },
+ { "r8", "r8", false, TYPE_INT },
+ { "r9", "r9", false, TYPE_INT },
+ { "r10", "r10", false, TYPE_INT },
+ { "r11", "r11", false, TYPE_INT },
+ { "r12", "r12", false, TYPE_INT },
+ { "r13", "r13", false, TYPE_INT },
+ { "r14", "r14", false, TYPE_INT },
+ { "r15", "r15", false, TYPE_INT },
+ { "r16", "r16", false, TYPE_INT },
+ { "r17", "r17", false, TYPE_INT },
+ { "r18", "r18", false, TYPE_INT },
+ { "r19", "r19", false, TYPE_INT },
+ { "r20", "r20", false, TYPE_INT },
+ { "r21", "r21", false, TYPE_INT },
+ { "r22", "r22", false, TYPE_INT },
+ { "r23", "r23", false, TYPE_INT },
+ { "r24", "r24", false, TYPE_INT },
+ { "r25", "r25", false, TYPE_INT },
+ { "r26", "r26", false, TYPE_INT },
+ { "r27", "r27", false, TYPE_INT },
+ { "r28", "r28", false, TYPE_INT },
+ { "r29", "r29", false, TYPE_INT },
+ { "r30", "r30", false, TYPE_INT },
+ { "r31", "r31", false, TYPE_INT },
+ { "cr0", "PSR", false, TYPE_INT },
+ { "cr1", "COND", false, TYPE_INT },
+ { "cr2", "ECR", false, TYPE_INT },
+ { "cr3", "EXCPVEC", false, TYPE_INT },
+ { "cr4", "CCR", false, TYPE_INT },
+ { "cr5", "EPC", false, TYPE_INT },
+ { "cr6", "EMA", false, TYPE_INT },
+ { "cr7", "TLBLOCK", false, TYPE_INT },
+ { "cr8", "TLBPT", false, TYPE_INT },
+ { "cr9", "PEADDR", false, TYPE_INT },
+ { "cr10", "TLBRPT", false, TYPE_INT },
+ { "cr11", "PEVN", false, TYPE_INT },
+ { "cr12", "PECTX", false, TYPE_INT },
+ { "cr15", "LIMPFN", false, TYPE_INT },
+ { "cr16", "LDMPFN", false, TYPE_INT },
+ { "cr18", "PREV", false, TYPE_INT },
+ { "cr29", "DREG", false, TYPE_INT },
+ { "PC", "PC", true, TYPE_CODE_POINTER }, // actually Debug exception program counter (DEPC)
+ { "cr31", "DSAVE", false, TYPE_INT },
+ { "sr0", "COUNTER", false, TYPE_INT },
+ { "sr1", "LDCR", false, TYPE_INT },
+ { "sr2", "STCR", false, TYPE_INT },
+ { "ceh", "CEH", false, TYPE_INT },
+ { "cel", "CEL", false, TYPE_INT },
+ }
+ }
+ }
+};
+
+
+//-------------------------------------------------------------------------
+static const gdb_register_map gdb_register_map_nios2 =
+{
+ "nios2",
+ {
+ {
+ "org.gnu.gdb.nios2.cpu",
+ {
+ { "zero", "zero", false, TYPE_INT },
+ { "at", "at", false, TYPE_INT },
+ { "r2", "r2", false, TYPE_INT },
+ { "r3", "r3", false, TYPE_INT },
+ { "r4", "r4", false, TYPE_INT },
+ { "r5", "r5", false, TYPE_INT },
+ { "r6", "r6", false, TYPE_INT },
+ { "r7", "r7", false, TYPE_INT },
+ { "r8", "r8", false, TYPE_INT },
+ { "r9", "r9", false, TYPE_INT },
+ { "r10", "r10", false, TYPE_INT },
+ { "r11", "r11", false, TYPE_INT },
+ { "r12", "r12", false, TYPE_INT },
+ { "r13", "r13", false, TYPE_INT },
+ { "r14", "r14", false, TYPE_INT },
+ { "r15", "r15", false, TYPE_INT },
+ { "r16", "r16", false, TYPE_INT },
+ { "r17", "r17", false, TYPE_INT },
+ { "r18", "r18", false, TYPE_INT },
+ { "r19", "r19", false, TYPE_INT },
+ { "r20", "r20", false, TYPE_INT },
+ { "r21", "r21", false, TYPE_INT },
+ { "r22", "r22", false, TYPE_INT },
+ { "r23", "r23", false, TYPE_INT },
+ { "et", "et", false, TYPE_INT },
+ { "bt", "bt", false, TYPE_INT },
+ { "gp", "gp", false, TYPE_DATA_POINTER },
+ { "sp", "sp", true, TYPE_DATA_POINTER },
+ { "fp", "fp", false, TYPE_DATA_POINTER },
+ { "ea", "ea", false, TYPE_CODE_POINTER },
+ { "ba", "sstatus", false, TYPE_INT }, // this is Altera's fault
+ { "ra", "ra", false, TYPE_CODE_POINTER },
+ { "status", "status", false, TYPE_INT },
+ { "estatus", "estatus", false, TYPE_INT },
+ { "bstatus", "bstatus", false, TYPE_INT },
+ { "ienable", "ienable", false, TYPE_INT },
+ { "ipending", "ipending", false, TYPE_INT },
+ { "cpuid", "cpuid", false, TYPE_INT },
+ { "ctl6", "ctl6", false, TYPE_INT },
+ { "exception","exception",false, TYPE_INT },
+ { "pteaddr", "pteaddr", false, TYPE_INT },
+ { "tlbacc", "tlbacc", false, TYPE_INT },
+ { "tlbmisc", "tlbmisc", false, TYPE_INT },
+ { "eccinj", "eccinj", false, TYPE_INT },
+ { "badaddr", "badaddr", false, TYPE_INT },
+ { "config", "config", false, TYPE_INT },
+ { "mpubase", "mpubase", false, TYPE_INT },
+ { "mpuacc", "mpuacc", false, TYPE_INT },
+ { "PC", "pc", true, TYPE_CODE_POINTER },
+ }
+ }
+ }
+};
+
+//-------------------------------------------------------------------------
+static const gdb_register_map gdb_register_map_psxcpu =
+{
+ "mips",
+ {
+ {
+ "org.gnu.gdb.mips.cpu",
+ {
+ { "zero", "r0", false, TYPE_INT },
+ { "at", "r1", false, TYPE_INT },
+ { "v0", "r2", false, TYPE_INT },
+ { "v1", "r3", false, TYPE_INT },
+ { "a0", "r4", false, TYPE_INT },
+ { "a1", "r5", false, TYPE_INT },
+ { "a2", "r6", false, TYPE_INT },
+ { "a3", "r7", false, TYPE_INT },
+ { "t0", "r8", false, TYPE_INT },
+ { "t1", "r9", false, TYPE_INT },
+ { "t2", "r10", false, TYPE_INT },
+ { "t3", "r11", false, TYPE_INT },
+ { "t4", "r12", false, TYPE_INT },
+ { "t5", "r13", false, TYPE_INT },
+ { "t6", "r14", false, TYPE_INT },
+ { "t7", "r15", false, TYPE_INT },
+ { "s0", "r16", false, TYPE_INT },
+ { "s1", "r17", false, TYPE_INT },
+ { "s2", "r18", false, TYPE_INT },
+ { "s3", "r19", false, TYPE_INT },
+ { "s4", "r20", false, TYPE_INT },
+ { "s5", "r21", false, TYPE_INT },
+ { "s6", "r22", false, TYPE_INT },
+ { "s7", "r23", false, TYPE_INT },
+ { "t8", "r24", false, TYPE_INT },
+ { "t9", "r25", false, TYPE_INT },
+ { "k0", "r26", false, TYPE_INT },
+ { "k1", "r27", false, TYPE_INT },
+ { "gp", "r28", false, TYPE_INT },
+ { "sp", "r29", false, TYPE_INT },
+ { "fp", "r30", false, TYPE_INT },
+ { "ra", "r31", false, TYPE_CODE_POINTER },
+ { "lo", "lo", false, TYPE_INT },
+ { "hi", "hi", false, TYPE_INT },
+ { "pc", "pc", true, TYPE_CODE_POINTER },
+ }
+ },
+ {
+ "org.gnu.gdb.mips.cp0",
+ {
+ { "SR", "status", false, TYPE_INT },
+ { "BadA", "badvaddr", false, TYPE_INT },
+ { "Cause", "cause", false, TYPE_INT },
+ }
+ },
+ {
+ "org.gnu.gdb.mips.fpu",
+ {
+ { "zero", "f0", false, TYPE_INT },
+ { "zero", "f1", false, TYPE_INT },
+ { "zero", "f2", false, TYPE_INT },
+ { "zero", "f3", false, TYPE_INT },
+ { "zero", "f4", false, TYPE_INT },
+ { "zero", "f5", false, TYPE_INT },
+ { "zero", "f6", false, TYPE_INT },
+ { "zero", "f7", false, TYPE_INT },
+ { "zero", "f8", false, TYPE_INT },
+ { "zero", "f9", false, TYPE_INT },
+ { "zero", "f10", false, TYPE_INT },
+ { "zero", "f11", false, TYPE_INT },
+ { "zero", "f12", false, TYPE_INT },
+ { "zero", "f13", false, TYPE_INT },
+ { "zero", "f14", false, TYPE_INT },
+ { "zero", "f15", false, TYPE_INT },
+ { "zero", "f16", false, TYPE_INT },
+ { "zero", "f17", false, TYPE_INT },
+ { "zero", "f18", false, TYPE_INT },
+ { "zero", "f19", false, TYPE_INT },
+ { "zero", "f20", false, TYPE_INT },
+ { "zero", "f21", false, TYPE_INT },
+ { "zero", "f22", false, TYPE_INT },
+ { "zero", "f23", false, TYPE_INT },
+ { "zero", "f24", false, TYPE_INT },
+ { "zero", "f25", false, TYPE_INT },
+ { "zero", "f26", false, TYPE_INT },
+ { "zero", "f27", false, TYPE_INT },
+ { "zero", "f28", false, TYPE_INT },
+ { "zero", "f29", false, TYPE_INT },
+ { "zero", "f30", false, TYPE_INT },
+ { "zero", "f31", false, TYPE_INT },
+ { "zero", "fcsr", false, TYPE_INT },
+ { "zero", "fir" , false, TYPE_INT },
+ }
+ }
}
};
@@ -291,17 +655,40 @@ 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_m68030 },
{ "m68020pmmu", gdb_register_map_m68020pmmu },
+ { "m68000", gdb_register_map_m68000 },
{ "z80", gdb_register_map_z80 },
+ { "z80n", gdb_register_map_z80 },
+ { "z84c015", gdb_register_map_z80 },
{ "m6502", gdb_register_map_m6502 },
+ { "m6507", gdb_register_map_m6502 },
+ { "m6510", gdb_register_map_m6502 },
+ { "m65ce02", gdb_register_map_m6502 },
+ { "rp2a03", gdb_register_map_m6502 },
+ { "w65c02", gdb_register_map_m6502 },
+ { "w65c02s", gdb_register_map_m6502 },
+ { "m6809", gdb_register_map_m6809 },
+ { "score7", gdb_register_map_score7 },
+ { "nios2", gdb_register_map_nios2 },
+ { "cxd8530q", gdb_register_map_psxcpu },
+ { "cxd8530aq", gdb_register_map_psxcpu },
+ { "cxd8530bq", gdb_register_map_psxcpu },
+ { "cxd8530cq", gdb_register_map_psxcpu },
+ { "cxd8606q", gdb_register_map_psxcpu },
+ { "cxd8606aq", gdb_register_map_psxcpu },
+ { "cxd8606bq", gdb_register_map_psxcpu },
+ { "cxd8606cq", gdb_register_map_psxcpu },
+ { "cxd8661r", gdb_register_map_psxcpu },
};
//-------------------------------------------------------------------------
class debug_gdbstub : public osd_module, public debug_module
{
public:
- debug_gdbstub()
- : osd_module(OSD_DEBUG_PROVIDER, "gdbstub"), debug_module(),
+ debug_gdbstub() :
+ osd_module(OSD_DEBUG_PROVIDER, "gdbstub"), debug_module(),
+ m_readbuf_state(PACKET_START),
m_machine(nullptr),
m_maincpu(nullptr),
m_state(nullptr),
@@ -309,6 +696,7 @@ public:
m_address_space(nullptr),
m_debugger_cpu(nullptr),
m_debugger_console(nullptr),
+ m_debugger_host(),
m_debugger_port(0),
m_socket(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE),
m_is_be(false),
@@ -329,7 +717,7 @@ public:
virtual ~debug_gdbstub() { }
- virtual int init(const osd_options &options) override;
+ virtual int init(osd_interface &osd, const osd_options &options) override;
virtual void exit() override;
virtual void init_debugger(running_machine &machine) override;
@@ -346,9 +734,9 @@ public:
bool is_thread_id_ok(const char *buf);
void handle_character(char ch);
- void send_nack(void);
- void send_ack(void);
- void handle_packet(void);
+ void send_nack();
+ void send_ack();
+ void handle_packet();
enum cmd_reply
{
@@ -374,6 +762,7 @@ public:
cmd_reply handle_P(const char *buf);
cmd_reply handle_q(const char *buf);
cmd_reply handle_s(const char *buf);
+ cmd_reply handle_T(const char *buf);
cmd_reply handle_z(const char *buf);
cmd_reply handle_Z(const char *buf);
@@ -387,12 +776,12 @@ public:
readbuf_state m_readbuf_state;
- void generate_target_xml(void);
+ void generate_target_xml();
- int readchar(void);
+ int readchar();
- void send_reply(const char *str);
- void send_stop_packet(void);
+ void send_reply(std::string_view str);
+ void send_stop_packet();
private:
running_machine *m_machine;
@@ -402,6 +791,7 @@ private:
address_space *m_address_space;
debugger_cpu *m_debugger_cpu;
debugger_console *m_debugger_console;
+ std::string m_debugger_host;
int m_debugger_port;
emu_file m_socket;
bool m_is_be;
@@ -413,6 +803,7 @@ private:
struct gdb_register
{
+ std::string gdb_feature_name;
std::string gdb_name;
int gdb_regnum;
gdb_register_type gdb_type;
@@ -422,12 +813,11 @@ private:
std::vector<gdb_register> m_gdb_registers;
std::set<int> m_stop_reply_registers;
std::string m_gdb_arch;
- std::string m_gdb_feature;
std::map<offs_t, uint64_t> m_address_map;
- device_debug::breakpoint *m_triggered_breakpoint;
- device_debug::watchpoint *m_triggered_watchpoint;
+ debug_breakpoint *m_triggered_breakpoint;
+ debug_watchpoint *m_triggered_watchpoint;
std::string m_target_xml;
@@ -442,14 +832,15 @@ private:
};
//-------------------------------------------------------------------------
-int debug_gdbstub::init(const osd_options &options)
+int debug_gdbstub::init(osd_interface &osd, const osd_options &options)
{
+ m_debugger_host = options.debugger_host();
m_debugger_port = options.debugger_port();
return 0;
}
//-------------------------------------------------------------------------
-void debug_gdbstub::exit(void)
+void debug_gdbstub::exit()
{
}
@@ -460,7 +851,7 @@ void debug_gdbstub::init_debugger(running_machine &machine)
}
//-------------------------------------------------------------------------
-int debug_gdbstub::readchar(void)
+int debug_gdbstub::readchar()
{
// NOTE: we don't use m_socket.getc() because it does not work with
// sockets (it assumes seeking is possible).
@@ -480,11 +871,11 @@ int debug_gdbstub::readchar(void)
}
//-------------------------------------------------------------------------
-static std::string escape_packet(const std::string src)
+static std::string escape_packet(std::string_view src)
{
std::string result;
result.reserve(src.length());
- for ( char ch: src )
+ for ( char ch : src )
{
if ( ch == '#' || ch == '$' || ch == '}' )
{
@@ -497,7 +888,7 @@ static std::string escape_packet(const std::string src)
}
//-------------------------------------------------------------------------
-void debug_gdbstub::generate_target_xml(void)
+void debug_gdbstub::generate_target_xml()
{
// Note: we do not attempt to replicate the regnum values from old
// GDB clients that did not support target.xml.
@@ -505,11 +896,23 @@ void debug_gdbstub::generate_target_xml(void)
target_xml += "<?xml version=\"1.0\"?>\n";
target_xml += "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">\n";
target_xml += "<target version=\"1.0\">\n";
- target_xml += string_format("<architecture>%s</architecture>\n", m_gdb_arch.c_str());
- target_xml += string_format(" <feature name=\"%s\">\n", m_gdb_feature.c_str());
+ target_xml += string_format("<architecture>%s</architecture>\n", m_gdb_arch);
+ std::string feature_name;
for ( const auto &reg: m_gdb_registers )
- target_xml += string_format(" <reg name=\"%s\" bitsize=\"%d\" type=\"%s\"/>\n", reg.gdb_name.c_str(), reg.gdb_bitsize, gdb_register_type_str[reg.gdb_type]);
- target_xml += " </feature>\n";
+ {
+ if (feature_name != reg.gdb_feature_name)
+ {
+ if (!feature_name.empty())
+ target_xml += " </feature>\n";
+
+ feature_name = reg.gdb_feature_name;
+ target_xml += string_format(" <feature name=\"%s\">\n", feature_name);
+ }
+
+ target_xml += string_format(" <reg name=\"%s\" bitsize=\"%d\" type=\"%s\"/>\n", reg.gdb_name, reg.gdb_bitsize, gdb_register_type_str[reg.gdb_type]);
+ }
+ if (!feature_name.empty())
+ target_xml += " </feature>\n";
target_xml += "</target>\n";
m_target_xml = escape_packet(target_xml);
}
@@ -522,13 +925,18 @@ void debug_gdbstub::wait_for_debugger(device_t &device, bool firststop)
if ( firststop && !m_initialized )
{
- m_maincpu = m_machine->root_device().subdevice(":maincpu");
+ // find the "main" CPU, which is the first CPU (gdbstub doesn't have any notion of switching CPUs)
+ m_maincpu = device_interface_enumerator<cpu_device>(m_machine->root_device()).first();
+ if (!m_maincpu)
+ fatalerror("gdbstub: cannot find any CPUs\n");
+
const char *cpuname = m_maincpu->shortname();
auto it = gdb_register_maps.find(cpuname);
if ( it == gdb_register_maps.end() )
fatalerror("gdbstub: cpuname %s not found in gdb stub descriptions\n", cpuname);
- m_state = &m_maincpu->state();
+ m_maincpu->interface(m_state);
+ assert(m_state != nullptr);
m_memory = &m_maincpu->memory();
m_address_space = &m_memory->space(AS_PROGRAM);
m_debugger_cpu = &m_machine->debugger().cpu();
@@ -544,59 +952,60 @@ void debug_gdbstub::wait_for_debugger(device_t &device, bool firststop)
uint64_t datamask = entry->datamask();
int index = entry->index();
const std::string &format_string = entry->format_string();
- osd_printf_info("[%3d] datasize %d mask %016" PRIx64 " [%s] [%s]\n", index, datasize, datamask, symbol, format_string.c_str());
+ osd_printf_info("[%3d] datasize %d mask %016" PRIx64 " [%s] [%s]\n", index, datasize, datamask, symbol, format_string);
}
#endif
const gdb_register_map &register_map = it->second;
m_gdb_arch = register_map.arch;
- m_gdb_feature = register_map.feature;
int cur_gdb_regnum = 0;
- for ( const auto &reg: register_map.registers )
- {
- bool added = false;
- for ( const auto &entry: m_state->state_entries() )
+ for ( const auto &feature: register_map.features )
+ for ( const auto &reg: feature.registers )
{
- const char *symbol = entry->symbol();
- if ( strcmp(symbol, reg.state_name) == 0 )
+ bool added = false;
+ for ( const auto &entry: m_state->state_entries() )
{
- gdb_register new_reg;
- new_reg.gdb_name = reg.gdb_name;
- new_reg.gdb_regnum = cur_gdb_regnum;
- new_reg.gdb_type = reg.gdb_type;
- if ( reg.override_bitsize != -1 )
- new_reg.gdb_bitsize = reg.override_bitsize;
- else
- new_reg.gdb_bitsize = entry->datasize() * 8;
- new_reg.state_index = entry->index();
- m_gdb_registers.push_back(std::move(new_reg));
- if ( reg.stop_packet )
- m_stop_reply_registers.insert(cur_gdb_regnum);
- added = true;
- cur_gdb_regnum++;
- break;
+ const char *symbol = entry->symbol();
+ if ( strcmp(symbol, reg.state_name) == 0 )
+ {
+ gdb_register new_reg;
+ new_reg.gdb_feature_name = feature.feature_name;
+ new_reg.gdb_name = reg.gdb_name;
+ new_reg.gdb_regnum = cur_gdb_regnum;
+ new_reg.gdb_type = reg.gdb_type;
+ if ( reg.override_bitsize != -1 )
+ new_reg.gdb_bitsize = reg.override_bitsize;
+ else
+ new_reg.gdb_bitsize = entry->datasize() * 8;
+ new_reg.state_index = entry->index();
+ m_gdb_registers.push_back(std::move(new_reg));
+ if ( reg.stop_packet )
+ m_stop_reply_registers.insert(cur_gdb_regnum);
+ added = true;
+ cur_gdb_regnum++;
+ break;
+ }
}
+ if ( !added )
+ osd_printf_info("gdbstub: could not find register [%s]\n", reg.gdb_name);
}
- if ( !added )
- osd_printf_info("gdbstub: could not find register [%s]\n", reg.gdb_name);
- }
#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.c_str());
+ 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);
- osd_file::error filerr = m_socket.open(socket_name.c_str());
- if ( filerr != osd_file::error::NONE )
- fatalerror("gdbstub: failed to start listening on port %d\n", m_debugger_port);
- osd_printf_info("gdbstub: listening on port %d\n", m_debugger_port);
+ std::string socket_name = string_format("socket.%s:%d", m_debugger_host, m_debugger_port);
+ std::error_condition const filerr = m_socket.open(socket_name);
+ if ( filerr )
+ fatalerror("gdbstub: failed to start listening on address %s port %d\n", m_debugger_host, m_debugger_port);
+ osd_printf_info("gdbstub: listening on address %s port %d\n", m_debugger_host, m_debugger_port);
m_initialized = true;
}
else
{
- device_debug *debug = m_debugger_cpu->get_visible_cpu()->debug();
+ device_debug *debug = m_debugger_console->get_visible_cpu()->debug();
m_triggered_watchpoint = debug->triggered_watchpoint();
m_triggered_breakpoint = debug->triggered_breakpoint();
if ( m_send_stop_packet )
@@ -622,7 +1031,7 @@ void debug_gdbstub::wait_for_debugger(device_t &device, bool firststop)
}
//-------------------------------------------------------------------------
-void debug_gdbstub::debugger_update(void)
+void debug_gdbstub::debugger_update()
{
while ( true )
{
@@ -634,28 +1043,26 @@ void debug_gdbstub::debugger_update(void)
}
//-------------------------------------------------------------------------
-void debug_gdbstub::send_nack(void)
+void debug_gdbstub::send_nack()
{
- m_socket.puts("-");
+ m_socket.write("-", 1);
}
//-------------------------------------------------------------------------
-void debug_gdbstub::send_ack(void)
+void debug_gdbstub::send_ack()
{
- m_socket.puts("+");
+ m_socket.write("+", 1);
}
//-------------------------------------------------------------------------
-void debug_gdbstub::send_reply(const char *str)
+void debug_gdbstub::send_reply(std::string_view str)
{
- size_t length = strlen(str);
-
uint8_t checksum = 0;
- for ( size_t i = 0; i < length; i++ )
- checksum += str[i];
+ for ( char ch : str )
+ checksum += ch;
std::string reply = string_format("$%s#%02x", str, checksum);
- m_socket.puts(reply.c_str());
+ m_socket.write(reply.c_str(), reply.length());
}
@@ -683,7 +1090,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_c(const char *buf)
if ( *buf != '\0' )
return REPLY_UNSUPPORTED;
- m_debugger_cpu->get_visible_cpu()->debug()->go();
+ m_debugger_console->get_visible_cpu()->debug()->go();
m_send_stop_packet = true;
return REPLY_NONE;
}
@@ -696,7 +1103,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_D(const char *buf)
if ( *buf != '\0' )
return REPLY_UNSUPPORTED;
- m_debugger_cpu->get_visible_cpu()->debug()->go();
+ m_debugger_console->get_visible_cpu()->debug()->go();
m_dettached = true;
return REPLY_OK;
@@ -713,7 +1120,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_g(const char *buf)
std::string reply;
for ( const auto &reg: m_gdb_registers )
reply += get_register_string(reg.gdb_regnum);
- send_reply(reply.c_str());
+ send_reply(reply);
return REPLY_NONE;
}
@@ -752,7 +1159,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_H(const char *buf)
debug_gdbstub::cmd_reply debug_gdbstub::handle_k(const char *buf)
{
m_machine->schedule_exit();
- m_debugger_cpu->get_visible_cpu()->debug()->go();
+ m_debugger_console->get_visible_cpu()->debug()->go();
m_dettached = true;
m_socket.close();
return REPLY_NONE;
@@ -768,7 +1175,8 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_m(const char *buf)
return REPLY_ENN;
offs_t offset = address;
- if ( !m_memory->translate(m_address_space->spacenum(), TRANSLATE_READ_DEBUG, offset) )
+ address_space *tspace;
+ if ( !m_memory->translate(m_address_space->spacenum(), device_memory_interface::TR_READ, offset, tspace) )
return REPLY_ENN;
// Disable side effects while reading memory.
@@ -778,10 +1186,10 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_m(const char *buf)
reply.reserve(length * 2);
for ( int i = 0; i < length; i++ )
{
- uint8_t value = m_address_space->read_byte(offset + i);
+ uint8_t value = tspace->read_byte(offset + i);
reply += string_format("%02x", value);
}
- send_reply(reply.c_str());
+ send_reply(reply);
return REPLY_NONE;
}
@@ -813,7 +1221,8 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_M(const char *buf)
return REPLY_ENN;
offs_t offset = address;
- if ( !m_memory->translate(m_address_space->spacenum(), TRANSLATE_READ_DEBUG, offset) )
+ address_space *tspace;
+ if ( !m_memory->translate(m_address_space->spacenum(), device_memory_interface::TR_READ, offset, tspace) )
return REPLY_ENN;
std::vector<uint8_t> data;
@@ -821,7 +1230,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_M(const char *buf)
return REPLY_ENN;
for ( int i = 0; i < length; i++ )
- m_address_space->write_byte(offset + i, data[i]);
+ tspace->write_byte(offset + i, data[i]);
return REPLY_OK;
}
@@ -836,7 +1245,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_p(const char *buf)
if ( sscanf(buf, "%x", &gdb_regnum) != 1 || gdb_regnum >= m_gdb_registers.size() )
return REPLY_ENN;
std::string reply = get_register_string(gdb_regnum);
- send_reply(reply.c_str());
+ send_reply(reply);
return REPLY_NONE;
}
@@ -888,7 +1297,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_q(const char *buf)
if ( !hex_decode(&data, buf, strlen(buf) / 2) )
return REPLY_ENN;
std::string command(data.begin(), data.end());
- text_buffer *textbuf = m_debugger_console->get_console_textbuf();
+ text_buffer &textbuf = m_debugger_console->get_console_textbuf();
text_buffer_clear(textbuf);
m_debugger_console->execute_command(command, false);
uint32_t nlines = text_buffer_num_lines(textbuf);
@@ -903,7 +1312,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_q(const char *buf)
reply += string_format("%02x", *line++);
reply += "0A";
}
- send_reply(reply.c_str());
+ send_reply(reply);
return REPLY_NONE;
}
@@ -920,7 +1329,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_q(const char *buf)
{
std::string reply = string_format("PacketSize=%x", MAX_PACKET_SIZE);
reply += ";qXfer:features:read+";
- send_reply(reply.c_str());
+ send_reply(reply);
return REPLY_NONE;
}
else if ( name == "Xfer" )
@@ -941,7 +1350,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_q(const char *buf)
else
reply += 'l';
reply += m_target_xml.substr(offset, length);
- send_reply(reply.c_str());
+ send_reply(reply);
m_target_xml_sent = true;
return REPLY_NONE;
}
@@ -969,15 +1378,26 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_s(const char *buf)
if ( *buf != '\0' )
return REPLY_UNSUPPORTED;
- m_debugger_cpu->get_visible_cpu()->debug()->single_step();
+ m_debugger_console->get_visible_cpu()->debug()->single_step();
m_send_stop_packet = true;
return REPLY_NONE;
}
//-------------------------------------------------------------------------
+// Find out if the thread XX is alive.
+debug_gdbstub::cmd_reply debug_gdbstub::handle_T(const char *buf)
+{
+ if ( is_thread_id_ok(buf) )
+ return REPLY_OK;
+
+ // thread is dead
+ return REPLY_ENN;
+}
+
+//-------------------------------------------------------------------------
static bool remove_breakpoint(device_debug *debug, uint64_t address, int /*kind*/)
{
- const device_debug::breakpoint *bp = debug->breakpoint_find(address);
+ const debug_breakpoint *bp = debug->breakpoint_find(address);
if (bp != nullptr)
return debug->breakpoint_clear(bp->index());
return false;
@@ -1014,14 +1434,15 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_z(const char *buf)
// watchpoints
offs_t offset = address;
+ address_space *tspace;
if ( type == 2 || type == 3 || type == 4 )
{
- if ( !m_memory->translate(m_address_space->spacenum(), TRANSLATE_READ_DEBUG, offset) )
+ if ( !m_memory->translate(m_address_space->spacenum(), device_memory_interface::TR_READ, offset, tspace) )
return REPLY_ENN;
m_address_map.erase(offset);
}
- device_debug *debug = m_debugger_cpu->get_visible_cpu()->debug();
+ device_debug *debug = m_debugger_console->get_visible_cpu()->debug();
switch ( type )
{
// Note: software and hardware breakpoints are treated both the
@@ -1055,14 +1476,15 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_Z(const char *buf)
// watchpoints
offs_t offset = address;
+ address_space *tspace;
if ( type == 2 || type == 3 || type == 4 )
{
- if ( !m_memory->translate(m_address_space->spacenum(), TRANSLATE_READ_DEBUG, offset) )
+ if ( !m_memory->translate(m_address_space->spacenum(), device_memory_interface::TR_READ, offset, tspace) )
return REPLY_ENN;
m_address_map[offset] = address;
}
- device_debug *debug = m_debugger_cpu->get_visible_cpu()->debug();
+ device_debug *debug = m_debugger_console->get_visible_cpu()->debug();
switch ( type )
{
// Note: software and hardware breakpoints are treated both the
@@ -1073,15 +1495,15 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_Z(const char *buf)
return REPLY_OK;
case 2:
// write watchpoint
- debug->watchpoint_set(*m_address_space, read_or_write::WRITE, offset, kind, nullptr, nullptr);
+ debug->watchpoint_set(*m_address_space, read_or_write::WRITE, offset, kind);
return REPLY_OK;
case 3:
// read watchpoint
- debug->watchpoint_set(*m_address_space, read_or_write::READ, offset, kind, nullptr, nullptr);
+ debug->watchpoint_set(*m_address_space, read_or_write::READ, offset, kind);
return REPLY_OK;
case 4:
// access watchpoint
- debug->watchpoint_set(*m_address_space, read_or_write::READWRITE, offset, kind, nullptr, nullptr);
+ debug->watchpoint_set(*m_address_space, read_or_write::READWRITE, offset, kind);
return REPLY_OK;
}
@@ -1090,7 +1512,7 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_Z(const char *buf)
//-------------------------------------------------------------------------
-void debug_gdbstub::send_stop_packet(void)
+void debug_gdbstub::send_stop_packet()
{
int signal = 5; // GDB_SIGNAL_TRAP
std::string reply = string_format("T%02x", signal);
@@ -1115,11 +1537,11 @@ void debug_gdbstub::send_stop_packet(void)
if ( m_target_xml_sent )
for ( const auto &gdb_regnum: m_stop_reply_registers )
reply += string_format("%02x:%s;", gdb_regnum, get_register_string(gdb_regnum));
- send_reply(reply.c_str());
+ send_reply(reply);
}
//-------------------------------------------------------------------------
-void debug_gdbstub::handle_packet(void)
+void debug_gdbstub::handle_packet()
{
// For any command not supported by the stub, an empty response
// (‘$#00’) should be returned. That way it is possible to extend
@@ -1144,6 +1566,7 @@ void debug_gdbstub::handle_packet(void)
case 'P': reply = handle_P(buf); break;
case 'q': reply = handle_q(buf); break;
case 's': reply = handle_s(buf); break;
+ case 'T': reply = handle_T(buf); break;
case 'z': reply = handle_z(buf); break;
case 'Z': reply = handle_Z(buf); break;
}
@@ -1156,22 +1579,6 @@ void debug_gdbstub::handle_packet(void)
}
//-------------------------------------------------------------------------
-#define BYTESWAP_64(x) ((((x) << 56) & 0xFF00000000000000) \
- | (((x) << 40) & 0x00FF000000000000) \
- | (((x) << 24) & 0x0000FF0000000000) \
- | (((x) << 8) & 0x000000FF00000000) \
- | (((x) >> 8) & 0x00000000FF000000) \
- | (((x) >> 24) & 0x0000000000FF0000) \
- | (((x) >> 40) & 0x000000000000FF00) \
- | (((x) >> 56) & 0x00000000000000FF))
-#define BYTESWAP_32(x) ((((x) << 24) & 0xFF000000) \
- | (((x) << 8) & 0x00FF0000) \
- | (((x) >> 8) & 0x0000FF00) \
- | (((x) >> 24) & 0x000000FF))
-#define BYTESWAP_16(x) ((((x) << 8) & 0xFF00) \
- | (((x) >> 8) & 0x00FF))
-
-//-------------------------------------------------------------------------
std::string debug_gdbstub::get_register_string(int gdb_regnum)
{
const gdb_register &reg = m_gdb_registers[gdb_regnum];
@@ -1184,9 +1591,9 @@ std::string debug_gdbstub::get_register_string(int gdb_regnum)
value &= (1ULL << reg.gdb_bitsize) - 1;
if ( !m_is_be )
{
- value = (reg.gdb_bitsize == 64) ? BYTESWAP_64(value)
- : (reg.gdb_bitsize == 32) ? BYTESWAP_32(value)
- : (reg.gdb_bitsize == 16) ? BYTESWAP_16(value)
+ value = (reg.gdb_bitsize == 64) ? swapendian_int64(value)
+ : (reg.gdb_bitsize == 32) ? swapendian_int32(value)
+ : (reg.gdb_bitsize == 16) ? swapendian_int16(value)
: value;
}
return string_format(fmt, value);
@@ -1205,9 +1612,9 @@ bool debug_gdbstub::parse_register_string(uint64_t *pvalue, const char *buf, int
return false;
if ( !m_is_be )
{
- value = (reg.gdb_bitsize == 64) ? BYTESWAP_64(value)
- : (reg.gdb_bitsize == 32) ? BYTESWAP_32(value)
- : (reg.gdb_bitsize == 16) ? BYTESWAP_16(value)
+ value = (reg.gdb_bitsize == 64) ? swapendian_int64(value)
+ : (reg.gdb_bitsize == 32) ? swapendian_int32(value)
+ : (reg.gdb_bitsize == 16) ? swapendian_int16(value)
: value;
}
*pvalue = value;
@@ -1304,5 +1711,9 @@ void debug_gdbstub::handle_character(char ch)
}
}
+} // anonymous namespace
+
+} // namespace osd
+
//-------------------------------------------------------------------------
-MODULE_DEFINITION(DEBUG_GDBSTUB, debug_gdbstub)
+MODULE_DEFINITION(DEBUG_GDBSTUB, osd::debug_gdbstub)