From c8a24a0f1227ff1901e4fa86db2f0e7292884b92 Mon Sep 17 00:00:00 2001 From: kynex7510 Date: Tue, 19 Nov 2024 16:15:10 +0100 Subject: [PATCH] App section info --- Include/CTRL/App.h | 31 +++++++++++++++++ Include/CTRL/Env.h | 22 ------------ Include/CTRL/Exception.h | 2 +- Source/App.c | 72 ++++++++++++++++++++++++++++++++++++++++ Source/Env.c | 35 ------------------- Source/Exception.c | 5 +-- Source/Memory.c | 12 +++---- Tests/Main.c | 23 ++++++++++--- 8 files changed, 132 insertions(+), 70 deletions(-) create mode 100644 Include/CTRL/App.h delete mode 100644 Include/CTRL/Env.h create mode 100644 Source/App.c delete mode 100644 Source/Env.c diff --git a/Include/CTRL/App.h b/Include/CTRL/App.h new file mode 100644 index 0000000..429a001 --- /dev/null +++ b/Include/CTRL/App.h @@ -0,0 +1,31 @@ +#ifndef _CTRL_APP_H +#define _CTRL_APP_H + +#include "CTRL/Types.h" + +#if defined(__cplusplus) +extern "C" { +#endif // __cplusplus + +typedef enum { + Env_Luma, + Env_Citra, +} CTRLEnv; + +typedef struct { + u32 textAddr; + size_t textSize; + u32 rodataAddr; + size_t rodataSize; + u32 dataAddr; + size_t dataSize; +} CTRLAppSectionInfo; + +CTRLEnv ctrlEnv(void); +const CTRLAppSectionInfo* ctrlAppSectionInfo(void); + +#if defined(__cplusplus) +} +#endif // __cplusplus + +#endif // _CTRL_APP_H \ No newline at end of file diff --git a/Include/CTRL/Env.h b/Include/CTRL/Env.h deleted file mode 100644 index 690ae54..0000000 --- a/Include/CTRL/Env.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _CTRL_ENV_H -#define _CTRL_ENV_H - -#include "CTRL/Types.h" - -typedef enum { - Env_Unknown, - Env_Luma, - Env_Citra, -} CTRLEnv; - -#if defined(__cplusplus) -extern "C" { -#endif // __cplusplus - -CTRLEnv ctrlDetectEnv(void); - -#if defined(__cplusplus) -} -#endif // __cplusplus - -#endif /* _CTRL_ENV_H */ \ No newline at end of file diff --git a/Include/CTRL/Exception.h b/Include/CTRL/Exception.h index 636cf05..80c4e6f 100644 --- a/Include/CTRL/Exception.h +++ b/Include/CTRL/Exception.h @@ -11,9 +11,9 @@ extern "C" { typedef void(*CTRLExHandlerFn)(ERRF_ExceptionData*); +bool ctrlExceptionHandlingIsSupported(void); bool ctrlEnableExceptionHandling(void); void ctrlDisableExceptionHandling(void); -bool ctrlExceptionHandlingIsSupported(void); bool ctrlSetExceptionHandler(CTRLExHandlerFn fn, size_t index); bool ctrlClearExceptionHandler(size_t index); diff --git a/Source/App.c b/Source/App.c new file mode 100644 index 0000000..6c0b8e5 --- /dev/null +++ b/Source/App.c @@ -0,0 +1,72 @@ +#include "CTRL/App.h" +#include "CTRL/Memory.h" + +#include + +#define LUMA_TYPE 0x10000 +#define CITRA_TYPE 0x20000 + +#define TEXT_ADDR_TYPE 0x10005 +#define TEXT_SIZE_TYPE 0x10002 +#define RODATA_ADDR_TYPE 0x10006 +#define RODATA_SIZE_TYPE 0x10003 +#define DATA_ADDR_TYPE 0x10007 +#define DATA_SIZE_TYPE 0x10004 + +#define LUMA_SYSTEM_VERSION(major, minor, revision) (((major) << 24) | ((minor) << 16) | ((revision) << 8)) + +static CTRLEnv g_Env; +static CTRLAppSectionInfo g_AppSectionInfo; + +static CTRL_INLINE bool ctrl_detectEnv(CTRLEnv* env) { + s64 check = 0; + + // Detected luma 8.0.0+. + if (R_SUCCEEDED(svcGetSystemInfo(&check, LUMA_TYPE, 0)) && (check >= LUMA_SYSTEM_VERSION(8, 0, 0))) { + *env = Env_Luma; + return true; + } + + // Detected citra. + if (R_SUCCEEDED(svcGetSystemInfo(&check, CITRA_TYPE, 0)) && (check == 1)) { + *env = Env_Citra; + return true; + } + + return false; +} + +static CTRL_INLINE Result ctrl_getAppSectionInfo(CTRLAppSectionInfo* out) { + s64 tmp; + Result ret; + +#define READ_INFO(type, outMember) \ + ret = svcGetProcessInfo(&tmp, CUR_PROCESS_HANDLE, ((type))); \ + if (R_FAILED(ret)) \ + return ret; \ + \ + outMember = tmp; + + READ_INFO(TEXT_ADDR_TYPE, out->textAddr); + READ_INFO(TEXT_SIZE_TYPE, out->textSize); + READ_INFO(RODATA_ADDR_TYPE, out->rodataAddr); + READ_INFO(RODATA_SIZE_TYPE, out->rodataSize); + READ_INFO(DATA_ADDR_TYPE, out->dataAddr); + READ_INFO(DATA_SIZE_TYPE, out->dataSize); + +#undef READ_INFO + return 0; +} + +static __attribute((constructor)) void ctrl_initEnv(void) { + if (!ctrl_detectEnv(&g_Env)) + svcBreak(USERBREAK_PANIC); +} + +static __attribute((constructor)) void ctrl_initAppSectionInfo(void) { + if (R_FAILED(ctrl_getAppSectionInfo(&g_AppSectionInfo))) + svcBreak(USERBREAK_PANIC); +} + +CTRLEnv ctrlEnv(void) { return g_Env; } +const CTRLAppSectionInfo* ctrlAppSectionInfo(void) { return &g_AppSectionInfo; } \ No newline at end of file diff --git a/Source/Env.c b/Source/Env.c deleted file mode 100644 index d91f71b..0000000 --- a/Source/Env.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "CTRL/Env.h" - -#define LUMA_TYPE 0x10000 -#define CITRA_TYPE 0x20000 - -#define NOT_INIT (CTRLEnv)-1 - -#define LUMA_SYSTEM_VERSION(major, minor, revision) (((major) << 24) | ((minor) << 16) | ((revision) << 8)) - -static s32 g_Env = NOT_INIT; - -CTRLEnv ctrlDetectEnv(void) { - CTRLEnv env = (CTRLEnv)g_Env; - - if (env == NOT_INIT) { - s64 check = 0; - - if (R_SUCCEEDED(svcGetSystemInfo(&check, LUMA_TYPE, 0)) && (check >= LUMA_SYSTEM_VERSION(8, 0, 0))) { - // Detected luma 8.0.0+. - env = Env_Luma; - } else if (R_SUCCEEDED(svcGetSystemInfo(&check, CITRA_TYPE, 0)) && (check == 1)) { - // Detected citra. - env = Env_Citra; - } else { - // Detected nothing. - env = Env_Unknown; - } - - do { - __ldrex(&g_Env); - } while (__strex(&g_Env, (s32)env)); - } - - return env; -} \ No newline at end of file diff --git a/Source/Exception.c b/Source/Exception.c index 86c1713..c6a50f0 100644 --- a/Source/Exception.c +++ b/Source/Exception.c @@ -1,5 +1,5 @@ #include "CTRL/Exception.h" -#include "CTRL/Env.h" +#include "CTRL/App.h" #define TLS_EX_HANDLER_SLOT 16 #define TLS_EX_STACK_SLOT 17 @@ -29,6 +29,8 @@ static void ctrl_disableExHandlingImpl(u32* tls) { tls[TLS_EX_CTX_SLOT] = 0; } +bool ctrlExceptionHandlingIsSupported(void) { return ctrlEnv() == Env_Luma; } + bool ctrlEnableExceptionHandling(void) { if (ctrlExceptionHandlingIsSupported()) { u32* tls = (u32*)getThreadLocalStorage(); @@ -42,7 +44,6 @@ bool ctrlEnableExceptionHandling(void) { } void ctrlDisableExceptionHandling(void) { ctrl_disableExHandlingImpl((u32*)getThreadLocalStorage()); } -bool ctrlExceptionHandlingIsSupported(void) { return ctrlDetectEnv() != Env_Citra; } bool ctrlSetExceptionHandler(CTRLExHandlerFn fn, size_t index) { if (!ctrlExceptionHandlingIsSupported() || (index >= CTRL_MAX_EX_HANDLERS)) diff --git a/Source/Memory.c b/Source/Memory.c index 17c8911..9ae28ee 100644 --- a/Source/Memory.c +++ b/Source/Memory.c @@ -7,20 +7,20 @@ * -- It enforces permission checks, so MEMOP_PROT is a no-go; but it's "fine" as permissions arent really emulated. * - svcQueryMemory will never return whether the page is executable; svcQueryProcessMemory does. * -- Once again, citra doesn't have this limitation. - * - HOS doesn't expose anything for cleaning the instruction cache. + * - Both luma and citra support cleaning the instruction cache. * - When mapping/unmapping svcControlProcessMemory expects a region of pages. * -- When unmapping, it's possible that the mirrored memory is made of multiple regions. */ #include "CTRL/Memory.h" -#include "CTRL/Env.h" +#include "CTRL/App.h" #include #define DCACHE_THRESHOLD 0x700000 static CTRL_INLINE void ctrl_flushInsnCache(void) { - switch (ctrlDetectEnv()) { + switch (ctrlEnv()) { case Env_Luma: case Env_Citra: asm("svc 0x94"); @@ -79,7 +79,7 @@ Result ctrlQueryRegion(u32 addr, MemInfo* memInfo) { } Result ctrlChangePerms(u32 addr, size_t size, MemPerm perms) { - if (ctrlDetectEnv() == Env_Citra) + if (ctrlEnv() == Env_Citra) return 0; Handle proc; @@ -97,7 +97,7 @@ Result ctrlChangePerms(u32 addr, size_t size, MemPerm perms) { Result ctrlMirror(u32 addr, u32 source, size_t size) { Result ret = 0; - if (ctrlDetectEnv() == Env_Citra) { + if (ctrlEnv() == Env_Citra) { u32 out; ret = svcControlMemory(&out, addr, source, size, MEMOP_MAP, MEMPERM_READWRITE); } else { @@ -115,7 +115,7 @@ Result ctrlMirror(u32 addr, u32 source, size_t size) { Result ctrlUnmirror(u32 addr, u32 source, size_t size) { Result ret = 0; - bool isCitra = (ctrlDetectEnv() == Env_Citra); + bool isCitra = (ctrlEnv() == Env_Citra); Handle proc = CUR_PROCESS_HANDLE; if (!isCitra) { diff --git a/Tests/Main.c b/Tests/Main.c index 58d160d..1a0e0a9 100644 --- a/Tests/Main.c +++ b/Tests/Main.c @@ -1,6 +1,7 @@ #include "CTRL/Memory.h" #include "CTRL/Hook.h" #include "CTRL/Exception.h" +#include "CTRL/App.h" #include #include @@ -12,6 +13,20 @@ #define CODE_REGION_START 0x100000 #define CODE_REGION_SIZE 0x3F00000 +static bool test1(void) { + printf("=== APP INFO TEST ===\n"); + + const CTRLAppSectionInfo* info = ctrlAppSectionInfo(); + + printf("Total size: 0x%08x\n", info->textSize + info->rodataSize + info->dataSize); + printf("- .text: 0x%08x-0x%08x\n", info->textAddr, info->textAddr + info->textSize); + printf("- .rodata: 0x%08x-0x%08x\n", info->rodataAddr, info->rodataAddr + info->rodataSize); + printf("- .data: 0x%08x-0x%08x\n", info->dataAddr, info->dataAddr + info->dataSize); + + printf("SUCCESS\n"); + return true; +} + static void exHandler0(ERRF_ExceptionData* info) { printf("exHandler0(): This is called first (not handling)\n"); } @@ -22,7 +37,7 @@ static void exHandler1(ERRF_ExceptionData* info) { info->regs.pc += 4; } -static bool test1(void) { +static bool test2(void) { printf("=== EXCEPTION HANDLER TEST ===\n"); if (ctrlExceptionHandlingIsSupported()) { @@ -50,7 +65,7 @@ static bool test1(void) { static int myRand(void) { return RAND_EXPECTED_RET; } -static bool test2(void) { +static bool test3(void) { printf("=== HOOK TEST ===\n"); CTRLHook hook; @@ -95,7 +110,7 @@ static bool test2(void) { return true; } -static bool test3(void) { +static bool test4(void) { #define FUNC_PARAM_1 5 #define FUNC_PARAM_2 3 @@ -193,7 +208,7 @@ static bool test3(void) { int main(int argc, char* argv[]) { typedef bool(*Test_t)(void); - Test_t tests[] = { test1, test2, test3 }; + Test_t tests[] = { test1, test2, test3, test4 }; const size_t numTests = sizeof(tests) / sizeof(Test_t);