diff --git a/sysmodules/rosalina/include/gdb/server.h b/sysmodules/rosalina/include/gdb/server.h index a3e3cff..9446b3e 100644 --- a/sysmodules/rosalina/include/gdb/server.h +++ b/sysmodules/rosalina/include/gdb/server.h @@ -37,6 +37,7 @@ typedef struct GDBServer sock_server super; s32 referenceCount; Handle statusUpdated; + Handle statusUpdateReceived; GDBContext ctxs[MAX_DEBUG]; } GDBServer; diff --git a/sysmodules/rosalina/source/gdb.c b/sysmodules/rosalina/source/gdb.c index 6873ab9..c203abc 100644 --- a/sysmodules/rosalina/source/gdb.c +++ b/sysmodules/rosalina/source/gdb.c @@ -175,7 +175,9 @@ void GDB_DetachFromProcess(GDBContext *ctx) ctx->eventToWaitFor = ctx->processAttachedEvent; ctx->continueFlags = (DebugFlags)(DBG_SIGNAL_FAULT_EXCEPTION_EVENTS | DBG_INHIBIT_USER_CPU_EXCEPTION_HANDLERS); ctx->pid = 0; - ctx->currentThreadId = ctx->selectedThreadId = ctx->selectedThreadIdForContinuing = 0; + ctx->currentThreadId = 0; + ctx->selectedThreadId = 0; + ctx->selectedThreadIdForContinuing = 0; ctx->nbThreads = 0; ctx->totalNbCreatedThreads = 0; memset(ctx->threadInfos, 0, sizeof(ctx->threadInfos)); diff --git a/sysmodules/rosalina/source/gdb/debug.c b/sysmodules/rosalina/source/gdb/debug.c index daafecd..e7d6a2c 100644 --- a/sysmodules/rosalina/source/gdb/debug.c +++ b/sysmodules/rosalina/source/gdb/debug.c @@ -43,9 +43,15 @@ static void GDB_DetachImmediatelyExtended(GDBContext *ctx) { // detach immediately RecursiveLock_Lock(&ctx->lock); - svcSignalEvent(ctx->parent->statusUpdated); // note: monitor will be waiting for lock - ctx->state = GDB_STATE_DETACHING; + + svcClearEvent(ctx->parent->statusUpdateReceived); + svcSignalEvent(ctx->parent->statusUpdated); + RecursiveLock_Unlock(&ctx->lock); + + svcWaitSynchronization(ctx->parent->statusUpdateReceived, -1LL); + + RecursiveLock_Lock(&ctx->lock); GDB_DetachFromProcess(ctx); ctx->flags &= GDB_FLAG_PROC_RESTART_MASK; RecursiveLock_Unlock(&ctx->lock); @@ -279,7 +285,15 @@ GDB_DECLARE_VERBOSE_HANDLER(Continue) GDB_DECLARE_HANDLER(GetStopReason) { - return ctx->debug != 0 ? GDB_SendStopReply(ctx, &ctx->latestDebugEvent) : GDB_SendPacket(ctx, "W00", 3); // "process exited" if nothing + if (ctx->processEnded && ctx->processExited) { + return GDB_SendPacket(ctx, "W00", 3); + } else if (ctx->processEnded && !ctx->processExited) { + return GDB_SendPacket(ctx, "X0f", 3); + } else if (ctx->debug == 0) { + return GDB_SendPacket(ctx, "W00", 3); + } else { + return GDB_SendStopReply(ctx, &ctx->latestDebugEvent); + } } static int GDB_ParseCommonThreadInfo(char *out, GDBContext *ctx, int sig) diff --git a/sysmodules/rosalina/source/gdb/monitor.c b/sysmodules/rosalina/source/gdb/monitor.c index 72d48bf..413ac86 100644 --- a/sysmodules/rosalina/source/gdb/monitor.c +++ b/sysmodules/rosalina/source/gdb/monitor.c @@ -55,8 +55,10 @@ void GDB_RunMonitor(GDBServer *server) if(R_FAILED(r) || idx < 2) break; - else if(idx == 2) + else if(idx == 2) { + svcSignalEvent(server->statusUpdateReceived); continue; + } else { GDBContext *ctx = &server->ctxs[idx - 3]; @@ -84,6 +86,12 @@ void GDB_RunMonitor(GDBServer *server) while(GDB_HandleDebugEvents(ctx) != -1) // until we've got all the remaining debug events svcSleepThread(1 * 1000 * 1000LL); // sleep just in case + // GDB doens't close the socket in extended-remote + if (ctx->flags & GDB_FLAG_EXTENDED_REMOTE) { + ctx->state = GDB_STATE_DETACHING; + GDB_DetachFromProcess(ctx); + ctx->flags &= GDB_FLAG_PROC_RESTART_MASK; + } svcClearEvent(ctx->processAttachedEvent); ctx->eventToWaitFor = ctx->processAttachedEvent; } diff --git a/sysmodules/rosalina/source/gdb/server.c b/sysmodules/rosalina/source/gdb/server.c index f1dc7bf..7eb46ca 100644 --- a/sysmodules/rosalina/source/gdb/server.c +++ b/sysmodules/rosalina/source/gdb/server.c @@ -56,6 +56,7 @@ Result GDB_InitializeServer(GDBServer *server) server->referenceCount = 0; svcCreateEvent(&server->statusUpdated, RESET_ONESHOT); + svcCreateEvent(&server->statusUpdateReceived, RESET_STICKY); for(u32 i = 0; i < sizeof(server->ctxs) / sizeof(GDBContext); i++) GDB_InitializeContext(server->ctxs + i); @@ -70,6 +71,7 @@ void GDB_FinalizeServer(GDBServer *server) server_finalize(&server->super); svcCloseHandle(server->statusUpdated); + svcCloseHandle(server->statusUpdateReceived); } void GDB_IncrementServerReferenceCount(GDBServer *server) @@ -189,7 +191,13 @@ int GDB_AcceptClient(GDBContext *ctx) int GDB_CloseClient(GDBContext *ctx) { RecursiveLock_Lock(&ctx->lock); + svcClearEvent(ctx->parent->statusUpdateReceived); svcSignalEvent(ctx->parent->statusUpdated); // note: monitor will be waiting for lock + RecursiveLock_Unlock(&ctx->lock); + + svcWaitSynchronization(ctx->parent->statusUpdateReceived, -1LL); + + RecursiveLock_Lock(&ctx->lock); GDB_DetachFromProcess(ctx); ctx->state = GDB_STATE_DISCONNECTED; RecursiveLock_Unlock(&ctx->lock);