diff options
Diffstat (limited to 'src/osd/modules/debugger/debuggdbstub.cpp')
-rw-r--r-- | src/osd/modules/debugger/debuggdbstub.cpp | 204 |
1 files changed, 141 insertions, 63 deletions
diff --git a/src/osd/modules/debugger/debuggdbstub.cpp b/src/osd/modules/debugger/debuggdbstub.cpp index eaeb1df4cca..e5092c71548 100644 --- a/src/osd/modules/debugger/debuggdbstub.cpp +++ b/src/osd/modules/debugger/debuggdbstub.cpp @@ -7,17 +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 "fileio.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 @@ -245,9 +254,9 @@ static const gdb_register_map gdb_register_map_m68020pmmu = { "A4", "a4", false, TYPE_INT }, { "A5", "a5", false, TYPE_INT }, { "A6", "fp", true, TYPE_INT }, - { "A7", "sp", true, TYPE_INT }, + { "SP", "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 }, + { "CURPC","pc", true, TYPE_CODE_POINTER }, } }; @@ -272,9 +281,9 @@ static const gdb_register_map gdb_register_map_m68000 = { "A4", "a4", false, TYPE_INT }, { "A5", "a5", false, TYPE_INT }, { "A6", "fp", true, TYPE_INT }, - { "A7", "sp", true, TYPE_INT }, + { "SP", "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 }, + { "CURPC","pc", true, TYPE_CODE_POINTER }, //NOTE m68-elf-gdb complains about fpcontrol register not present but 68000 doesn't have floating point so... } }; @@ -401,6 +410,65 @@ static const gdb_register_map gdb_register_map_score7 = } }; + +//------------------------------------------------------------------------- +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 std::map<std::string, const gdb_register_map &> gdb_register_maps = { { "i486", gdb_register_map_i486 }, @@ -410,10 +478,17 @@ static const std::map<std::string, const gdb_register_map &> gdb_register_maps = { "m68020pmmu", gdb_register_map_m68020pmmu }, { "m68000", gdb_register_map_m68000 }, { "z80", gdb_register_map_z80 }, + { "z84c015", gdb_register_map_z80 }, { "m6502", gdb_register_map_m6502 }, - { "n2a03", gdb_register_map_m6502 }, + { "m6507", gdb_register_map_m6502 }, + { "m6510", gdb_register_map_m6502 }, + { "m65c02", gdb_register_map_m6502 }, + { "m65ce02", gdb_register_map_m6502 }, + { "rp2a03", gdb_register_map_m6502 }, + { "w65c02s", gdb_register_map_m6502 }, { "m6809", gdb_register_map_m6809 }, { "score7", gdb_register_map_score7 }, + { "nios2", gdb_register_map_nios2 }, }; //------------------------------------------------------------------------- @@ -450,7 +525,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; @@ -495,6 +570,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); @@ -512,7 +588,7 @@ public: int readchar(); - void send_reply(const char *str); + void send_reply(std::string_view str); void send_stop_packet(); private: @@ -563,7 +639,7 @@ private: }; //------------------------------------------------------------------------- -int debug_gdbstub::init(const osd_options &options) +int debug_gdbstub::init(osd_interface &osd, const osd_options &options) { m_debugger_port = options.debugger_port(); return 0; @@ -601,11 +677,11 @@ int debug_gdbstub::readchar() } //------------------------------------------------------------------------- -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 == '}' ) { @@ -626,10 +702,10 @@ void debug_gdbstub::generate_target_xml() 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); + target_xml += string_format(" <feature name=\"%s\">\n", m_gdb_feature); 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 += string_format(" <reg name=\"%s\" bitsize=\"%d\" type=\"%s\"/>\n", reg.gdb_name, reg.gdb_bitsize, gdb_register_type_str[reg.gdb_type]); target_xml += " </feature>\n"; target_xml += "</target>\n"; m_target_xml = escape_packet(target_xml); @@ -644,7 +720,7 @@ void debug_gdbstub::wait_for_debugger(device_t &device, bool firststop) if ( firststop && !m_initialized ) { // find the "main" CPU, which is the first CPU (gdbstub doesn't have any notion of switching CPUs) - m_maincpu = device_type_enumerator<cpu_device>(m_machine->root_device()).first(); + m_maincpu = device_interface_enumerator<cpu_device>(m_machine->root_device()).first(); if (!m_maincpu) fatalerror("gdbstub: cannot find any CPUs\n"); @@ -762,26 +838,24 @@ void debug_gdbstub::debugger_update() //------------------------------------------------------------------------- void debug_gdbstub::send_nack() { - m_socket.puts("-"); + m_socket.write("-", 1); } //------------------------------------------------------------------------- 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); + m_socket.write(reply.c_str(), reply.length()); } @@ -839,7 +913,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; } @@ -894,7 +968,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. @@ -904,10 +979,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; } @@ -939,7 +1014,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; @@ -947,7 +1023,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; } @@ -962,7 +1038,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; } @@ -1029,7 +1105,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; } @@ -1046,7 +1122,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" ) @@ -1067,7 +1143,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; } @@ -1101,6 +1177,17 @@ debug_gdbstub::cmd_reply debug_gdbstub::handle_s(const char *buf) } //------------------------------------------------------------------------- +// 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 debug_breakpoint *bp = debug->breakpoint_find(address); @@ -1140,9 +1227,10 @@ 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); } @@ -1181,9 +1269,10 @@ 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; } @@ -1199,15 +1288,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; } @@ -1241,7 +1330,7 @@ void debug_gdbstub::send_stop_packet() 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); } //------------------------------------------------------------------------- @@ -1270,6 +1359,7 @@ void debug_gdbstub::handle_packet() 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; } @@ -1282,22 +1372,6 @@ void debug_gdbstub::handle_packet() } //------------------------------------------------------------------------- -#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]; @@ -1310,9 +1384,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); @@ -1331,9 +1405,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; @@ -1430,5 +1504,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) |