gdb can attach and read the PC:
authorTim Newsome <tim@sifive.com>
Tue, 26 Apr 2016 21:32:08 +0000 (14:32 -0700)
committerTim Newsome <tim@sifive.com>
Mon, 23 May 2016 19:12:11 +0000 (12:12 -0700)
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
0x0000000000010178 in fib (n=0) at waste.c:1
1       unsigned int fib(unsigned int n) {
(gdb)

riscv/execute.cc
riscv/gdbserver.cc
riscv/gdbserver.h
riscv/mmu.h

index ae4c9597a1bd00af5b9ecfd992c470c807659d66..a1c22292a410774a9ae06a11f66c0e16dff9bcd6 100644 (file)
@@ -63,7 +63,7 @@ void processor_t::step(size_t n)
   if (state.dcsr.cause != DCSR_CAUSE_NONE) {
     // In Debug Mode, just do 10 steps at a time. Otherwise we're going to be
     // spinning the rest of the time anyway.
-    n = std::max(n, (size_t) 10);
+    n = std::min(n, (size_t) 10);
   }
 
   while (n > 0) {
index 04879394632a00590430d58033d29f706618df80..a4f8c0b4fc3296279afe01ea49b7fe9a7296736b 100644 (file)
@@ -63,6 +63,15 @@ static uint32_t sw(unsigned int src, unsigned int base, uint16_t offset)
     MATCH_SW;
 }
 
+static uint32_t sd(unsigned int src, unsigned int base, uint16_t offset)
+{
+  return (bits(offset, 11, 5) << 25) |
+    (src << 20) |
+    (base << 15) |
+    (bits(offset, 4, 0) << 7) |
+    MATCH_SD;
+}
+
 template <typename T>
 unsigned int circular_buffer_t<T>::size() const
 {
@@ -177,12 +186,12 @@ uint32_t gdbserver_t::read_debug_ram(unsigned int index)
 
 void gdbserver_t::halt()
 {
-  processor_t *p = sim->get_core(0);
+  // TODO: For now we just assume the target is 64-bit.
   write_debug_ram(0, csrsi(DCSR_ADDRESS, DCSR_HALT_MASK));
   write_debug_ram(1, csrr(S0, DPC_ADDRESS));
-  write_debug_ram(2, sw(S0, 0, (uint16_t) DEBUG_RAM_START));
+  write_debug_ram(2, sd(S0, 0, (uint16_t) DEBUG_RAM_START));
   write_debug_ram(3, csrr(S0, DCSR_ADDRESS));
-  write_debug_ram(4, sw(S0, 0, (uint16_t) DEBUG_RAM_START + 8));
+  write_debug_ram(4, sd(S0, 0, (uint16_t) DEBUG_RAM_START + 8));
   write_debug_ram(5, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*5))));
   sim->debug_module.set_interrupt(0);
   state = STATE_HALTING;
@@ -358,7 +367,7 @@ void gdbserver_t::handle_halt_reason(const std::vector<uint8_t> &packet)
 
 void die(const char* msg)
 {
-  fprintf(stderr, "%s\n", msg);
+  fprintf(stderr, "gdbserver code died: %s\n", msg);
   abort();
 }
 
@@ -379,12 +388,36 @@ void gdbserver_t::handle_general_registers_read(const std::vector<uint8_t> &pack
   send("$");
   running_checksum = 0;
   processor_t *p = sim->get_core(0);
-  for (int r = 0; r < 32; r++) {
-    die("handle_general_registers_read");
-    // send(p->state.XPR[r]);
+
+  // x0 is always zero.
+  send((reg_t) 0);
+
+  write_debug_ram(0, sd(1, 0, (uint16_t) DEBUG_RAM_START + 16));
+  write_debug_ram(1, sd(2, 0, (uint16_t) DEBUG_RAM_START + 0));
+  write_debug_ram(2, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*2))));
+  sim->debug_module.set_interrupt(0);
+  state = STATE_CONT_GENERAL_REGISTERS;
+  state_argument = 1;
+}
+
+void gdbserver_t::continue_general_registers_read()
+{
+  send(((uint64_t) read_debug_ram(5) << 32) | read_debug_ram(4));
+  if (state_argument >= 31) {
+    send_running_checksum();
+    expect_ack = true;
+    state = STATE_HALTED;
+  } else {
+    send(((uint64_t) read_debug_ram(1) << 32) | read_debug_ram(0));
+
+    state_argument += 2;
+    // TODO properly read s0 and s1
+    write_debug_ram(0, sd(state_argument, 0, (uint16_t) DEBUG_RAM_START + 16));
+    write_debug_ram(1, sd(state_argument+1, 0, (uint16_t) DEBUG_RAM_START + 0));
+    write_debug_ram(2, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*2))));
+    sim->debug_module.set_interrupt(0);
+    state = STATE_CONT_GENERAL_REGISTERS;
   }
-  send_running_checksum();
-  expect_ack = true;
 }
 
 // First byte is the most-significant one.
@@ -460,21 +493,24 @@ void gdbserver_t::handle_register_read(const std::vector<uint8_t> &packet)
   if (*iter != '#')
     return send_packet("E01");
 
-  processor_t *p = sim->get_core(0);
-  send("$");
-  running_checksum = 0;
+  state = STATE_CONT_REGISTER_READ;
+  state_argument = n;
 
-  die("handle_register_read");
-  /*
   if (n >= REG_XPR0 && n <= REG_XPR31) {
-    send(p->state.XPR[n - REG_XPR0]);
+    die("handle_register_read");
+    // send(p->state.XPR[n - REG_XPR0]);
   } else if (n == REG_PC) {
-    send(p->state.pc);
+    write_debug_ram(0, csrr(S0, DPC_ADDRESS));
+    write_debug_ram(1, sd(S0, 0, (uint16_t) DEBUG_RAM_START));
+    write_debug_ram(2, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*2))));
+    sim->debug_module.set_interrupt(0);
   } else if (n >= REG_FPR0 && n <= REG_FPR31) {
-    send(p->state.FPR[n - REG_FPR0]);
+    die("handle_register_read");
+    // send(p->state.FPR[n - REG_FPR0]);
   } else if (n >= REG_CSR0 && n <= REG_CSR4095) {
     try {
-      send(p->get_csr(n - REG_CSR0));
+      die("handle_register_read");
+      // send(p->get_csr(n - REG_CSR0));
     } catch(trap_t& t) {
       // It would be nicer to return an error here, but if you do that then gdb
       // exits out of 'info registers all' as soon as it encounters a register
@@ -482,12 +518,21 @@ void gdbserver_t::handle_register_read(const std::vector<uint8_t> &packet)
       send((reg_t) 0);
     }
   } else {
+    state = STATE_HALTED;
     return send_packet("E02");
   }
-  */
+}
+
+void gdbserver_t::continue_register_read()
+{
+  send("$");
+  running_checksum = 0;
+
+  send(((uint64_t) read_debug_ram(1) << 32) | read_debug_ram(0));
 
   send_running_checksum();
   expect_ack = true;
+  state = STATE_HALTED;
 }
 
 void gdbserver_t::handle_register_write(const std::vector<uint8_t> &packet)
@@ -786,13 +831,27 @@ void gdbserver_t::handle()
   if (client_fd > 0) {
     processor_t *p = sim->get_core(0);
 
-    if (state == STATE_HALTING && sim->debug_module.get_interrupt(0) == 0) {
+    bool interrupt = sim->debug_module.get_interrupt(0);
+
+    if (state == STATE_HALTING && !interrupt) {
       // gdb requested a halt and now it's done.
       send_packet("T05");
       fprintf(stderr, "DPC: 0x%x\n", read_debug_ram(0));
       fprintf(stderr, "DCSR: 0x%x\n", read_debug_ram(2));
       state = STATE_HALTED;
-      p->debug = false;
+    }
+
+    if (!interrupt) {
+      switch (state) {
+        case STATE_CONT_GENERAL_REGISTERS:
+          continue_general_registers_read();
+          break;
+        case STATE_CONT_REGISTER_READ:
+          continue_register_read();
+          break;
+        default:
+          break;
+      }
     }
 
     /* TODO
@@ -819,7 +878,13 @@ void gdbserver_t::handle()
     }
       */
 
-    this->read();
+    if (state == STATE_HALTED) {
+      this->read();
+      //p->debug = false;
+    } else {
+      //p->debug = true;
+    }
+
     this->write();
 
   } else {
index 5a7a102797e85270f72ed8fc5506928ae0317c41..156001d694f68f9f6d1e214402d2d827a0703e81 100644 (file)
@@ -71,12 +71,14 @@ public:
   void handle_continue(const std::vector<uint8_t> &packet);
   void handle_extended(const std::vector<uint8_t> &packet);
   void handle_general_registers_read(const std::vector<uint8_t> &packet);
+  void continue_general_registers_read();
   void handle_halt_reason(const std::vector<uint8_t> &packet);
   void handle_kill(const std::vector<uint8_t> &packet);
   void handle_memory_binary_write(const std::vector<uint8_t> &packet);
   void handle_memory_read(const std::vector<uint8_t> &packet);
   void handle_query(const std::vector<uint8_t> &packet);
   void handle_register_read(const std::vector<uint8_t> &packet);
+  void continue_register_read();
   void handle_register_write(const std::vector<uint8_t> &packet);
   void handle_step(const std::vector<uint8_t> &packet);
 
@@ -100,8 +102,11 @@ private:
     STATE_UNKNOWN,
     STATE_RUNNING,
     STATE_HALTING,
-    STATE_HALTED
+    STATE_HALTED,
+    STATE_CONT_GENERAL_REGISTERS,
+    STATE_CONT_REGISTER_READ,
   } state;
+  uint32_t state_argument;
 
   std::map <reg_t, software_breakpoint_t> breakpoints;
 
index a87b6af30480ec5d51ddea728bf9d83f1fc76253..8fe3043bb77d4bcafe3a289983c7b6c6a4a7f9b6 100644 (file)
@@ -117,6 +117,7 @@ public:
       entry->tag = -1;
       tracer.trace(paddr, length, FETCH);
     }
+    entry->tag = -1;    // TODO: this is hack to work around Debug RAM code being cached
     return entry;
   }