Now you can halt/continue from gdb.
authorTim Newsome <tim@sifive.com>
Wed, 9 Mar 2016 05:56:31 +0000 (21:56 -0800)
committerTim Newsome <tim@sifive.com>
Mon, 23 May 2016 19:12:09 +0000 (12:12 -0700)
riscv/execute.cc
riscv/gdbserver.cc
riscv/gdbserver.h
riscv/processor.cc
riscv/processor.h

index 5c3fdf7991552d1bff8a9c42425dff52d16f5eb4..45205b3d2ca1681f30bcc8740e8590356969d390 100644 (file)
@@ -53,7 +53,9 @@ static reg_t execute_insn(processor_t* p, reg_t pc, insn_fetch_t fetch)
 // fetch/decode/execute loop
 void processor_t::step(size_t n)
 {
-  while (run && n > 0) {
+  // TODO: We should really not call this function at all when halted, to avoid
+  // burning CPU.
+  while (run && !halted && n > 0) {
     size_t instret = 0;
     reg_t pc = state.pc;
     mmu_t* _mmu = mmu;
index fe553dc93888d603ec9c9e78740ac921942d9902..a3663c9ac6e108fe0b956b263fa34f0a327eb9bf 100644 (file)
@@ -145,6 +145,10 @@ void gdbserver_t::accept()
     int oldopts = fcntl(client_fd, F_GETFL, 0);
     fcntl(client_fd, F_SETFL, oldopts | O_NONBLOCK);
     expect_ack = false;
+
+    // gdb wants the core to be halted when it attaches.
+    processor_t *p = sim->get_core(0);
+    p->set_halted(true);
   }
 }
 
@@ -170,6 +174,7 @@ void gdbserver_t::read()
     send_buf.reset();
   } else {
     recv_buf.data_added(bytes);
+    printf("Read %d bytes.\n", bytes);
   }
 }
 
@@ -202,7 +207,10 @@ void gdbserver_t::write()
 void print_packet(const std::vector<uint8_t> &packet)
 {
   for (uint8_t c : packet) {
-    fprintf(stderr, "%c", c);
+    if (c >= ' ' and c <= '~')
+      fprintf(stderr, "%c", c);
+    else
+      fprintf(stderr, "\\x%x", c);
   }
   fprintf(stderr, "\n");
 }
@@ -248,6 +256,13 @@ void gdbserver_t::process_requests()
         break;
       }
 
+      if (packet.empty() && b == 3) {
+        fprintf(stderr, "Received interrupt\n");
+        recv_buf.consume(1);
+        handle_interrupt();
+        break;
+      }
+
       if (b == '$') {
         // Start of new packet.
         if (!packet.empty()) {
@@ -271,8 +286,11 @@ 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())
+    if (packet.size()) {
+      fprintf(stderr, "Partial packet: ");
+      print_packet(packet);
       break;
+    }
   }
 }
 
@@ -412,12 +430,35 @@ void gdbserver_t::handle_packet(const std::vector<uint8_t> &packet)
       return handle_read_memory(packet);
     case 'p':
       return handle_read_register(packet);
+    case 'c':
+      return handle_continue(packet);
   }
 
   // Not supported.
   send_packet("");
 }
 
+void gdbserver_t::handle_interrupt()
+{
+  processor_t *p = sim->get_core(0);
+  p->set_halted(true);
+  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) {
index 58bebf5b4428f06c15b06d3beccf6f267c7a66d1..8add2ad802dec4c5790547c8b2ba7aadf8e4499d 100644 (file)
@@ -52,11 +52,14 @@ public:
   // Process all pending messages from a client.
   void handle();
 
-  void handle_halt_reason(const std::vector<uint8_t> &packet);
   void handle_packet(const std::vector<uint8_t> &packet);
+  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_continue(const std::vector<uint8_t> &packet);
 
 private:
   sim_t *sim;
index 63339b153935d902371cdf86fb33d2c45d6c2e95..26a91dbc8bec6b4515267ca050c25c4ccb0c7d44 100644 (file)
@@ -22,7 +22,7 @@
 
 processor_t::processor_t(const char* isa, sim_t* sim, uint32_t id)
   : sim(sim), ext(NULL), disassembler(new disassembler_t),
-    id(id), run(false), debug(false)
+    id(id), run(false), debug(false), halted(false)
 {
   parse_isa_string(isa);
 
@@ -126,6 +126,11 @@ void processor_t::set_debug(bool value)
     ext->set_debug(value);
 }
 
+void processor_t::set_halted(bool value)
+{
+  halted = value;
+}
+
 void processor_t::set_histogram(bool value)
 {
   histogram_enabled = value;
index 3adf9903471f24846420d92aa5da9f9b56f83cf0..94e95939aebe547f492f8dd955beafeac6ec8e9c 100644 (file)
@@ -81,6 +81,7 @@ public:
   ~processor_t();
 
   void set_debug(bool value);
+  void set_halted(bool value);
   void set_histogram(bool value);
   void reset(bool value);
   void step(size_t n); // run for n cycles
@@ -118,7 +119,10 @@ private:
   reg_t isa;
   std::string isa_string;
   bool run; // !reset
+  // When true, display disassembly of each instruction that's executed.
   bool debug;
+  // TODO: Should this just be rolled into `run`?
+  bool halted;  // When true, no instructions are executed.
   bool histogram_enabled;
 
   std::vector<insn_desc_t> instructions;