From 0556fbbd990b069585aca983fa166abf83c7f000 Mon Sep 17 00:00:00 2001 From: fincs Date: Thu, 6 Dec 2018 02:18:50 +0100 Subject: [PATCH] Only apply SM close bug workaround to very old apps (use absence of MOD0 as heuristic) --- source/main.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/source/main.c b/source/main.c index b74cd3c..4dd7d4d 100644 --- a/source/main.c +++ b/source/main.c @@ -16,6 +16,7 @@ static bool g_isApplication = 0; static NsApplicationControlData g_applicationControlData; static bool g_isAutomaticGameplayRecording = 0; +static bool g_smCloseWorkaround = false; static u8 g_savedTls[0x100]; @@ -220,8 +221,13 @@ void loadNro(void) size_t rw_size=0; Result rc=0; - svcSleepThread(1000000000);//Wait for sm-sysmodule to handle closing the sm session from this process. Without this delay smInitialize will fail once eventually used later. - //TODO: Lower the above delay-value? + if (g_smCloseWorkaround) { + // For old applications, wait for SM to handle closing the SM session from this process. + // If we don't do this, smInitialize will fail once eventually used later. + // This is caused by a bug in old versions of libnx that was fixed in commit 68a77ac950. + g_smCloseWorkaround = false; + svcSleepThread(1000000000); + } memcpy((u8*)armGetTls() + 0x100, g_savedTls, 0x100); @@ -298,6 +304,10 @@ void loadNro(void) rw_size = header->segments[2].size + header->bss_size; rw_size = (rw_size+0xFFF) & ~0xFFF; + bool has_mod0 = false; + if (start->mod_offset > 0 && start->mod_offset <= (total_size-0x24)) // Validate MOD0 offset + has_mod0 = *(uint32_t*)(nrobuf + start->mod_offset) == 0x30444F4D; // Validate MOD0 header + int i; for (i=0; i<3; i++) { @@ -397,6 +407,13 @@ void loadNro(void) memset(__stack_top - STACK_SIZE, 0, STACK_SIZE); + if (!has_mod0) { + // Apply sm-close workaround to NROs which do not contain a valid MOD0 header. + // This heuristic is based on the fact that MOD0 support was added very shortly after + // the fix for the sm-close bug (in fact, two commits later). + g_smCloseWorkaround = true; + } + extern NORETURN void nroEntrypointTrampoline(u64 entries_ptr, u64 handle, u64 entrypoint); nroEntrypointTrampoline((u64) entries, -1, entrypoint); }