{
// TODO: We should really not call this function at all when halted, to avoid
// burning CPU.
- while (run && !halted && n > 0) {
+ if (single_step) {
+ halted = false;
+ n = 1;
+ }
+ if (halted) {
+ return;
+ }
+
+ while (run && n > 0) {
size_t instret = 0;
reg_t pc = state.pc;
mmu_t* _mmu = mmu;
state.minstret += instret;
n -= instret;
}
+
+ if (single_step) {
+ single_step = false;
+ halted = true;
+ }
}
}
p->set_halted(false);
+ running = true;
+}
+
+void gdbserver_t::handle_step(const std::vector<uint8_t> &packet)
+{
+ // s [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_single_step(true);
+ running = true;
}
void gdbserver_t::handle_kill(const std::vector<uint8_t> &packet)
return handle_register_read(packet);
case 'c':
return handle_continue(packet);
+ case 's':
+ return handle_step(packet);
}
// Not supported.
processor_t *p = sim->get_core(0);
p->set_halted(true);
send_packet("S02"); // Pretend program received SIGINT.
+ running = false;
}
void gdbserver_t::handle()
{
+ processor_t *p = sim->get_core(0);
+ if (running && p->halted) {
+ // The core was running, but now it's halted. Better tell gdb.
+ send_packet("T00");
+ // TODO: Actually include register values here
+ running = false;
+ }
+
if (client_fd > 0) {
this->read();
this->write();
void handle_packet(const std::vector<uint8_t> &packet);
void handle_interrupt();
- void handle_halt_reason(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);
- void handle_memory_read(const std::vector<uint8_t> &packet);
+ 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_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);
+ void handle_step(const std::vector<uint8_t> &packet);
private:
sim_t *sim;
bool expect_ack;
bool extended_mode;
+ // Used to track whether we think the target is running. If we think it is
+ // but it isn't, we need to tell gdb about it.
+ bool running;
// Read pending data from the client.
void read();
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), halted(false)
+ id(id), run(false), debug(false), halted(false), single_step(false)
{
parse_isa_string(isa);
halted = value;
}
+void processor_t::set_single_step(bool value)
+{
+ single_step = value;
+}
+
void processor_t::set_histogram(bool value)
{
histogram_enabled = value;
void set_debug(bool value);
void set_halted(bool value);
+ void set_single_step(bool value);
void set_histogram(bool value);
void reset(bool value);
void step(size_t n); // run for n cycles
bool debug;
// TODO: Should this just be rolled into `run`?
bool halted; // When true, no instructions are executed.
+ // When true, execute exactly one instruction (even if halted is true), then
+ // set halted to true and single_step to false.
+ bool single_step;
bool histogram_enabled;
std::vector<insn_desc_t> instructions;