rosalina: add hidden debug info menu
This commit is contained in:
parent
9097276a06
commit
b02d0346fd
@ -132,6 +132,7 @@ typedef struct CfwInfo
|
||||
} CfwInfo;
|
||||
|
||||
extern CfwInfo cfwInfo;
|
||||
extern u32 kextBasePa;
|
||||
|
||||
extern vu32 rosalinaState;
|
||||
extern bool hasStartedRosalinaNetworkFuncsOnce;
|
||||
|
@ -108,6 +108,7 @@ void (*mcuReboot)(void);
|
||||
void (*coreBarrier)(void);
|
||||
|
||||
CfwInfo cfwInfo;
|
||||
u32 kextBasePa;
|
||||
|
||||
vu32 rosalinaState;
|
||||
bool hasStartedRosalinaNetworkFuncsOnce;
|
||||
|
@ -271,6 +271,7 @@ void main(FcramLayout *layout, KCoreContext *ctxs)
|
||||
memcpy(L1MMUTableAddrs, (const void *)p->L1MMUTableAddrs, 16);
|
||||
exceptionStackTop = (u32 *)0xFFFF2000 + (1 << (32 - TTBCR - 20));
|
||||
cfwInfo = p->cfwInfo;
|
||||
kextBasePa = p->basePA;
|
||||
|
||||
memcpy(originalHandlers + 1, p->originalHandlers, 16);
|
||||
void **arm11SvcTable = (void**)originalHandlers[2];
|
||||
|
@ -79,7 +79,7 @@ Result GetSystemInfoHook(s64 *out, s32 type, s32 param)
|
||||
break;
|
||||
|
||||
case 0x300: // K11Ext size
|
||||
*out = (s64)(__end__ - __start__);
|
||||
*out = (s64)(((u64)kextBasePa << 32) | (u64)(__end__ - __start__));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -39,3 +39,6 @@ void RosalinaMenu_ProcessList(void);
|
||||
void RosalinaMenu_PowerOff(void);
|
||||
void RosalinaMenu_Reboot(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;
|
||||
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 "gdb/breakpoints.h"
|
||||
|
||||
#include "../utils.h"
|
||||
|
||||
struct
|
||||
{
|
||||
const char *name;
|
||||
@ -208,84 +210,19 @@ 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;
|
||||
return GDB_SendHexPacket(ctx, outbuf, posInBuffer);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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:
|
||||
posInBuffer = formatMemoryMapOfProcess(outbuf, GDB_BUF_LEN / 2, handle);
|
||||
return GDB_SendHexPacket(ctx, outbuf, posInBuffer);
|
||||
}
|
||||
|
||||
|
@ -55,10 +55,44 @@ Menu rosalinaMenu = {
|
||||
{ "Power off", METHOD, .method = &RosalinaMenu_PowerOff },
|
||||
{ "Reboot", METHOD, .method = &RosalinaMenu_Reboot },
|
||||
{ "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)
|
||||
{
|
||||
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