From 553f8d2533e5e6a23cc89c5e674a01bc6e84aed7 Mon Sep 17 00:00:00 2001 From: TuxSH Date: Fri, 12 Jan 2018 11:20:17 +0100 Subject: [PATCH 1/8] Remove lto for sysmodules --- sysmodules/loader/Makefile | 4 ++-- sysmodules/rosalina/Makefile | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sysmodules/loader/Makefile b/sysmodules/loader/Makefile index 532d934..e08ad6a 100755 --- a/sysmodules/loader/Makefile +++ b/sysmodules/loader/Makefile @@ -20,7 +20,7 @@ LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) INCLUDE := $(foreach dir,$(LIBDIRS),-I$(dir)/include) ASFLAGS := -mcpu=mpcore -mfloat-abi=hard -CFLAGS := -Wall -Wextra $(ASFLAGS) -fno-builtin -std=c11 -O2 -flto -ffast-math $(INCLUDE) -DARM11 -D_3DS +CFLAGS := -Wall -Wextra $(ASFLAGS) -fno-builtin -std=c11 -O2 -ffast-math $(INCLUDE) -DARM11 -D_3DS LDFLAGS := -specs=3dsx.specs $(ASFLAGS) -Wl,--section-start,.text=0x14000000 objects = $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ @@ -51,7 +51,7 @@ $(dir_build)/%.bin.o: $(dir_build)/%.bin @$(bin2o) $(dir_build)/%.bin: $(dir_patches)/%.s - @mkdir -p "$(@D)" + @mkdir -p "$(@D)" @armips $< $(dir_build)/memory.o $(dir_build)/strings.o: CFLAGS += -O3 diff --git a/sysmodules/rosalina/Makefile b/sysmodules/rosalina/Makefile index 24656de..58ab220 100644 --- a/sysmodules/rosalina/Makefile +++ b/sysmodules/rosalina/Makefile @@ -21,7 +21,7 @@ INCLUDE := $(foreach dir,$(LIBDIRS),-I$(dir)/include) ARCH := -mcpu=mpcore -mfloat-abi=hard ASFLAGS := -g $(ARCH) -CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -mtp=soft -fno-builtin -std=c11 -O2 -flto -ffast-math -mword-relocations \ +CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -mtp=soft -fno-builtin -std=c11 -O2 -ffast-math -mword-relocations \ -fomit-frame-pointer -ffunction-sections -fdata-sections $(INCLUDE) -I$(dir_include) -DARM11 -D_3DS LDFLAGS := -specs=3dsx.specs -g $(ARCH) -mtp=soft -Wl,--section-start,.text=0x14000000 -Wl,--gc-sections From 9074688491d11461f3b5942d34f36d197f8c4c43 Mon Sep 17 00:00:00 2001 From: TuxSH Date: Mon, 15 Jan 2018 02:27:07 +0100 Subject: [PATCH 2/8] Make srvGetServiceHandle non-blocking if service port is full in all cases --- sysmodules/rosalina/source/MyThread.c | 12 ++++++++++++ sysmodules/rosalina/source/main.c | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/sysmodules/rosalina/source/MyThread.c b/sysmodules/rosalina/source/MyThread.c index 6d420f5..8ede9eb 100644 --- a/sysmodules/rosalina/source/MyThread.c +++ b/sysmodules/rosalina/source/MyThread.c @@ -26,10 +26,22 @@ #include "MyThread.h" #include "memory.h" +#include <3ds/srv.h> static void _thread_begin(void* arg) { MyThread *t = (MyThread *)arg; + + // ROSALINA HACKJOB BEGIN + // NORMAL APPS SHOULD NOT DO THIS, EVER + u32 *tls = (u32 *)getThreadLocalStorage(); + memset(tls, 0, 0x80); + tls[0] = 0x21545624; + // ROSALINA HACKJOB END + + // Rosalina specific: + srvSetBlockingPolicy(true); // GetServiceHandle nonblocking if service port is full + t->ep(); MyThread_Exit(); } diff --git a/sysmodules/rosalina/source/main.c b/sysmodules/rosalina/source/main.c index e75ffac..1dafa6a 100644 --- a/sysmodules/rosalina/source/main.c +++ b/sysmodules/rosalina/source/main.c @@ -89,6 +89,16 @@ void initSystem() ProcessPatchesMenu_PatchUnpatchFSDirectly(); __sync_init(); __appInit(); + + // ROSALINA HACKJOB BEGIN + // NORMAL APPS SHOULD NOT DO THIS, EVER + u32 *tls = (u32 *)getThreadLocalStorage(); + memset(tls, 0, 0x80); + tls[0] = 0x21545624; + // ROSALINA HACKJOB END + + // Rosalina specific: + srvSetBlockingPolicy(true); // GetServiceHandle nonblocking if service port is full } bool terminationRequest = false; From 11f820efa75ca2093635aa94f3111375d644a976 Mon Sep 17 00:00:00 2001 From: TuxSH Date: Mon, 15 Jan 2018 02:52:50 +0100 Subject: [PATCH 3/8] Check service existence before GetServiceHandle --- sysmodules/rosalina/source/menu.c | 5 ++++- sysmodules/rosalina/source/menus/debugger.c | 10 ++++------ sysmodules/rosalina/source/minisoc.c | 15 +++++++++++++-- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/sysmodules/rosalina/source/menu.c b/sysmodules/rosalina/source/menu.c index f396460..d60af63 100644 --- a/sysmodules/rosalina/source/menu.c +++ b/sysmodules/rosalina/source/menu.c @@ -193,13 +193,16 @@ static void menuDraw(Menu *menu, u32 selected) s64 out; u32 version, commitHash; bool isRelease; + bool isMcuHwcRegistered; - if(R_SUCCEEDED(mcuHwcInit())) + if(R_SUCCEEDED(srvIsServiceRegistered(&isMcuHwcRegistered, "mcu::HWC")) && isMcuHwcRegistered && R_SUCCEEDED(mcuHwcInit())) { if(R_FAILED(MCUHWC_GetBatteryLevel(&batteryLevel))) batteryLevel = 255; mcuHwcExit(); } + else + batteryLevel = 255; svcGetSystemInfo(&out, 0x10000, 0); version = (u32)out; diff --git a/sysmodules/rosalina/source/menus/debugger.c b/sysmodules/rosalina/source/menus/debugger.c index 3b8632c..82b02bd 100644 --- a/sysmodules/rosalina/source/menus/debugger.c +++ b/sysmodules/rosalina/source/menus/debugger.c @@ -69,12 +69,10 @@ void DebuggerMenu_EnableDebugger(void) bool done = false, alreadyEnabled = gdbServer.super.running; Result res = 0; char buf[65]; - bool cantStart; - Handle dummy; + bool isSocURegistered; - res = OpenProcessByName("socket", &dummy); - cantStart = R_FAILED(res); - svcCloseHandle(dummy); + res = srvIsServiceRegistered(&isSocURegistered, "soc:U"); + isSocURegistered = R_SUCCEEDED(res) && isSocURegistered; Draw_Lock(); Draw_ClearFramebuffer(); @@ -88,7 +86,7 @@ void DebuggerMenu_EnableDebugger(void) if(alreadyEnabled) Draw_DrawString(10, 30, COLOR_WHITE, "Already enabled!"); - else if(cantStart) + else if(!isSocURegistered) Draw_DrawString(10, 30, COLOR_WHITE, "Can't start the debugger before the system has fi-\nnished loading."); else { diff --git a/sysmodules/rosalina/source/minisoc.c b/sysmodules/rosalina/source/minisoc.c index 76c2d22..e894ed6 100644 --- a/sysmodules/rosalina/source/minisoc.c +++ b/sysmodules/rosalina/source/minisoc.c @@ -80,6 +80,18 @@ Result miniSocInit() u32 tmp = 0; Result ret = 0; + bool isSocURegistered; + + ret = srvIsServiceRegistered(&isSocURegistered, "soc:U"); + if(ret != 0) goto cleanup; + if(!isSocURegistered) + { + ret = -1; + goto cleanup; + } + + ret = srvGetServiceHandle(&SOCU_handle, "soc:U"); + if(ret != 0) goto cleanup; ret = svcControlMemory(&tmp, socContextAddr, 0, socContextSize, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE); if(ret != 0) goto cleanup; @@ -89,8 +101,7 @@ Result miniSocInit() ret = svcCreateMemoryBlock(&socMemhandle, (u32)socContextAddr, socContextSize, 0, 3); if(ret != 0) goto cleanup; - ret = srvGetServiceHandle(&SOCU_handle, "soc:U"); - if(ret != 0) goto cleanup; + ret = SOCU_Initialize(socMemhandle, socContextSize); if(ret != 0) goto cleanup; From e40b547bb62847a39901f5c7c76e1299d359e965 Mon Sep 17 00:00:00 2001 From: Nanquitas Date: Thu, 18 Jan 2018 15:33:24 +0100 Subject: [PATCH 4/8] gdb: new getmemregions command --- .../rosalina/include/gdb/remote_command.h | 1 + .../rosalina/source/gdb/remote_command.c | 79 +++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/sysmodules/rosalina/include/gdb/remote_command.h b/sysmodules/rosalina/include/gdb/remote_command.h index d89e6f7..ba57b46 100644 --- a/sysmodules/rosalina/include/gdb/remote_command.h +++ b/sysmodules/rosalina/include/gdb/remote_command.h @@ -34,6 +34,7 @@ GDB_DECLARE_REMOTE_COMMAND_HANDLER(SyncRequestInfo); GDB_DECLARE_REMOTE_COMMAND_HANDLER(TranslateHandle); GDB_DECLARE_REMOTE_COMMAND_HANDLER(GetMmuConfig); +GDB_DECLARE_REMOTE_COMMAND_HANDLER(GetMemRegions); GDB_DECLARE_REMOTE_COMMAND_HANDLER(FlushCaches); GDB_DECLARE_REMOTE_COMMAND_HANDLER(ToggleExternalMemoryAccess); diff --git a/sysmodules/rosalina/source/gdb/remote_command.c b/sysmodules/rosalina/source/gdb/remote_command.c index 172224f..41c1005 100644 --- a/sysmodules/rosalina/source/gdb/remote_command.c +++ b/sysmodules/rosalina/source/gdb/remote_command.c @@ -39,6 +39,7 @@ struct { "syncrequestinfo" , GDB_REMOTE_COMMAND_HANDLER(SyncRequestInfo) }, { "translatehandle" , GDB_REMOTE_COMMAND_HANDLER(TranslateHandle) }, { "getmmuconfig" , GDB_REMOTE_COMMAND_HANDLER(GetMmuConfig) }, + { "getmemregions" , GDB_REMOTE_COMMAND_HANDLER(GetMemRegions) }, { "flushcaches" , GDB_REMOTE_COMMAND_HANDLER(FlushCaches) }, { "toggleextmemaccess", GDB_REMOTE_COMMAND_HANDLER(ToggleExternalMemoryAccess) }, }; @@ -226,6 +227,84 @@ GDB_DECLARE_REMOTE_COMMAND_HANDLER(GetMmuConfig) return GDB_SendHexPacket(ctx, outbuf, n); } +static const char *FormatMemPerm(u32 perm) +{ + if (perm == MEMPERM_DONTCARE) + return "???"; + + static char buf[4] = {0}; + + buf[0] = perm & MEMPERM_READ ? 'r' : '-'; + buf[1] = perm & MEMPERM_WRITE ? 'w' : '-'; + buf[2] = perm & MEMPERM_EXECUTE ? 'x' : '-'; + + return buf; +} + +static const char *FormatMemState(u32 state) +{ + if (state > 11) + return "Unknown"; + + static const char *states[12] = + { + "Free", + "Reserved", + "IO", + "Static", + "Code", + "Private", + "Shared", + "Continuous", + "Aliased", + "Alias", + "AliasCode", + "Locked" + }; + + return states[state]; +} + +GDB_DECLARE_REMOTE_COMMAND_HANDLER(GetMemRegions) +{ + u32 address = 0; + u32 posInBuffer = 0; + u32 maxPosInBuffer = GDB_BUF_LEN / 2 - 35; ///< 35 is the maximum length of a formatted region + Handle handle; + MemInfo memi; + PageInfo pagei; + char outbuf[GDB_BUF_LEN / 2 + 1]; + + if(R_FAILED(svcOpenProcess(&handle, ctx->pid))) + { + posInBuffer = sprintf(outbuf, "Invalid process (wtf?)\n"); + goto end; + } + + while (address < 0x50000000 ///< Limit to check for regions + && posInBuffer < maxPosInBuffer + && R_SUCCEEDED(svcQueryProcessMemory(&memi, &pagei, handle, address))) + { + // Update the address for next region + address = memi.base_addr + memi.size; + + // If region isn't FREE then add it to the list + if (memi.state != MEMSTATE_FREE) + { + const char *perm = FormatMemPerm(memi.perm); + const char *state = FormatMemState(memi.state); + + posInBuffer += sprintf(outbuf + posInBuffer, "%08X - %08X %s %s\n", + memi.base_addr, address, perm, state); + } + } + + svcCloseHandle(handle); + +end: + return GDB_SendHexPacket(ctx, outbuf, posInBuffer); +} + GDB_DECLARE_REMOTE_COMMAND_HANDLER(FlushCaches) { if(ctx->commandData[0] != 0) From f36977017bbf8556bfa43bcab740007283084ded Mon Sep 17 00:00:00 2001 From: Nanquitas Date: Thu, 18 Jan 2018 20:44:54 +0100 Subject: [PATCH 5/8] InputRedirection: check service existence instead of using OpenProcessByName --- .../rosalina/source/menus/miscellaneous.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sysmodules/rosalina/source/menus/miscellaneous.c b/sysmodules/rosalina/source/menus/miscellaneous.c index be0f802..69013c3 100644 --- a/sysmodules/rosalina/source/menus/miscellaneous.c +++ b/sysmodules/rosalina/source/menus/miscellaneous.c @@ -258,19 +258,19 @@ void MiscellaneousMenu_InputRedirection(void) } else { - Handle dummy; - s64 dummyInfo; - bool isN3DS = svcGetSystemInfo(&dummyInfo, 0x10001, 0) == 0; + s64 dummyInfo; + bool isN3DS = svcGetSystemInfo(&dummyInfo, 0x10001, 0) == 0; + bool isSocURegistered; - res = OpenProcessByName("socket", &dummy); - cantStart = R_FAILED(res); - svcCloseHandle(dummy); + res = srvIsServiceRegistered(&isSocURegistered, "soc:U"); + cantStart = R_FAILED(res) || !isSocURegistered; if(!cantStart && isN3DS) { - res = OpenProcessByName("ir", &dummy); - cantStart = R_FAILED(res); - svcCloseHandle(dummy); + bool isIrRstRegistered; + + res = srvIsServiceRegistered(&isIrRstRegistered, "ir:rst"); + cantStart = R_FAILED(res) || !isIrRstRegistered; } } @@ -285,7 +285,7 @@ void MiscellaneousMenu_InputRedirection(void) Draw_DrawString(10, 10, COLOR_TITLE, "Miscellaneous options menu"); if(!wasEnabled && cantStart) - Draw_DrawString(10, 30, COLOR_WHITE, "Can't start the debugger before the system has fi-\nnished loading."); + Draw_DrawString(10, 30, COLOR_WHITE, "Can't start the input redirection before the system\nhas finished loading."); else if(!wasEnabled) { Draw_DrawString(10, 30, COLOR_WHITE, "Starting InputRedirection..."); From 337205eb0857668ee5dfa8497fc683e0079145f9 Mon Sep 17 00:00:00 2001 From: Nanquitas Date: Thu, 18 Jan 2018 22:57:46 +0100 Subject: [PATCH 6/8] sock_util: remove unneeded check We loop while (server_sockfd == -1) so it's safe to assume that (server_sockfd != -1) once out of the loop. --- sysmodules/rosalina/source/sock_util.c | 43 ++++++++++++-------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/sysmodules/rosalina/source/sock_util.c b/sysmodules/rosalina/source/sock_util.c index ad88b0e..2eb62a9 100644 --- a/sysmodules/rosalina/source/sock_util.c +++ b/sysmodules/rosalina/source/sock_util.c @@ -135,33 +135,30 @@ void server_bind(struct sock_server *serv, u16 port) server_sockfd = socSocket(AF_INET, SOCK_STREAM, 0); } - if(server_sockfd != -1) + struct sockaddr_in saddr; + saddr.sin_family = AF_INET; + saddr.sin_port = htons(port); + saddr.sin_addr.s_addr = gethostid(); + + res = socBind(server_sockfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in)); + + if(res == 0) { - struct sockaddr_in saddr; - saddr.sin_family = AF_INET; - saddr.sin_port = htons(port); - saddr.sin_addr.s_addr = gethostid(); - - res = socBind(server_sockfd, (struct sockaddr*)&saddr, sizeof(struct sockaddr_in)); - + res = socListen(server_sockfd, 2); if(res == 0) { - res = socListen(server_sockfd, 2); - if(res == 0) - { - int idx = serv->nfds; - serv->nfds++; - serv->poll_fds[idx].fd = server_sockfd; - serv->poll_fds[idx].events = POLLIN; + int idx = serv->nfds; + serv->nfds++; + serv->poll_fds[idx].fd = server_sockfd; + serv->poll_fds[idx].events = POLLIN; - struct sock_ctx *new_ctx = server_alloc_server_ctx(serv); - memcpy(&new_ctx->addr_in, &saddr, sizeof(struct sockaddr_in)); - new_ctx->type = SOCK_SERVER; - new_ctx->sockfd = server_sockfd; - new_ctx->n = 0; - new_ctx->i = idx; - serv->ctx_ptrs[idx] = new_ctx; - } + struct sock_ctx *new_ctx = server_alloc_server_ctx(serv); + memcpy(&new_ctx->addr_in, &saddr, sizeof(struct sockaddr_in)); + new_ctx->type = SOCK_SERVER; + new_ctx->sockfd = server_sockfd; + new_ctx->n = 0; + new_ctx->i = idx; + serv->ctx_ptrs[idx] = new_ctx; } } } From 7cb74b74d7c0e9dbc937b90d10600a1f07147c64 Mon Sep 17 00:00:00 2001 From: Nanquitas Date: Thu, 18 Jan 2018 23:39:47 +0100 Subject: [PATCH 7/8] Rosalina: fix freeze when attempting to open Rosalina before the system finished to boot --- sysmodules/rosalina/source/menu.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/sysmodules/rosalina/source/menu.c b/sysmodules/rosalina/source/menu.c index d60af63..af719ec 100644 --- a/sysmodules/rosalina/source/menu.c +++ b/sysmodules/rosalina/source/menu.c @@ -148,14 +148,23 @@ void menuThreadMain(void) else N3DSMenu_UpdateStatus(); + bool isAcURegistered = false; + while(!terminationRequest) { if((HID_PAD & menuCombo) == menuCombo) { - menuEnter(); - if(isN3DS) N3DSMenu_UpdateStatus(); - menuShow(&rosalinaMenu); - menuLeave(); + if (!isAcURegistered) + isAcURegistered = R_SUCCEEDED(srvIsServiceRegistered(&isAcURegistered, "ac:u")) + && isAcURegistered; + + if (isAcURegistered) + { + menuEnter(); + if(isN3DS) N3DSMenu_UpdateStatus(); + menuShow(&rosalinaMenu); + menuLeave(); + } } svcSleepThread(50 * 1000 * 1000LL); } From 76d274cfe27d7a5a41d8094fe51ccb1fe2ab15e0 Mon Sep 17 00:00:00 2001 From: TuxSH Date: Fri, 19 Jan 2018 01:42:53 +0100 Subject: [PATCH 8/8] getmemregions: userland never exceeds 0x40000000 --- sysmodules/rosalina/source/gdb/remote_command.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysmodules/rosalina/source/gdb/remote_command.c b/sysmodules/rosalina/source/gdb/remote_command.c index 41c1005..c565927 100644 --- a/sysmodules/rosalina/source/gdb/remote_command.c +++ b/sysmodules/rosalina/source/gdb/remote_command.c @@ -281,7 +281,7 @@ GDB_DECLARE_REMOTE_COMMAND_HANDLER(GetMemRegions) goto end; } - while (address < 0x50000000 ///< Limit to check for regions + while (address < 0x40000000 ///< Limit to check for regions && posInBuffer < maxPosInBuffer && R_SUCCEEDED(svcQueryProcessMemory(&memi, &pagei, handle, address))) {