Browse Source

Software breakpoints seem to work.

pull/39/head
Tim Newsome 10 years ago
parent
commit
1f0612d593
  1. 5
      riscv/execute.cc
  2. 89
      riscv/gdbserver.cc
  3. 15
      riscv/gdbserver.h
  4. 6
      riscv/processor.cc

5
riscv/execute.cc

@ -59,11 +59,8 @@ void processor_t::step(size_t n)
halted = false;
n = 1;
}
if (halted) {
return;
}
while (run && n > 0) {
while (run && !halted && n > 0) {
size_t instret = 0;
reg_t pc = state.pc;
mmu_t* _mmu = mmu;

89
riscv/gdbserver.cc

@ -17,6 +17,9 @@
#include "gdbserver.h"
#include "mmu.h"
#define C_EBREAK 0x9002
#define EBREAK 0x00100073
template <typename T>
unsigned int circular_buffer_t<T>::size() const
{
@ -96,6 +99,12 @@ gdbserver_t::gdbserver_t(uint16_t port, sim_t *sim) :
}
fcntl(socket_fd, F_SETFL, O_NONBLOCK);
int reuseaddr = 1;
if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
sizeof(int)) == -1) {
fprintf(stderr, "failed setsockopt: %s (%d)\n", strerror(errno), errno);
abort();
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
@ -346,7 +355,7 @@ void gdbserver_t::handle_register_read(const std::vector<uint8_t> &packet)
std::vector<uint8_t>::const_iterator iter = packet.begin() + 2;
unsigned int n = consume_hex_number(iter, packet.end());
if (*iter != '#')
return send_packet("E16"); // EINVAL
return send_packet("E01");
processor_t *p = sim->get_core(0);
send("$");
@ -356,7 +365,7 @@ void gdbserver_t::handle_register_read(const std::vector<uint8_t> &packet)
} else if (n == 0x20) {
send(p->state.pc);
} else {
send("E16"); // EINVAL
send("E02");
}
send_running_checksum();
@ -369,11 +378,11 @@ void gdbserver_t::handle_memory_read(const std::vector<uint8_t> &packet)
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
return send_packet("E10");
iter++;
reg_t length = consume_hex_number(iter, packet.end());
if (*iter != '#')
return send_packet("E16"); // EINVAL
return send_packet("E11");
send("$");
running_checksum = 0;
@ -394,18 +403,18 @@ void gdbserver_t::handle_memory_binary_write(const std::vector<uint8_t> &packet)
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
return send_packet("E20");
iter++;
reg_t length = consume_hex_number(iter, packet.end());
if (*iter != ':')
return send_packet("E16"); // EINVAL
return send_packet("E21");
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
return send_packet("E22");
}
mmu->store_uint8(address + i, *iter);
iter++;
@ -424,7 +433,7 @@ void gdbserver_t::handle_continue(const std::vector<uint8_t> &packet)
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
return send_packet("E30");
}
p->set_halted(false);
@ -439,7 +448,7 @@ void gdbserver_t::handle_step(const std::vector<uint8_t> &packet)
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
return send_packet("E40");
}
p->set_single_step(true);
@ -462,6 +471,65 @@ void gdbserver_t::handle_extended(const std::vector<uint8_t> &packet)
extended_mode = true;
}
void software_breakpoint_t::insert(mmu_t* mmu)
{
if (size == 2) {
instruction = mmu->load_uint16(address);
mmu->store_uint16(address, C_EBREAK);
} else {
instruction = mmu->load_uint32(address);
mmu->store_uint32(address, EBREAK);
}
}
void software_breakpoint_t::remove(mmu_t* mmu)
{
if (size == 2) {
mmu->store_uint16(address, instruction);
} else {
mmu->store_uint32(address, instruction);
}
}
void gdbserver_t::handle_breakpoint(const std::vector<uint8_t> &packet)
{
// insert: Z type,addr,kind
// remove: z type,addr,kind
software_breakpoint_t bp;
bool insert = (packet[1] == 'Z');
std::vector<uint8_t>::const_iterator iter = packet.begin() + 2;
int type = consume_hex_number(iter, packet.end());
if (*iter != ',')
return send_packet("E50");
iter++;
bp.address = consume_hex_number(iter, packet.end());
if (*iter != ',')
return send_packet("E51");
iter++;
bp.size = consume_hex_number(iter, packet.end());
// There may be more options after a ; here, but we don't support that.
if (*iter != '#')
return send_packet("E52");
if (bp.size != 2 && bp.size != 4) {
return send_packet("E53");
}
processor_t *p = sim->get_core(0);
mmu_t* mmu = sim->debug_mmu;
if (insert) {
bp.insert(mmu);
breakpoints[bp.address] = bp;
} else {
bp = breakpoints[bp.address];
bp.remove(mmu);
breakpoints.erase(bp.address);
}
return send_packet("OK");
}
void gdbserver_t::handle_packet(const std::vector<uint8_t> &packet)
{
if (compute_checksum(packet) != extract_checksum(packet)) {
@ -497,6 +565,9 @@ void gdbserver_t::handle_packet(const std::vector<uint8_t> &packet)
return handle_continue(packet);
case 's':
return handle_step(packet);
case 'z':
case 'Z':
return handle_breakpoint(packet);
}
// Not supported.

15
riscv/gdbserver.h

@ -42,6 +42,18 @@ public:
void append(const T *src, unsigned int count);
};
// Class to track software breakpoints that we set.
class software_breakpoint_t
{
public:
reg_t address;
unsigned int size;
uint32_t instruction;
void insert(mmu_t* mmu);
void remove(mmu_t* mmu);
};
class gdbserver_t
{
public:
@ -55,6 +67,7 @@ public:
void handle_packet(const std::vector<uint8_t> &packet);
void handle_interrupt();
void handle_breakpoint(const std::vector<uint8_t> &packet);
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);
@ -78,6 +91,8 @@ private:
// but it isn't, we need to tell gdb about it.
bool running;
std::map <reg_t, software_breakpoint_t> breakpoints;
// Read pending data from the client.
void read();
void write();

6
riscv/processor.cc

@ -208,6 +208,12 @@ void processor_t::take_trap(trap_t& t, reg_t epc)
fprintf(stderr, "core %3d: exception %s, epc 0x%016" PRIx64 "\n",
id, t.name(), epc);
if (t.cause() == CAUSE_BREAKPOINT) {
// TODO: Only do this if there is a debugger attached.
halted = true;
return;
}
// by default, trap to M-mode, unless delegated to S-mode
reg_t bit = t.cause();
reg_t deleg = state.medeleg;

Loading…
Cancel
Save