class halt_op_t : public operation_t
{
public:
- halt_op_t(gdbserver_t& gdbserver) : operation_t(gdbserver) {};
+ halt_op_t(gdbserver_t& gdbserver, bool send_status=false) :
+ operation_t(gdbserver), send_status(send_status) {};
bool perform_step(unsigned int step) {
switch (step) {
gs.sptbr_valid = false;
gs.pte_cache.clear();
+
+ if (send_status) {
+ switch (get_field(gs.dcsr, DCSR_CAUSE)) {
+ case DCSR_CAUSE_NONE:
+ fprintf(stderr, "Internal error. Processor halted without reason.\n");
+ abort();
+
+ case DCSR_CAUSE_HWBP:
+ case DCSR_CAUSE_DEBUGINT:
+ case DCSR_CAUSE_STEP:
+ case DCSR_CAUSE_HALT:
+ // There's no gdb code for this.
+ gs.send_packet("T05");
+ break;
+ case DCSR_CAUSE_SWBP:
+ gs.send_packet("T05swbreak:;");
+ break;
+ }
+ }
+
return true;
}
return false;
}
+
+ private:
+ bool send_status;
};
class continue_op_t : public operation_t
class memory_read_op_t : public operation_t
{
public:
- memory_read_op_t(gdbserver_t& gdbserver, reg_t vaddr, unsigned int length) :
- operation_t(gdbserver), vaddr(vaddr), length(length) {};
+ // Read length bytes from vaddr, storing the result into data.
+ // If data is NULL, send the result straight to gdb.
+ memory_read_op_t(gdbserver_t& gdbserver, reg_t vaddr, unsigned int length,
+ unsigned char *data=NULL) :
+ operation_t(gdbserver), vaddr(vaddr), length(length), data(data) {};
bool perform_step(unsigned int step)
{
access_size = (paddr % length);
if (access_size == 0)
access_size = length;
+ if (access_size > 8)
+ access_size = 8;
gs.write_debug_ram(0, ld(S0, 0, (uint16_t) DEBUG_RAM_START + 16));
switch (access_size) {
case 8:
gs.write_debug_ram(1, ld(S1, S0, 0));
break;
- default:
- gs.send_packet("E12");
- return true;
}
gs.write_debug_ram(2, sd(S1, 0, (uint16_t) DEBUG_RAM_START + 24));
gs.write_debug_ram(3, jal(0, (uint32_t) (DEBUG_ROM_RESUME - (DEBUG_RAM_START + 4*3))));
gs.write_debug_ram(5, paddr >> 32);
gs.set_interrupt(0);
- gs.start_packet();
+ if (!data) {
+ gs.start_packet();
+ }
return false;
}
char buffer[3];
reg_t value = ((uint64_t) gs.read_debug_ram(7) << 32) | gs.read_debug_ram(6);
for (unsigned int i = 0; i < access_size; i++) {
- sprintf(buffer, "%02x", (unsigned int) (value & 0xff));
- gs.send(buffer);
+ if (data) {
+ *(data++) = value & 0xff;
+ } else {
+ sprintf(buffer, "%02x", (unsigned int) (value & 0xff));
+ gs.send(buffer);
+ }
value >>= 8;
}
length -= access_size;
paddr += access_size;
if (length == 0) {
- gs.end_packet();
+ if (!data) {
+ gs.end_packet();
+ }
return true;
} else {
gs.write_debug_ram(4, paddr);
}
private:
- reg_t vaddr, paddr;
+ reg_t vaddr;
unsigned int length;
+ unsigned char* data;
+ reg_t paddr;
unsigned int access_size;
};
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);
- }
- fprintf(stderr, ">>> Read %x from %lx\n", instruction, address);
-}
-
-void software_breakpoint_t::remove(mmu_t* mmu)
-{
- fprintf(stderr, ">>> write %x to %lx\n", instruction, address);
- 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
return send_packet("E53");
}
- processor_t *p = sim->get_core(0);
- die("handle_breakpoint");
- /*
- mmu_t* mmu = p->mmu;
+ add_operation(new collect_translation_info_op_t(*this, bp.address, bp.size));
if (insert) {
- bp.insert(mmu);
+ // TODO: this only works on little-endian hosts.
+ unsigned char* swbp = new unsigned char[4];
+ if (bp.size == 2) {
+ swbp[0] = C_EBREAK & 0xff;
+ swbp[1] = (C_EBREAK >> 8) & 0xff;
+ } else {
+ swbp[0] = EBREAK & 0xff;
+ swbp[1] = (EBREAK >> 8) & 0xff;
+ swbp[2] = (EBREAK >> 16) & 0xff;
+ swbp[3] = (EBREAK >> 24) & 0xff;
+ }
+
+ add_operation(new memory_read_op_t(*this, bp.address, bp.size, bp.instruction));
+ add_operation(new memory_write_op_t(*this, bp.address, bp.size, swbp));
breakpoints[bp.address] = bp;
} else {
bp = breakpoints[bp.address];
- bp.remove(mmu);
+ unsigned char* instruction = new unsigned char[4];
+ memcpy(instruction, bp.instruction, 4);
+ add_operation(new memory_write_op_t(*this, bp.address, bp.size, instruction));
breakpoints.erase(bp.address);
}
- mmu->flush_icache();
- sim->debug_mmu->flush_icache();
- */
+
+ // TODO mmu->flush_icache();
+ // TODO sim->debug_mmu->flush_icache();
+
return send_packet("OK");
}
}
}
- /* TODO
- if (running && p->halted) {
- // The core was running, but now it's halted. Better tell gdb.
- switch (p->halt_reason) {
- case HR_NONE:
- fprintf(stderr, "Internal error. Processor halted without reason.\n");
- abort();
- case HR_STEPPED:
- case HR_INTERRUPT:
- case HR_CMDLINE:
- case HR_ATTACHED:
- // There's no gdb code for this.
- send_packet("T05");
- break;
- case HR_SWBP:
- send_packet("T05swbreak:;");
- break;
- }
- send_packet("T00");
- // TODO: Actually include register values here
- running = false;
+ bool halt_notification = sim->debug_module.get_halt_notification(0);
+ if (halt_notification) {
+ sim->debug_module.clear_halt_notification(0);
+ add_operation(new halt_op_t(*this, true));
}
- */
this->read();
this->write();