aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2016-03-09 10:31:51 -0800
committerTim Newsome <tim@sifive.com>2016-05-23 12:12:09 -0700
commit38b8c095df4555b618bd269e3a53817c91dc893d (patch)
tree47331ffd7595637c060e9dbd1a7f690fe2cbe640
parent64f57718a840888fd2ba944316576c5a35f7a7a8 (diff)
downloadspike-38b8c095df4555b618bd269e3a53817c91dc893d.zip
spike-38b8c095df4555b618bd269e3a53817c91dc893d.tar.gz
spike-38b8c095df4555b618bd269e3a53817c91dc893d.tar.bz2
Implement binary memory write.
Also set the simulation running again when gdb disconnects.
-rw-r--r--riscv/gdbserver.cc107
-rw-r--r--riscv/gdbserver.h10
2 files changed, 86 insertions, 31 deletions
diff --git a/riscv/gdbserver.cc b/riscv/gdbserver.cc
index a3663c9..d188f92 100644
--- a/riscv/gdbserver.cc
+++ b/riscv/gdbserver.cc
@@ -145,6 +145,7 @@ void gdbserver_t::accept()
int oldopts = fcntl(client_fd, F_GETFL, 0);
fcntl(client_fd, F_SETFL, oldopts | O_NONBLOCK);
expect_ack = false;
+ extended_mode = false;
// gdb wants the core to be halted when it attaches.
processor_t *p = sim->get_core(0);
@@ -170,11 +171,12 @@ void gdbserver_t::read()
} else if (bytes == 0) {
// The remote disconnected.
client_fd = 0;
+ processor_t *p = sim->get_core(0);
+ p->set_halted(false);
recv_buf.reset();
send_buf.reset();
} else {
recv_buf.data_added(bytes);
- printf("Read %d bytes.\n", bytes);
}
}
@@ -251,7 +253,6 @@ void gdbserver_t::process_requests()
uint8_t b = recv_buf[i];
if (packet.empty() && expect_ack && b == '+') {
- fprintf(stderr, "Received ack\n");
recv_buf.consume(1);
break;
}
@@ -287,8 +288,6 @@ void gdbserver_t::process_requests()
// There's a partial packet in the buffer. Wait until we get more data to
// process it.
if (packet.size()) {
- fprintf(stderr, "Partial packet: ");
- print_packet(packet);
break;
}
}
@@ -299,7 +298,7 @@ void gdbserver_t::handle_halt_reason(const std::vector<uint8_t> &packet)
send_packet("S00");
}
-void gdbserver_t::handle_read_general_registers(const std::vector<uint8_t> &packet)
+void gdbserver_t::handle_general_registers_read(const std::vector<uint8_t> &packet)
{
// Register order that gdb expects is:
// "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
@@ -345,7 +344,7 @@ uint64_t consume_hex_number(std::vector<uint8_t>::const_iterator &iter,
return value;
}
-void gdbserver_t::handle_read_register(const std::vector<uint8_t> &packet)
+void gdbserver_t::handle_register_read(const std::vector<uint8_t> &packet)
{
// p n
@@ -380,17 +379,15 @@ void gdbserver_t::handle_read_register(const std::vector<uint8_t> &packet)
expect_ack = true;
}
-void gdbserver_t::handle_read_memory(const std::vector<uint8_t> &packet)
+void gdbserver_t::handle_memory_read(const std::vector<uint8_t> &packet)
{
// m addr,length
std::vector<uint8_t>::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
@@ -407,6 +404,64 @@ void gdbserver_t::handle_read_memory(const std::vector<uint8_t> &packet)
send_running_checksum();
}
+void gdbserver_t::handle_memory_binary_write(const std::vector<uint8_t> &packet)
+{
+ // X addr,length:XX...
+ std::vector<uint8_t>::const_iterator iter = packet.begin() + 2;
+ reg_t address = consume_hex_number(iter, packet.end());
+ if (*iter != ',')
+ return send_packet("E16"); // EINVAL
+ iter++;
+ reg_t length = consume_hex_number(iter, packet.end());
+ if (*iter != ':')
+ return send_packet("E16"); // EINVAL
+ iter++;
+
+ processor_t *p = sim->get_core(0);
+ mmu_t* mmu = sim->debug_mmu;
+ for (unsigned int i = 0; i < length; i++) {
+ if (iter == packet.end()) {
+ return send_packet("E16"); // EINVAL
+ }
+ mmu->store_uint8(address + i, *iter);
+ iter++;
+ }
+ if (*iter != '#')
+ return send_packet("E4b"); // EOVERFLOW
+
+ send_packet("OK");
+}
+
+void gdbserver_t::handle_continue(const std::vector<uint8_t> &packet)
+{
+ // c [addr]
+ processor_t *p = sim->get_core(0);
+ if (packet[2] != '#') {
+ std::vector<uint8_t>::const_iterator iter = packet.begin() + 2;
+ p->state.pc = consume_hex_number(iter, packet.end());
+ if (*iter != '#')
+ return send_packet("E16"); // EINVAL
+ }
+
+ p->set_halted(false);
+}
+
+void gdbserver_t::handle_kill(const std::vector<uint8_t> &packet)
+{
+ // k
+ // The exact effect of this packet is not specified.
+ // Looks like OpenOCD disconnects?
+ // TODO
+}
+
+void gdbserver_t::handle_extended(const std::vector<uint8_t> &packet)
+{
+ // Enable extended mode. In extended mode, the remote server is made
+ // persistent. The ‘R’ packet is used to restart the program being debugged.
+ send_packet("OK");
+ extended_mode = true;
+}
+
void gdbserver_t::handle_packet(const std::vector<uint8_t> &packet)
{
if (compute_checksum(packet) != extract_checksum(packet)) {
@@ -422,19 +477,29 @@ void gdbserver_t::handle_packet(const std::vector<uint8_t> &packet)
send("+");
switch (packet[1]) {
+ case '!':
+ return handle_extended(packet);
case '?':
return handle_halt_reason(packet);
case 'g':
- return handle_read_general_registers(packet);
+ return handle_general_registers_read(packet);
+ case 'k':
+ return handle_kill(packet);
case 'm':
- return handle_read_memory(packet);
+ return handle_memory_read(packet);
+// case 'M':
+// return handle_memory_write(packet);
+ case 'X':
+ return handle_memory_binary_write(packet);
case 'p':
- return handle_read_register(packet);
+ return handle_register_read(packet);
case 'c':
return handle_continue(packet);
}
// Not supported.
+ fprintf(stderr, "** Unsupported packet: ");
+ print_packet(packet);
send_packet("");
}
@@ -445,20 +510,6 @@ void gdbserver_t::handle_interrupt()
send_packet("S02"); // Pretend program received SIGINT.
}
-void gdbserver_t::handle_continue(const std::vector<uint8_t> &packet)
-{
- // c [addr]
- processor_t *p = sim->get_core(0);
- if (packet[2] != '#') {
- std::vector<uint8_t>::const_iterator iter = packet.begin() + 2;
- p->state.pc = consume_hex_number(iter, packet.end());
- if (*iter != '#')
- return send_packet("E16"); // EINVAL
- }
-
- p->set_halted(false);
-}
-
void gdbserver_t::handle()
{
if (client_fd > 0) {
@@ -484,7 +535,7 @@ void gdbserver_t::send(uint64_t value)
{
char buffer[3];
for (unsigned int i = 0; i < 8; i++) {
- sprintf(buffer, "%02x", value & 0xff);
+ sprintf(buffer, "%02x", (int) (value & 0xff));
send(buffer);
value >>= 8;
}
@@ -494,7 +545,7 @@ void gdbserver_t::send(uint32_t value)
{
char buffer[3];
for (unsigned int i = 0; i < 4; i++) {
- sprintf(buffer, "%02x", value & 0xff);
+ sprintf(buffer, "%02x", (int) (value & 0xff));
send(buffer);
value >>= 8;
}
diff --git a/riscv/gdbserver.h b/riscv/gdbserver.h
index 8add2ad..4b34aef 100644
--- a/riscv/gdbserver.h
+++ b/riscv/gdbserver.h
@@ -56,10 +56,13 @@ public:
void handle_interrupt();
void handle_halt_reason(const std::vector<uint8_t> &packet);
- void handle_read_general_registers(const std::vector<uint8_t> &packet);
- void handle_read_memory(const std::vector<uint8_t> &packet);
- void handle_read_register(const std::vector<uint8_t> &packet);
+ void handle_general_registers_read(const std::vector<uint8_t> &packet);
+ void handle_memory_read(const std::vector<uint8_t> &packet);
+ void handle_memory_binary_write(const std::vector<uint8_t> &packet);
+ void handle_register_read(const std::vector<uint8_t> &packet);
void handle_continue(const std::vector<uint8_t> &packet);
+ void handle_kill(const std::vector<uint8_t> &packet);
+ void handle_extended(const std::vector<uint8_t> &packet);
private:
sim_t *sim;
@@ -69,6 +72,7 @@ private:
circular_buffer_t<uint8_t> send_buf;
bool expect_ack;
+ bool extended_mode;
// Read pending data from the client.
void read();