gdb: fix multiple extended-remote issues, also fix possible race condtions
This commit is contained in:
parent
54de645dc3
commit
17ca09346d
@ -37,6 +37,7 @@ typedef struct GDBServer
|
|||||||
sock_server super;
|
sock_server super;
|
||||||
s32 referenceCount;
|
s32 referenceCount;
|
||||||
Handle statusUpdated;
|
Handle statusUpdated;
|
||||||
|
Handle statusUpdateReceived;
|
||||||
GDBContext ctxs[MAX_DEBUG];
|
GDBContext ctxs[MAX_DEBUG];
|
||||||
} GDBServer;
|
} GDBServer;
|
||||||
|
|
||||||
|
@ -175,7 +175,9 @@ void GDB_DetachFromProcess(GDBContext *ctx)
|
|||||||
ctx->eventToWaitFor = ctx->processAttachedEvent;
|
ctx->eventToWaitFor = ctx->processAttachedEvent;
|
||||||
ctx->continueFlags = (DebugFlags)(DBG_SIGNAL_FAULT_EXCEPTION_EVENTS | DBG_INHIBIT_USER_CPU_EXCEPTION_HANDLERS);
|
ctx->continueFlags = (DebugFlags)(DBG_SIGNAL_FAULT_EXCEPTION_EVENTS | DBG_INHIBIT_USER_CPU_EXCEPTION_HANDLERS);
|
||||||
ctx->pid = 0;
|
ctx->pid = 0;
|
||||||
ctx->currentThreadId = ctx->selectedThreadId = ctx->selectedThreadIdForContinuing = 0;
|
ctx->currentThreadId = 0;
|
||||||
|
ctx->selectedThreadId = 0;
|
||||||
|
ctx->selectedThreadIdForContinuing = 0;
|
||||||
ctx->nbThreads = 0;
|
ctx->nbThreads = 0;
|
||||||
ctx->totalNbCreatedThreads = 0;
|
ctx->totalNbCreatedThreads = 0;
|
||||||
memset(ctx->threadInfos, 0, sizeof(ctx->threadInfos));
|
memset(ctx->threadInfos, 0, sizeof(ctx->threadInfos));
|
||||||
|
@ -43,9 +43,15 @@ static void GDB_DetachImmediatelyExtended(GDBContext *ctx)
|
|||||||
{
|
{
|
||||||
// detach immediately
|
// detach immediately
|
||||||
RecursiveLock_Lock(&ctx->lock);
|
RecursiveLock_Lock(&ctx->lock);
|
||||||
svcSignalEvent(ctx->parent->statusUpdated); // note: monitor will be waiting for lock
|
|
||||||
|
|
||||||
ctx->state = GDB_STATE_DETACHING;
|
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);
|
GDB_DetachFromProcess(ctx);
|
||||||
ctx->flags &= GDB_FLAG_PROC_RESTART_MASK;
|
ctx->flags &= GDB_FLAG_PROC_RESTART_MASK;
|
||||||
RecursiveLock_Unlock(&ctx->lock);
|
RecursiveLock_Unlock(&ctx->lock);
|
||||||
@ -279,7 +285,15 @@ GDB_DECLARE_VERBOSE_HANDLER(Continue)
|
|||||||
|
|
||||||
GDB_DECLARE_HANDLER(GetStopReason)
|
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)
|
static int GDB_ParseCommonThreadInfo(char *out, GDBContext *ctx, int sig)
|
||||||
|
@ -55,8 +55,10 @@ void GDB_RunMonitor(GDBServer *server)
|
|||||||
|
|
||||||
if(R_FAILED(r) || idx < 2)
|
if(R_FAILED(r) || idx < 2)
|
||||||
break;
|
break;
|
||||||
else if(idx == 2)
|
else if(idx == 2) {
|
||||||
|
svcSignalEvent(server->statusUpdateReceived);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GDBContext *ctx = &server->ctxs[idx - 3];
|
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
|
while(GDB_HandleDebugEvents(ctx) != -1) // until we've got all the remaining debug events
|
||||||
svcSleepThread(1 * 1000 * 1000LL); // sleep just in case
|
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);
|
svcClearEvent(ctx->processAttachedEvent);
|
||||||
ctx->eventToWaitFor = ctx->processAttachedEvent;
|
ctx->eventToWaitFor = ctx->processAttachedEvent;
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,7 @@ Result GDB_InitializeServer(GDBServer *server)
|
|||||||
|
|
||||||
server->referenceCount = 0;
|
server->referenceCount = 0;
|
||||||
svcCreateEvent(&server->statusUpdated, RESET_ONESHOT);
|
svcCreateEvent(&server->statusUpdated, RESET_ONESHOT);
|
||||||
|
svcCreateEvent(&server->statusUpdateReceived, RESET_STICKY);
|
||||||
|
|
||||||
for(u32 i = 0; i < sizeof(server->ctxs) / sizeof(GDBContext); i++)
|
for(u32 i = 0; i < sizeof(server->ctxs) / sizeof(GDBContext); i++)
|
||||||
GDB_InitializeContext(server->ctxs + i);
|
GDB_InitializeContext(server->ctxs + i);
|
||||||
@ -70,6 +71,7 @@ void GDB_FinalizeServer(GDBServer *server)
|
|||||||
server_finalize(&server->super);
|
server_finalize(&server->super);
|
||||||
|
|
||||||
svcCloseHandle(server->statusUpdated);
|
svcCloseHandle(server->statusUpdated);
|
||||||
|
svcCloseHandle(server->statusUpdateReceived);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDB_IncrementServerReferenceCount(GDBServer *server)
|
void GDB_IncrementServerReferenceCount(GDBServer *server)
|
||||||
@ -189,7 +191,13 @@ int GDB_AcceptClient(GDBContext *ctx)
|
|||||||
int GDB_CloseClient(GDBContext *ctx)
|
int GDB_CloseClient(GDBContext *ctx)
|
||||||
{
|
{
|
||||||
RecursiveLock_Lock(&ctx->lock);
|
RecursiveLock_Lock(&ctx->lock);
|
||||||
|
svcClearEvent(ctx->parent->statusUpdateReceived);
|
||||||
svcSignalEvent(ctx->parent->statusUpdated); // note: monitor will be waiting for lock
|
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);
|
GDB_DetachFromProcess(ctx);
|
||||||
ctx->state = GDB_STATE_DISCONNECTED;
|
ctx->state = GDB_STATE_DISCONNECTED;
|
||||||
RecursiveLock_Unlock(&ctx->lock);
|
RecursiveLock_Unlock(&ctx->lock);
|
||||||
|
Reference in New Issue
Block a user