gdb: fix multiple extended-remote issues, also fix possible race condtions

This commit is contained in:
TuxSH 2019-04-17 23:12:29 +02:00
parent 54de645dc3
commit 17ca09346d
5 changed files with 38 additions and 5 deletions

View File

@ -37,6 +37,7 @@ typedef struct GDBServer
sock_server super;
s32 referenceCount;
Handle statusUpdated;
Handle statusUpdateReceived;
GDBContext ctxs[MAX_DEBUG];
} GDBServer;

View File

@ -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));

View File

@ -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)

View File

@ -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;
}

View File

@ -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);