Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GDB stub #1583

Merged
merged 28 commits into from
Oct 22, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
2f67161
gdbstub beginnings
PoroCYon Dec 5, 2022
4a9456c
gdbstub: finish gdb impl things, next up is integration with melonDS
PoroCYon Dec 5, 2022
300bc37
holy fuck the gdbstub works
PoroCYon Dec 6, 2022
7059dee
gdb breakpoints work, but there's a mysterious crash on continue
PoroCYon Dec 8, 2022
358dfb1
fix memory corruption that sometimes happened, and make resetting the…
PoroCYon Dec 8, 2022
448848d
remove some gdb debug printing
PoroCYon Dec 8, 2022
857f574
fix things in gdbstub
PoroCYon Dec 13, 2022
f35a807
separate option for enabling gdbstub
PoroCYon Dec 13, 2022
160ee42
add mode-dependent CPU registers
PoroCYon Jul 8, 2023
e17cda7
C++ize the GDBstub code
PoroCYon Jul 9, 2023
e2b9e9a
add gdbstub config in emu settings dialog
PoroCYon Jul 9, 2023
c41bad1
make sure gdb is disabled when jit is enabled
PoroCYon Jul 9, 2023
071e588
Remove unnecessary compiler flags, mark ARMJIT assembly code as no-ex…
PoroCYon Jul 9, 2023
24cc71d
add option to wait for debugger attach on startup
PoroCYon Jul 9, 2023
0eebcdf
only insert GNU stack notes on linux
PoroCYon Jul 9, 2023
c71d47b
disable gdbstub enable checkbox when jit is enabled
PoroCYon Jul 9, 2023
c489593
fix non-linux incompatibilities
PoroCYon Jul 9, 2023
3ddb384
enable gdbstub by default
PoroCYon Jul 9, 2023
242c035
fix issues with gdbstub settings disable stuff
PoroCYon Jul 9, 2023
0503b19
format stuff
PoroCYon Jul 15, 2023
a94d924
update gdb test code
PoroCYon Jul 16, 2023
60cd6c1
Fix segfault when calling StubCallbacks->GetCPU()
PoroCYon Jul 18, 2023
34218ef
fix packet size not being sent correctly
PoroCYon Jul 20, 2023
30bb773
fix select(2) calls (i should read docs more properly)
PoroCYon Jul 24, 2023
223043c
fix GDB command sequencing/parsing issue (hopefully)
PoroCYon Aug 20, 2023
73d2c5f
[GDB] implement no-ack mode
PoroCYon Aug 21, 2023
fae3642
fix sending ack on handshake
PoroCYon Aug 21, 2023
7305cb3
get lldb to work
PoroCYon Aug 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fix things in gdbstub
  • Loading branch information
PoroCYon committed Jul 16, 2023
commit 857f5747042fac0a8f54fce59d2219c9b6984e61
85 changes: 67 additions & 18 deletions src/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,31 +38,37 @@ using Platform::LogLevel;
#ifdef GDBSTUB_ENABLED

#define GDB_CHECK_A() do{\
PoroCYon marked this conversation as resolved.
Show resolved Hide resolved
if (!is_single_step) { /* check if eg. break signal is incoming etc. */ \
if (!is_single_step && !break_req) { /* check if eg. break signal is incoming etc. */ \
enum gdbstub_state st = gdbstub_enter(stub, false); \
is_single_step = st == gdbstat_step; \
break_req = st == gdbstat_attach || st == gdbstat_break; \
} \
} while (0) \

#define GDB_CHECK_B(...) do{\
if (is_single_step || break_req) \
{ /* use else here or we singnle-step the same insn twice in gdb */ \
uint32_t pc_real = R[15] - ((CPSR & 0x20) ? 2 : 4); \
enum gdbstub_state st = gdbstub_enter_reason(stub, true, gdbt_singlestep, pc_real); \
is_single_step = st == gdbstat_step; \
break_req = st == gdbstat_attach || st == gdbstat_break; \
if (break_req) Log(LogLevel::Debug, "=== BREAK REQ ===\n"); \
} \
} while (0) \
} while (0) \

#define GDB_CHECK_B() do{\

#define GDB_CHECK_C() do{\
uint32_t pc_real = R[15] - ((CPSR & 0x20) ? 2 : 4); \
enum gdbstub_state st = gdbstub_check_bkpt(stub, pc_real, true, true); \
if (st != gdbstat_check_no_hit) { \
is_single_step = st == gdbstat_step; \
break_req = st == gdbstat_attach || st == gdbstat_break; \
} else if (is_single_step || break_req) \
{ /* use else here or we singnle-step the same insn twice in gdb */ \
if (break_req) Log(LogLevel::Debug, "=== BREAK RESP ===\n"); \
st = gdbstub_enter_reason(stub, true, gdbt_singlestep, pc_real); \
is_single_step = st == gdbstat_step; \
break_req = st == gdbstat_attach || st == gdbstat_break; \
} \
} else GDB_CHECK_B(true); \
} while (0) \

#else
#define GDB_CHECK_A() do{}while(0)
#define GDB_CHECK_B() do{}while(0)
#define GDB_CHECK_C() do{}while(0)
#endif


Expand Down Expand Up @@ -620,7 +626,7 @@ void ARM::CheckGdbIncoming()

void ARMv5::Execute()
{
//GDB_CHECK_A();
GDB_CHECK_B();

if (Halted)
{
Expand All @@ -645,7 +651,7 @@ void ARMv5::Execute()
{
if (CPSR & 0x20) // THUMB
{
GDB_CHECK_B();
GDB_CHECK_C();

// prefetch
R[15] += 2;
Expand All @@ -660,7 +666,7 @@ void ARMv5::Execute()
}
else
{
GDB_CHECK_B();
GDB_CHECK_C();

// prefetch
R[15] += 4;
Expand Down Expand Up @@ -776,7 +782,7 @@ void ARMv5::ExecuteJIT()

void ARMv4::Execute()
{
//GDB_CHECK_A();
GDB_CHECK_B();

if (Halted)
{
Expand All @@ -801,7 +807,7 @@ void ARMv4::Execute()
{
if (CPSR & 0x20) // THUMB
{
GDB_CHECK_B();
GDB_CHECK_C();

// prefetch
R[15] += 2;
Expand All @@ -815,7 +821,7 @@ void ARMv4::Execute()
}
else
{
GDB_CHECK_B();
GDB_CHECK_C();

// prefetch
R[15] += 4;
Expand Down Expand Up @@ -1000,6 +1006,26 @@ uint32_t ARM::GdbReadMem(void* ud, uint32_t addr, int size)
{
ARM* cpu = (ARM*)ud;

if (cpu == NDS::ARM9)
{
ARMv5* a9 = (ARMv5*)ud;

if (addr < a9->ITCMSize)
{
if (size == 8) return *(u8*)&a9->ITCM[addr & (ITCMPhysicalSize - 1)];
else if (size == 16) return *(u16*)&a9->ITCM[addr & (ITCMPhysicalSize - 1)];
else if (size == 32) return *(u32*)&a9->ITCM[addr & (ITCMPhysicalSize - 1)];
else return 0xfeedface;
}
else if ((addr & a9->DTCMMask) == a9->DTCMBase)
{
if (size == 8) return *(u8*)&a9->DTCM[addr & (DTCMPhysicalSize - 1)];
else if (size == 16) return *(u16*)&a9->DTCM[addr & (DTCMPhysicalSize - 1)];
else if (size == 32) return *(u32*)&a9->DTCM[addr & (DTCMPhysicalSize - 1)];
else return 0xfeedface;
}
}

if (size == 8) return cpu->BusRead8(addr);
else if (size == 16) return cpu->BusRead16(addr);
else if (size == 32) return cpu->BusRead32(addr);
Expand All @@ -1009,6 +1035,29 @@ void ARM::GdbWriteMem(void* ud, uint32_t addr, int size, uint32_t v)
{
ARM* cpu = (ARM*)ud;

if (cpu == NDS::ARM9)
{
ARMv5* a9 = (ARMv5*)ud;

if (addr < a9->ITCMSize)
{
if (size == 8) *(u8*)&a9->ITCM[addr & (ITCMPhysicalSize - 1)] = (u8)v;
else if (size == 16) *(u16*)&a9->ITCM[addr & (ITCMPhysicalSize - 1)] = (u16)v;
else if (size == 32) *(u32*)&a9->ITCM[addr & (ITCMPhysicalSize - 1)] = (u32)v;
else {}
return;
}
else if ((addr & a9->DTCMMask) == a9->DTCMBase)
{
if (size == 8) *(u8*)&a9->DTCM[addr & (DTCMPhysicalSize - 1)] = (u8)v;
else if (size == 16) *(u16*)&a9->DTCM[addr & (DTCMPhysicalSize - 1)] = (u16)v;
else if (size == 32) *(u32*)&a9->DTCM[addr & (DTCMPhysicalSize - 1)] = (u32)v;
else {}
return;
}
}


if (size == 8) cpu->BusWrite8(addr, (uint8_t)v);
else if (size == 16) cpu->BusWrite16(addr, (uint16_t)v);
else if (size == 32) cpu->BusWrite32(addr, v);
Expand All @@ -1027,7 +1076,7 @@ int ARM::GdbRemoteCmd(void* ud, const uint8_t* cmd, size_t len)
(void)len;

printf("[ARMGDB] Rcmd: \"%s\"\n", cmd);
if (!strcmp((const char*)cmd, "reset")) {
if (!strcmp((const char*)cmd, "reset") || !strcmp((const char*)cmd, "r")) {
GdbReset(ud);
return 0;
}
Expand Down
29 changes: 20 additions & 9 deletions src/debug/gdbstub.c
Original file line number Diff line number Diff line change
Expand Up @@ -319,13 +319,17 @@ void gdbstub_signal_status(struct gdbstub* stub, enum gdbtgt_status stat, uint32


enum gdbstub_state gdbstub_enter_reason(struct gdbstub* stub, bool stay, enum gdbtgt_status stat, uint32_t arg) {
if (!stub) return;
if (!stub) return gdbstat_noconn;
if (stat != gdbt_no_event) gdbstub_signal_status(stub, stat, arg);

enum gdbstub_state st;
bool do_next = true;
do {
bool was_conn = stub->connfd > 0;
st = gdbstub_poll(stub);
bool has_conn = stub->connfd > 0;

if (has_conn && !was_conn) stay = true;

switch (st) {
case gdbstat_break:
Expand All @@ -346,9 +350,7 @@ enum gdbstub_state gdbstub_enter_reason(struct gdbstub* stub, bool stay, enum gd
do_next = false;
break;
}

if (!stay) break;
} while (do_next);
} while (do_next && stay);

//if (st != 0 && st != 1) printf("[GDB] enter exit: %d\n", st);
return st;
Expand Down Expand Up @@ -391,6 +393,12 @@ void gdbstub_add_bkpt(struct gdbstub* stub, uint32_t addr, int kind) {
}

stub->bp_list[ind] = new;

/*printf("[GDB] added bkpt:\n");
for (size_t i = 0; i < stub->bp_size; ++i) {
printf("\t[%zu]: addr=%08x, kind=%d, used=%c\n", i, stub->bp_list[i].addr,
stub->bp_list[i].kind, stub->bp_list[i].used?'T':'f');
}*/
}
void gdbstub_add_watchpt(struct gdbstub* stub, uint32_t addr, uint32_t len, int kind) {
if (!stub) return;
Expand Down Expand Up @@ -464,14 +472,17 @@ void gdbstub_del_all_bp_wp(struct gdbstub* stub) {

enum gdbstub_state gdbstub_check_bkpt(struct gdbstub* stub, uint32_t addr, bool enter, bool stay) {
addr ^= (addr & 1); // clear lowest bit to not break on thumb mode weirdnesses
if (!stub) return;
if (!stub) return gdbstat_check_no_hit;
uint32_t ind = addr % stub->bp_size;

if (stub->bp_list[ind].used && stub->bp_list[ind].addr == addr) {
//__builtin_trap();
if (enter)
return gdbstub_enter_reason(stub, stay, gdbt_bkpt, addr);
else {
if (enter) {
//printf("[GDB] ENTER bkpt 0x%08x!\n", addr);
enum gdbstub_state r = gdbstub_enter_reason(stub, stay, gdbt_bkpt, addr);
//printf("[GDB] ENTER st=%d\n", r);
return r;
} else {
gdbstub_signal_status(stub, gdbt_bkpt, addr);
return gdbstat_none;
}
Expand All @@ -480,7 +491,7 @@ enum gdbstub_state gdbstub_check_bkpt(struct gdbstub* stub, uint32_t addr, bool
return gdbstat_check_no_hit;
}
enum gdbstub_state gdbstub_check_watchpt(struct gdbstub* stub, uint32_t addr, int kind, bool enter, bool stay) {
if (!stub) return;
if (!stub) return gdbstat_check_no_hit;
uint32_t ind = addr % stub->wp_size;

// TODO: check address ranges!
Expand Down