gdb: break before panicking in user code

This commit is contained in:
redoste 2023-06-04 18:37:27 +02:00
parent 6efcfa6018
commit 7d3663483f
No known key found for this signature in database

View file

@ -474,13 +474,13 @@ static struct {
void* channel0_addr; void* channel0_addr;
void* channel1_addr; void* channel1_addr;
} gdb_single_step_backup = { false }; } gdb_single_step_backup = { false };
static void gdb_handle_single_step(gdb_cpu_state_t* cpu_state) static void gdb_handle_single_step(uint32_t pc, ubc_break_mode_t break_mode)
{ {
gdb_single_step_backup.channel0_used = ubc_get_break_address(0, &gdb_single_step_backup.channel0_addr); gdb_single_step_backup.channel0_used = ubc_get_break_address(0, &gdb_single_step_backup.channel0_addr);
gdb_single_step_backup.channel1_used = ubc_get_break_address(1, &gdb_single_step_backup.channel1_addr); gdb_single_step_backup.channel1_used = ubc_get_break_address(1, &gdb_single_step_backup.channel1_addr);
ubc_disable_channel(0); ubc_disable_channel(0);
ubc_set_breakpoint(1, (void*)cpu_state->reg.pc, UBC_BREAK_AFTER); ubc_set_breakpoint(1, (void*)pc, break_mode);
gdb_single_step_backup.single_stepped = true; gdb_single_step_backup.single_stepped = true;
} }
@ -553,7 +553,7 @@ void gdb_main(gdb_cpu_state_t* cpu_state)
break; break;
case 's': case 's':
gdb_handle_single_step(cpu_state); gdb_handle_single_step(cpu_state->reg.pc, UBC_BREAK_AFTER);
return; return;
case 'c': // Continue case 'c': // Continue
return; return;
@ -579,20 +579,13 @@ static void gdb_notifier_function(void)
if (gdb_single_step_backup.single_stepped) if (gdb_single_step_backup.single_stepped)
return; return;
gdb_cpu_state_t fake_state = {}; gdb_handle_single_step(usb_interrupt_context->spc, UBC_BREAK_AFTER);
fake_state.reg.pc = usb_interrupt_context->spc;
gdb_handle_single_step(&fake_state);
} }
/* TODO : break and let the debugger attempt to fix the issue before panicking
* in user code
*/
static int gdb_panic_handler(uint32_t code) static int gdb_panic_handler(uint32_t code)
{ {
// We make sure we currently want to handle TLB misses // If we are currently expecting to handle TLB misses
if (!gdb_tlbh_enable) if (gdb_tlbh_enable) {
return 1;
// We only handle TLB miss reads (0x040) and writes (0x060) // We only handle TLB miss reads (0x040) and writes (0x060)
if (code != 0x040 && code != 0x060) if (code != 0x040 && code != 0x060)
return 1; return 1;
@ -602,6 +595,19 @@ static int gdb_panic_handler(uint32_t code)
// We skip the offending instruction and continue // We skip the offending instruction and continue
gint_exc_skip(1); gint_exc_skip(1);
return 0; return 0;
}
// If we are in user code, let's break
else if (!ubc_dbh_lock && gdb_state == GDB_STATE_STARTED) {
// We make sure an other step break is not already set up
if (gdb_single_step_backup.single_stepped)
return 1;
uint32_t spc;
__asm__("stc spc, %0" : "=r"(spc));
gdb_handle_single_step(spc, UBC_BREAK_BEFORE);
return 0;
}
return 1;
} }
int gdb_start(void) int gdb_start(void)