rosalina: add hidden debug info menu
This commit is contained in:
parent
9097276a06
commit
b02d0346fd
@ -132,6 +132,7 @@ typedef struct CfwInfo
|
|||||||
} CfwInfo;
|
} CfwInfo;
|
||||||
|
|
||||||
extern CfwInfo cfwInfo;
|
extern CfwInfo cfwInfo;
|
||||||
|
extern u32 kextBasePa;
|
||||||
|
|
||||||
extern vu32 rosalinaState;
|
extern vu32 rosalinaState;
|
||||||
extern bool hasStartedRosalinaNetworkFuncsOnce;
|
extern bool hasStartedRosalinaNetworkFuncsOnce;
|
||||||
|
@ -108,6 +108,7 @@ void (*mcuReboot)(void);
|
|||||||
void (*coreBarrier)(void);
|
void (*coreBarrier)(void);
|
||||||
|
|
||||||
CfwInfo cfwInfo;
|
CfwInfo cfwInfo;
|
||||||
|
u32 kextBasePa;
|
||||||
|
|
||||||
vu32 rosalinaState;
|
vu32 rosalinaState;
|
||||||
bool hasStartedRosalinaNetworkFuncsOnce;
|
bool hasStartedRosalinaNetworkFuncsOnce;
|
||||||
|
@ -271,6 +271,7 @@ void main(FcramLayout *layout, KCoreContext *ctxs)
|
|||||||
memcpy(L1MMUTableAddrs, (const void *)p->L1MMUTableAddrs, 16);
|
memcpy(L1MMUTableAddrs, (const void *)p->L1MMUTableAddrs, 16);
|
||||||
exceptionStackTop = (u32 *)0xFFFF2000 + (1 << (32 - TTBCR - 20));
|
exceptionStackTop = (u32 *)0xFFFF2000 + (1 << (32 - TTBCR - 20));
|
||||||
cfwInfo = p->cfwInfo;
|
cfwInfo = p->cfwInfo;
|
||||||
|
kextBasePa = p->basePA;
|
||||||
|
|
||||||
memcpy(originalHandlers + 1, p->originalHandlers, 16);
|
memcpy(originalHandlers + 1, p->originalHandlers, 16);
|
||||||
void **arm11SvcTable = (void**)originalHandlers[2];
|
void **arm11SvcTable = (void**)originalHandlers[2];
|
||||||
|
@ -79,7 +79,7 @@ Result GetSystemInfoHook(s64 *out, s32 type, s32 param)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x300: // K11Ext size
|
case 0x300: // K11Ext size
|
||||||
*out = (s64)(__end__ - __start__);
|
*out = (s64)(((u64)kextBasePa << 32) | (u64)(__end__ - __start__));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -39,3 +39,6 @@ void RosalinaMenu_ProcessList(void);
|
|||||||
void RosalinaMenu_PowerOff(void);
|
void RosalinaMenu_PowerOff(void);
|
||||||
void RosalinaMenu_Reboot(void);
|
void RosalinaMenu_Reboot(void);
|
||||||
void RosalinaMenu_Cheats(void);
|
void RosalinaMenu_Cheats(void);
|
||||||
|
|
||||||
|
bool rosalinaMenuShouldShowDebugInfo(void);
|
||||||
|
void RosalinaMenu_ShowDebugInfo(void);
|
||||||
|
@ -62,3 +62,7 @@ static inline bool isServiceUsable(const char *name)
|
|||||||
bool r;
|
bool r;
|
||||||
return R_SUCCEEDED(srvIsServiceRegistered(&r, name)) && r;
|
return R_SUCCEEDED(srvIsServiceRegistered(&r, name)) && r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void formatMemoryPermission(char *outbuf, MemPerm perm);
|
||||||
|
void formatUserMemoryState(char *outbuf, MemState state);
|
||||||
|
u32 formatMemoryMapOfProcess(char *outbuf, u32 bufLen, Handle handle);
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
#include "fmt.h"
|
#include "fmt.h"
|
||||||
#include "gdb/breakpoints.h"
|
#include "gdb/breakpoints.h"
|
||||||
|
|
||||||
|
#include "../utils.h"
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
@ -208,84 +210,19 @@ GDB_DECLARE_REMOTE_COMMAND_HANDLER(GetMmuConfig)
|
|||||||
return GDB_SendHexPacket(ctx, outbuf, n);
|
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)
|
GDB_DECLARE_REMOTE_COMMAND_HANDLER(GetMemRegions)
|
||||||
{
|
{
|
||||||
u32 address = 0;
|
|
||||||
u32 posInBuffer = 0;
|
u32 posInBuffer = 0;
|
||||||
u32 maxPosInBuffer = GDB_BUF_LEN / 2 - 35; ///< 35 is the maximum length of a formatted region
|
|
||||||
Handle handle;
|
Handle handle;
|
||||||
MemInfo memi;
|
|
||||||
PageInfo pagei;
|
|
||||||
char outbuf[GDB_BUF_LEN / 2 + 1];
|
char outbuf[GDB_BUF_LEN / 2 + 1];
|
||||||
|
|
||||||
if(R_FAILED(svcOpenProcess(&handle, ctx->pid)))
|
if(R_FAILED(svcOpenProcess(&handle, ctx->pid)))
|
||||||
{
|
{
|
||||||
posInBuffer = sprintf(outbuf, "Invalid process (wtf?)\n");
|
posInBuffer = sprintf(outbuf, "Invalid process (wtf?)\n");
|
||||||
goto end;
|
return GDB_SendHexPacket(ctx, outbuf, posInBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 TTBCR;
|
posInBuffer = formatMemoryMapOfProcess(outbuf, GDB_BUF_LEN / 2, handle);
|
||||||
svcGetSystemInfo(&TTBCR, 0x10002, 0);
|
|
||||||
|
|
||||||
while (address < (1u << (32 - (u32)TTBCR)) ///< 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, "%08lx - %08lx %s %s\n",
|
|
||||||
memi.base_addr, address, perm, state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
svcCloseHandle(handle);
|
|
||||||
|
|
||||||
end:
|
|
||||||
return GDB_SendHexPacket(ctx, outbuf, posInBuffer);
|
return GDB_SendHexPacket(ctx, outbuf, posInBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,10 +55,44 @@ Menu rosalinaMenu = {
|
|||||||
{ "Power off", METHOD, .method = &RosalinaMenu_PowerOff },
|
{ "Power off", METHOD, .method = &RosalinaMenu_PowerOff },
|
||||||
{ "Reboot", METHOD, .method = &RosalinaMenu_Reboot },
|
{ "Reboot", METHOD, .method = &RosalinaMenu_Reboot },
|
||||||
{ "Credits", METHOD, .method = &RosalinaMenu_ShowCredits },
|
{ "Credits", METHOD, .method = &RosalinaMenu_ShowCredits },
|
||||||
|
{ "Debug info", METHOD, .method = &RosalinaMenu_ShowDebugInfo, .visibility = &rosalinaMenuShouldShowDebugInfo },
|
||||||
{},
|
{},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool rosalinaMenuShouldShowDebugInfo(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RosalinaMenu_ShowDebugInfo(void)
|
||||||
|
{
|
||||||
|
Draw_Lock();
|
||||||
|
Draw_ClearFramebuffer();
|
||||||
|
Draw_FlushFramebuffer();
|
||||||
|
Draw_Unlock();
|
||||||
|
|
||||||
|
char memoryMap[512];
|
||||||
|
formatMemoryMapOfProcess(memoryMap, 511, CUR_PROCESS_HANDLE);
|
||||||
|
|
||||||
|
s64 kextAddrSize;
|
||||||
|
svcGetSystemInfo(&kextAddrSize, 0x10000, 0x300);
|
||||||
|
u32 kextPa = (u32)((u64)kextAddrSize >> 32);
|
||||||
|
u32 kextSize = (u32)kextAddrSize;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
Draw_Lock();
|
||||||
|
Draw_DrawString(10, 10, COLOR_TITLE, "Rosalina -- Debug info");
|
||||||
|
|
||||||
|
u32 posY = Draw_DrawString(10, 30, COLOR_WHITE, memoryMap);
|
||||||
|
Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Kernel ext PA: %08lx - %08lx\n", kextPa, kextPa + kextSize);
|
||||||
|
Draw_FlushFramebuffer();
|
||||||
|
Draw_Unlock();
|
||||||
|
}
|
||||||
|
while(!(waitInput() & KEY_B) && !menuShouldExit);
|
||||||
|
}
|
||||||
|
|
||||||
void RosalinaMenu_ShowCredits(void)
|
void RosalinaMenu_ShowCredits(void)
|
||||||
{
|
{
|
||||||
Draw_Lock();
|
Draw_Lock();
|
||||||
|
110
sysmodules/rosalina/source/utils.c
Normal file
110
sysmodules/rosalina/source/utils.c
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Luma3DS
|
||||||
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
||||||
|
* * Requiring preservation of specified reasonable legal notices or
|
||||||
|
* author attributions in that material or in the Appropriate Legal
|
||||||
|
* Notices displayed by works containing it.
|
||||||
|
* * Prohibiting misrepresentation of the origin of that material,
|
||||||
|
* or requiring that modified versions of such material be marked in
|
||||||
|
* reasonable ways as different from the original version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
#include "csvc.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void formatMemoryPermission(char *outbuf, MemPerm perm)
|
||||||
|
{
|
||||||
|
if (perm == MEMPERM_DONTCARE)
|
||||||
|
{
|
||||||
|
strcpy(outbuf, "???");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
outbuf[0] = perm & MEMPERM_READ ? 'r' : '-';
|
||||||
|
outbuf[1] = perm & MEMPERM_WRITE ? 'w' : '-';
|
||||||
|
outbuf[2] = perm & MEMPERM_EXECUTE ? 'x' : '-';
|
||||||
|
outbuf[3] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void formatUserMemoryState(char *outbuf, MemState state)
|
||||||
|
{
|
||||||
|
static const char *states[12] =
|
||||||
|
{
|
||||||
|
"Free",
|
||||||
|
"Reserved",
|
||||||
|
"IO",
|
||||||
|
"Static",
|
||||||
|
"Code",
|
||||||
|
"Private",
|
||||||
|
"Shared",
|
||||||
|
"Continuous",
|
||||||
|
"Aliased",
|
||||||
|
"Alias",
|
||||||
|
"AliasCode",
|
||||||
|
"Locked"
|
||||||
|
};
|
||||||
|
|
||||||
|
strcpy(outbuf, state > 11 ? "Unknown" : states[state]);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 formatMemoryMapOfProcess(char *outbuf, u32 bufLen, Handle handle)
|
||||||
|
{
|
||||||
|
u32 maxLineSize = 35 + (handle == CUR_PROCESS_HANDLE ? 15 : 0);
|
||||||
|
u32 address = 0;
|
||||||
|
u32 posInBuffer = 0;
|
||||||
|
u32 maxPosInBuffer = bufLen - maxLineSize; // 35 is the maximum length of a formatted region
|
||||||
|
MemInfo memi;
|
||||||
|
PageInfo pagei;
|
||||||
|
char pabuf[32];
|
||||||
|
char permbuf[8];
|
||||||
|
char statebuf[16];
|
||||||
|
|
||||||
|
s64 TTBCR;
|
||||||
|
svcGetSystemInfo(&TTBCR, 0x10002, 0);
|
||||||
|
|
||||||
|
while (address < (1u << (32 - (u32)TTBCR)) // 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)
|
||||||
|
{
|
||||||
|
if (handle == CUR_PROCESS_HANDLE)
|
||||||
|
{
|
||||||
|
u32 pa = svcConvertVAToPA((void *)memi.base_addr, false);
|
||||||
|
sprintf(pabuf, " (PA %08lx)", pa);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pabuf[0] = '\0';
|
||||||
|
|
||||||
|
formatMemoryPermission(permbuf, memi.perm);
|
||||||
|
formatUserMemoryState(statebuf, memi.state);
|
||||||
|
|
||||||
|
posInBuffer += sprintf(outbuf + posInBuffer, "%08lx - %08lx%s %s %s\n",
|
||||||
|
memi.base_addr, address, pabuf, permbuf, statebuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
svcCloseHandle(handle);
|
||||||
|
return posInBuffer;
|
||||||
|
}
|
Reference in New Issue
Block a user