From d1ba8b559309c6e3dd47c18674b199bd3cf6e8d9 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 7 Mar 2016 15:44:20 -0800 Subject: [PATCH] gdb can now read spike memory. The endianness is wrong, but I think it might be that gdb doesn't have it right. Need to investigate what architecture gdb thinks it's debugging. --- riscv/gdbserver.cc | 106 +++++++++++++++++++++++++++++++++++--------- riscv/gdbserver.h | 10 ++++- riscv/processor.h | 1 + riscv/sim.h | 1 + spike_main/spike.cc | 2 +- 5 files changed, 97 insertions(+), 23 deletions(-) diff --git a/riscv/gdbserver.cc b/riscv/gdbserver.cc index e2481bc..40ee4b2 100644 --- a/riscv/gdbserver.cc +++ b/riscv/gdbserver.cc @@ -12,6 +12,8 @@ #include #include +#include "disasm.h" +#include "sim.h" #include "gdbserver.h" template @@ -82,7 +84,8 @@ void circular_buffer_t::append(const T *src, unsigned int count) // Code inspired by/copied from OpenOCD server/server.c. -gdbserver_t::gdbserver_t(uint16_t port) : +gdbserver_t::gdbserver_t(uint16_t port, sim_t *sim) : + sim(sim), client_fd(0), recv_buf(64 * 1024), send_buf(64 * 1024) { @@ -222,7 +225,7 @@ uint8_t character_hex_value(uint8_t character) return 10 + character - 'a'; if (character >= 'A' && character <= 'F') return 10 + character - 'A'; - return 0; + return 0xff; } uint8_t extract_checksum(const std::vector &packet) @@ -274,19 +277,78 @@ void gdbserver_t::process_requests() } } -void gdbserver_t::handle_set_threadid(const std::vector &packet) +void gdbserver_t::handle_halt_reason(const std::vector &packet) { - if (packet[2] == 'g' && packet[3] == '0') { - // Use thread 0 for all operations. - send("OK"); - } else { - send("$#00"); + send_packet("S00"); +} + +void gdbserver_t::handle_read_general_registers(const std::vector &packet) +{ + // Register order that gdb expects is: + // "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", + // "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", + // "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", + // "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", + // "pc", + // "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", + // "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", + // "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", + // "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", + + send("$"); + running_checksum = 0; + char buffer[17]; + processor_t *p = sim->get_core(0); + for (int r = 0; r < 32; r++) { + sprintf(buffer, "%08lx", p->state.XPR[r]); + send(buffer); } + send_running_checksum(); + expect_ack = true; } -void gdbserver_t::handle_halt_reason(const std::vector &packet) +uint64_t consume_hex_number(std::vector::const_iterator &iter, + std::vector::const_iterator end) { - send_packet("S00"); + uint64_t value = 0; + + while (iter != end) { + uint8_t c = *iter; + uint64_t c_value = character_hex_value(c); + if (c_value > 15) + break; + iter++; + value <<= 4; + value += c_value; + } + return value; +} + +void gdbserver_t::handle_read_memory(const std::vector &packet) +{ + // m addr,length + std::vector::const_iterator iter = packet.begin() + 2; + reg_t address = consume_hex_number(iter, packet.end()); + printf("address=%lx %c\n", address, *iter); + if (*iter != ',') + return send_packet("E16"); // EINVAL + iter++; + reg_t length = consume_hex_number(iter, packet.end()); + printf("length=%lx %c\n", length, *iter); + if (*iter != '#') + return send_packet("E16"); // EINVAL + + send("$"); + running_checksum = 0; + char buffer[3]; + processor_t *p = sim->get_core(0); + mmu_t* mmu = sim->debug_mmu; + + for (reg_t i = 0; i < length; i++) { + sprintf(buffer, "%02x", mmu->load_uint8(address + i)); + send(buffer); + } + send_running_checksum(); } void gdbserver_t::handle_packet(const std::vector &packet) @@ -304,10 +366,12 @@ void gdbserver_t::handle_packet(const std::vector &packet) send("+"); switch (packet[1]) { - case 'H': - return handle_set_threadid(packet); case '?': return handle_halt_reason(packet); + case 'g': + return handle_read_general_registers(packet); + case 'm': + return handle_read_memory(packet); } // Not supported. @@ -330,21 +394,23 @@ void gdbserver_t::handle() void gdbserver_t::send(const char* msg) { unsigned int length = strlen(msg); + for (const char *c = msg; *c; c++) + running_checksum += *c; send_buf.append((const uint8_t *) msg, length); } void gdbserver_t::send_packet(const char* data) { send("$"); + running_checksum = 0; send(data); - send("#"); + send_running_checksum(); + expect_ack = true; +} - uint8_t checksum = 0; - for ( ; *data; data++) { - checksum += *data; - } - char checksum_string[3]; - sprintf(checksum_string, "%02x", checksum); +void gdbserver_t::send_running_checksum() +{ + char checksum_string[4]; + sprintf(checksum_string, "#%02x", running_checksum); send(checksum_string); - expect_ack = true; } diff --git a/riscv/gdbserver.h b/riscv/gdbserver.h index 675add6..d81790d 100644 --- a/riscv/gdbserver.h +++ b/riscv/gdbserver.h @@ -3,6 +3,8 @@ #include +class sim_t; + template class circular_buffer_t { @@ -45,16 +47,18 @@ class gdbserver_t public: // Create a new server, listening for connections from localhost on the given // port. - gdbserver_t(uint16_t port); + gdbserver_t(uint16_t port, sim_t *sim); // Process all pending messages from a client. void handle(); void handle_packet(const std::vector &packet); - void handle_set_threadid(const std::vector &packet); void handle_halt_reason(const std::vector &packet); + void handle_read_general_registers(const std::vector &packet); + void handle_read_memory(const std::vector &packet); private: + sim_t *sim; int socket_fd; int client_fd; circular_buffer_t recv_buf; @@ -72,6 +76,8 @@ private: // Add the given message to send_buf. void send(const char* msg); void send_packet(const char* data); + uint8_t running_checksum; + void send_running_checksum(); }; #endif diff --git a/riscv/processor.h b/riscv/processor.h index ccf72ef..3adf990 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -136,6 +136,7 @@ private: friend class mmu_t; friend class rtc_t; friend class extension_t; + friend class gdbserver_t; void parse_isa_string(const char* isa); void build_opcode_map(); diff --git a/riscv/sim.h b/riscv/sim.h index cac1daf..7ee4020 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -92,6 +92,7 @@ private: friend class htif_isasim_t; friend class processor_t; friend class mmu_t; + friend class gdbserver_t; }; extern volatile bool ctrlc_pressed; diff --git a/spike_main/spike.cc b/spike_main/spike.cc index b7748d6..b0a9a3e 100644 --- a/spike_main/spike.cc +++ b/spike_main/spike.cc @@ -74,7 +74,7 @@ int main(int argc, char** argv) auto argv1 = parser.parse(argv); std::vector htif_args(argv1, (const char*const*)argv + argc); sim_t s(isa, nprocs, mem_mb, htif_args); - gdbserver_t gdbserver(9824); + gdbserver_t gdbserver(9824, &s); s.set_gdbserver(&gdbserver); if (dump_config_string) { -- 2.30.2