diff options
Diffstat (limited to 'src/osd/modules/debugger/debuggdbstub.cpp')
-rw-r--r-- | src/osd/modules/debugger/debuggdbstub.cpp | 1021 |
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 ®: 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 ®ister_map = it->second; m_gdb_arch = register_map.arch; - m_gdb_feature = register_map.feature; int cur_gdb_regnum = 0; - for ( const auto ®: register_map.registers ) - { - bool added = false; - for ( const auto &entry: m_state->state_entries() ) + for ( const auto &feature: register_map.features ) + for ( const auto ®: 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 ®: 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 ®: 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 ® = 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) |