From eef22f8701175f46254ba8c72fbd79a92c90c0fa Mon Sep 17 00:00:00 2001 From: TuxSH Date: Thu, 18 Apr 2019 22:58:53 +0200 Subject: [PATCH] Fix "debug next process" with hbldr homebrew --- sysmodules/rosalina/include/menus/debugger.h | 2 +- sysmodules/rosalina/include/pmdbgext.h | 1 + sysmodules/rosalina/include/task_runner.h | 22 ++++++++++ sysmodules/rosalina/source/gdb/server.c | 5 +++ sysmodules/rosalina/source/main.c | 10 +++-- sysmodules/rosalina/source/menus/debugger.c | 6 ++- sysmodules/rosalina/source/task_runner.c | 45 ++++++++++++++++++++ 7 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 sysmodules/rosalina/include/task_runner.h create mode 100644 sysmodules/rosalina/source/task_runner.c diff --git a/sysmodules/rosalina/include/menus/debugger.h b/sysmodules/rosalina/include/menus/debugger.h index 8a097a1..c24d813 100644 --- a/sysmodules/rosalina/include/menus/debugger.h +++ b/sysmodules/rosalina/include/menus/debugger.h @@ -31,7 +31,7 @@ extern Menu debuggerMenu; -void debuggerSetNextApplicationDebugHandle(Handle debug); +void debuggerFetchAndSetNextApplicationDebugHandleTask(void *argdata); void DebuggerMenu_EnableDebugger(void); void DebuggerMenu_DisableDebugger(void); void DebuggerMenu_DebugNextApplicationByForce(void); diff --git a/sysmodules/rosalina/include/pmdbgext.h b/sysmodules/rosalina/include/pmdbgext.h index f5d1236..788fd32 100644 --- a/sysmodules/rosalina/include/pmdbgext.h +++ b/sysmodules/rosalina/include/pmdbgext.h @@ -4,6 +4,7 @@ #pragma once #include <3ds/services/pmapp.h> +#include <3ds/services/pmdbg.h> Result PMDBG_GetCurrentAppTitleIdAndPid(u64 *outTitleId, u32 *outPid); Result PMDBG_DebugNextApplicationByForce(void); diff --git a/sysmodules/rosalina/include/task_runner.h b/sysmodules/rosalina/include/task_runner.h new file mode 100644 index 0000000..9e924d8 --- /dev/null +++ b/sysmodules/rosalina/include/task_runner.h @@ -0,0 +1,22 @@ +#pragma once + +#include <3ds/types.h> +#include <3ds/synchronization.h> +#include "MyThread.h" + +typedef struct TaskRunner { + LightEvent readyEvent; + LightEvent parametersSetEvent; + void (*task)(void *argdata); + u8 argStorage[0x40]; +} TaskRunner; + +extern TaskRunner g_taskRunner; + +MyThread *taskRunnerCreateThread(void); + +void TaskRunner_Init(void); +void TaskRunner_RunTask(void (*task)(void *argdata), void *argdata, size_t argsize); +/// Thread function +void TaskRunner_HandleTasks(void); +void TaskRunner_WaitReady(void); \ No newline at end of file diff --git a/sysmodules/rosalina/source/gdb/server.c b/sysmodules/rosalina/source/gdb/server.c index 6efb593..1d5c872 100644 --- a/sysmodules/rosalina/source/gdb/server.c +++ b/sysmodules/rosalina/source/gdb/server.c @@ -36,6 +36,7 @@ #include "gdb/watchpoints.h" #include "gdb/breakpoints.h" #include "gdb/stop_point.h" +#include "task_runner.h" Result GDB_InitializeServer(GDBServer *server) { @@ -225,6 +226,10 @@ GDBContext *GDB_GetClient(GDBServer *server, u16 port) GDB_UnlockAllContexts(server); return NULL; } + + if (ctx->localPort == GDB_PORT_BASE + MAX_DEBUG) + TaskRunner_WaitReady(); // Finish grabbing new process debug, if anything... + ctx->flags |= GDB_FLAG_USED; ctx->state = GDB_STATE_CONNECTED; ctx->parent = server; diff --git a/sysmodules/rosalina/source/main.c b/sysmodules/rosalina/source/main.c index 9782bed..74a7d27 100644 --- a/sysmodules/rosalina/source/main.c +++ b/sysmodules/rosalina/source/main.c @@ -38,6 +38,8 @@ #include "menus/debugger.h" #include "menus/screen_filters.h" +#include "task_runner.h" + static Result stealFsReg(void) { Result ret = 0; @@ -157,10 +159,10 @@ static void handleTermNotification(u32 notificationId) static void handleNextApplicationDebuggedByForce(u32 notificationId) { + int dummy; (void)notificationId; - Handle debug = 0; - PMDBG_RunQueuedProcess(&debug); - debuggerSetNextApplicationDebugHandle(debug); + // Following call needs to be async because pm -> Loader depends on rosalina hb:ldr, handled in this very thread. + TaskRunner_RunTask(debuggerFetchAndSetNextApplicationDebugHandleTask, &dummy, 0); } static const ServiceManagerServiceEntry services[] = { @@ -191,11 +193,13 @@ int main(void) svcBreak(USERBREAK_ASSERT); MyThread *menuThread = menuCreateThread(); + MyThread *taskRunnerThread = taskRunnerCreateThread(); if (R_FAILED(ServiceManager_Run(services, notifications, NULL))) svcBreak(USERBREAK_PANIC); MyThread_Join(menuThread, -1LL); + MyThread_Join(taskRunnerThread, -1LL); return 0; } diff --git a/sysmodules/rosalina/source/menus/debugger.c b/sysmodules/rosalina/source/menus/debugger.c index 6d3871d..fc0d078 100644 --- a/sysmodules/rosalina/source/menus/debugger.c +++ b/sysmodules/rosalina/source/menus/debugger.c @@ -34,6 +34,7 @@ #include "gdb/debug.h" #include "gdb/monitor.h" #include "gdb/net.h" +#include "pmdbgext.h" Menu debuggerMenu = { "Debugger options menu", @@ -68,8 +69,11 @@ MyThread *debuggerCreateDebugThread(void) return &debuggerDebugThread; } -void debuggerSetNextApplicationDebugHandle(Handle debug) +void debuggerFetchAndSetNextApplicationDebugHandleTask(void *argdata) { + (void)argdata; + Handle debug = 0; + PMDBG_RunQueuedProcess(&debug); GDB_LockAllContexts(&gdbServer); nextApplicationGdbCtx->debug = debug; if (debug == 0) diff --git a/sysmodules/rosalina/source/task_runner.c b/sysmodules/rosalina/source/task_runner.c new file mode 100644 index 0000000..b651349 --- /dev/null +++ b/sysmodules/rosalina/source/task_runner.c @@ -0,0 +1,45 @@ +#include <3ds.h> +#include +#include "task_runner.h" + +TaskRunner g_taskRunner; + +static MyThread taskRunnerThread; +static u8 ALIGN(8) taskRunnerThreadStack[0x1000]; + +MyThread *taskRunnerCreateThread(void) +{ + TaskRunner_Init(); + MyThread_Create(&taskRunnerThread, TaskRunner_HandleTasks, taskRunnerThreadStack, THREAD_STACK_SIZE, 0x20, 1); + return &taskRunnerThread; +} + +void TaskRunner_Init(void) +{ + memset(&g_taskRunner, 0, sizeof(TaskRunner)); + LightEvent_Init(&g_taskRunner.readyEvent, RESET_ONESHOT); + LightEvent_Init(&g_taskRunner.parametersSetEvent, RESET_ONESHOT); +} + +void TaskRunner_RunTask(void (*task)(void *argdata), void *argdata, size_t argsize) +{ + argsize = argsize > sizeof(g_taskRunner.argStorage) ? sizeof(g_taskRunner.argStorage) : argsize; + LightEvent_Wait(&g_taskRunner.readyEvent); + g_taskRunner.task = task; + memcpy(g_taskRunner.argStorage, argdata, argsize); + LightEvent_Signal(&g_taskRunner.parametersSetEvent); +} + +void TaskRunner_HandleTasks(void) +{ + for (;;) { + LightEvent_Signal(&g_taskRunner.readyEvent); + LightEvent_Wait(&g_taskRunner.parametersSetEvent); + g_taskRunner.task(g_taskRunner.argStorage); + } +} + +void TaskRunner_WaitReady(void) +{ + LightEvent_Wait(&g_taskRunner.readyEvent); +} \ No newline at end of file