diff --git a/sysmodules/rosalina/include/gdb.h b/sysmodules/rosalina/include/gdb.h index 595fa4d..2f1cf4e 100644 --- a/sysmodules/rosalina/include/gdb.h +++ b/sysmodules/rosalina/include/gdb.h @@ -85,6 +85,8 @@ typedef struct GDBContext sock_ctx super; RecursiveLock lock; + u16 localPort; + GDBFlags flags; GDBState state; diff --git a/sysmodules/rosalina/include/gdb/server.h b/sysmodules/rosalina/include/gdb/server.h index bf189fd..77817e0 100644 --- a/sysmodules/rosalina/include/gdb/server.h +++ b/sysmodules/rosalina/include/gdb/server.h @@ -47,6 +47,7 @@ void GDB_IncrementServerReferenceCount(GDBServer *server); void GDB_DecrementServerReferenceCount(GDBServer *server); void GDB_RunServer(GDBServer *server); +GDBContext *GDB_SelectAvailableContext(GDBServer *server, u16 minPort, u16 maxPort); int GDB_AcceptClient(GDBContext *ctx); int GDB_CloseClient(GDBContext *ctx); diff --git a/sysmodules/rosalina/source/gdb.c b/sysmodules/rosalina/source/gdb.c index 657cd30..20367ea 100644 --- a/sysmodules/rosalina/source/gdb.c +++ b/sysmodules/rosalina/source/gdb.c @@ -29,6 +29,7 @@ void GDB_InitializeContext(GDBContext *ctx) { + memset(ctx, 0, sizeof(GDBContext)); RecursiveLock_Init(&ctx->lock); RecursiveLock_Lock(&ctx->lock); diff --git a/sysmodules/rosalina/source/gdb/server.c b/sysmodules/rosalina/source/gdb/server.c index bac4d80..9e894d0 100644 --- a/sysmodules/rosalina/source/gdb/server.c +++ b/sysmodules/rosalina/source/gdb/server.c @@ -90,6 +90,51 @@ void GDB_RunServer(GDBServer *server) server_run(&server->super); } +GDBContext *GDB_SelectAvailableContext(GDBServer *server, u16 minPort, u16 maxPort) +{ + GDBContext *ctx; + u16 port; + + // Get a context + u32 id; + for(id = 0; id < MAX_DEBUG && (server->ctxs[id].flags & GDB_FLAG_SELECTED); id++); + if(id < MAX_DEBUG) + ctx = &server->ctxs[id]; + else + return NULL; + + // Get a port + for (port = minPort; port < maxPort; port++) + { + bool portUsed = false; + for(id = 0; id < MAX_DEBUG; id++) + { + if((server->ctxs[id].flags & GDB_FLAG_SELECTED) && server->ctxs[id].localPort == port) + portUsed = true; + } + + if (!portUsed) + break; + } + + if (port >= maxPort) + { + RecursiveLock_Lock(&ctx->lock); + ctx->flags = ~GDB_FLAG_SELECTED; + RecursiveLock_Unlock(&ctx->lock); + return NULL; + } + + else + { + RecursiveLock_Lock(&ctx->lock); + ctx->flags |= GDB_FLAG_SELECTED; + ctx->localPort = port; + RecursiveLock_Unlock(&ctx->lock); + return ctx; + } +} + int GDB_AcceptClient(GDBContext *ctx) { RecursiveLock_Lock(&ctx->lock); @@ -148,27 +193,36 @@ int GDB_CloseClient(GDBContext *ctx) svcClearEvent(ctx->clientAcceptedEvent); ctx->eventToWaitFor = ctx->clientAcceptedEvent; + + ctx->localPort = 0; RecursiveLock_Unlock(&ctx->lock); return 0; } GDBContext *GDB_GetClient(GDBServer *server, u16 port) { - if(port < GDB_PORT_BASE || port >= GDB_PORT_BASE + sizeof(server->ctxs) / sizeof(GDBContext)) - return NULL; + GDBContext *ctx = NULL; + if (port >= GDB_PORT_BASE && port < GDB_PORT_BASE + MAX_DEBUG) + { + for (u32 i = 0; i < MAX_DEBUG; i++) + { + if ((server->ctxs[i].flags & GDB_FLAG_SELECTED) && server->ctxs[i].localPort == port) + { + ctx = &server->ctxs[i]; + break; + } + } + } - GDBContext *ctx = &server->ctxs[port - GDB_PORT_BASE]; - if(!(ctx->flags & GDB_FLAG_USED) && (ctx->flags & GDB_FLAG_SELECTED)) + if (ctx != NULL) { RecursiveLock_Lock(&ctx->lock); ctx->flags |= GDB_FLAG_USED; ctx->state = GDB_STATE_CONNECTED; RecursiveLock_Unlock(&ctx->lock); - - return ctx; } - return NULL; + return ctx; } void GDB_ReleaseClient(GDBServer *server, GDBContext *ctx) diff --git a/sysmodules/rosalina/source/menus/process_list.c b/sysmodules/rosalina/source/menus/process_list.c index f4bfe83..9c3ae6f 100644 --- a/sysmodules/rosalina/source/menus/process_list.c +++ b/sysmodules/rosalina/source/menus/process_list.c @@ -73,7 +73,7 @@ static inline int ProcessListMenu_FormatInfoLine(char *out, const ProcessInfo *i else { checkbox = "(W) "; - sprintf(commentBuf, "Port: %ld", GDB_PORT_BASE + id); + sprintf(commentBuf, "Port: %hu", gdbServer.ctxs[id].localPort); } } @@ -584,10 +584,9 @@ static inline void ProcessListMenu_HandleSelected(const ProcessInfo *info) u32 id; for(id = 0; id < MAX_DEBUG && (!(gdbServer.ctxs[id].flags & GDB_FLAG_SELECTED) || gdbServer.ctxs[id].pid != info->pid); id++); - GDBContext *ctx = &gdbServer.ctxs[id]; - if(id < MAX_DEBUG) { + GDBContext *ctx = &gdbServer.ctxs[id]; if(ctx->flags & GDB_FLAG_USED) { RecursiveLock_Lock(&ctx->lock); @@ -601,20 +600,15 @@ static inline void ProcessListMenu_HandleSelected(const ProcessInfo *info) { RecursiveLock_Lock(&ctx->lock); ctx->flags &= ~GDB_FLAG_SELECTED; + ctx->localPort = 0; RecursiveLock_Unlock(&ctx->lock); } } else { - for(id = 0; id < MAX_DEBUG && gdbServer.ctxs[id].flags & GDB_FLAG_SELECTED; id++); - if(id < MAX_DEBUG) - { - ctx = &gdbServer.ctxs[id]; - RecursiveLock_Lock(&ctx->lock); + GDBContext *ctx = GDB_SelectAvailableContext(&gdbServer, GDB_PORT_BASE, GDB_PORT_BASE + MAX_DEBUG); + if (ctx != NULL) ctx->pid = info->pid; - ctx->flags |= GDB_FLAG_SELECTED; - RecursiveLock_Unlock(&ctx->lock); - } } }