Stub svcBreak with "bkpt 65535" so we can debug it
This commit is contained in:
@@ -98,13 +98,14 @@ void detectAndProcessExceptionDumps(void)
|
||||
char path9[41] = "/luma/dumps/arm9";
|
||||
char path11[42] = "/luma/dumps/arm11";
|
||||
char fileName[] = "crash_dump_00000000.dmp";
|
||||
u32 size = dump[5];
|
||||
|
||||
if(dump[3] == 9)
|
||||
{
|
||||
findDumpFile(path9, fileName);
|
||||
path9[16] = '/';
|
||||
memcpy(&path9[17], fileName, sizeof(fileName));
|
||||
fileWrite((void *)dump, path9, dump[5]);
|
||||
fileWrite((void *)dump, path9, size);
|
||||
}
|
||||
|
||||
else
|
||||
@@ -125,7 +126,9 @@ void detectAndProcessExceptionDumps(void)
|
||||
int posY = drawString(((dump[3] & 0xFFFF) == 11) ? arm11Str : "Processor: ARM9", 10, 30, COLOR_WHITE) + SPACING_Y;
|
||||
posY = drawString("Exception type: ", 10, posY, COLOR_WHITE);
|
||||
posY = drawString(handledExceptionNames[dump[4]], 10 + 16 * SPACING_X, posY, COLOR_WHITE);
|
||||
|
||||
if(dump[4] == 2 && dump[7] >= 4 && (dump[10 + 16] & 0x20) == 0 && *(vu32 *)((vu8 *)dump + 40 + dump[6] + dump[7] - 4) == 0xE12FFF7F)
|
||||
posY = drawString("(svcBreak)", 10 + 31 * SPACING_X, posY, COLOR_WHITE);
|
||||
|
||||
posY += 3 * SPACING_Y;
|
||||
for(u32 i = 0; i < 17; i += 2)
|
||||
{
|
||||
@@ -145,7 +148,7 @@ void detectAndProcessExceptionDumps(void)
|
||||
|
||||
posY += 2 * SPACING_Y;
|
||||
|
||||
u32 mode = dump[40 + 16] & 0xF;
|
||||
u32 mode = dump[10 + 16] & 0xF;
|
||||
if(dump[4] == 3 && (mode == 7 || mode == 11))
|
||||
posY = drawString("Incorrect dump: failed to dump code and/or stack", 10, posY, 0x00FFFF) + 2 * SPACING_Y; //in yellow
|
||||
|
||||
@@ -155,8 +158,7 @@ void detectAndProcessExceptionDumps(void)
|
||||
|
||||
waitInput();
|
||||
|
||||
*(vu32 *)0x25000000 = 0; //Make sure we won't detect a corrupted exception dump after we've rebooted. It doesn't seem to be sufficient though
|
||||
*(vu32 *)0x25000004 = 0;
|
||||
for(u32 i = 0; i < size / 4; i++) dump[i] = 0;
|
||||
|
||||
clearScreens();
|
||||
|
||||
|
||||
@@ -216,7 +216,9 @@ void main(void)
|
||||
{
|
||||
u32 arm9SectionNum = 0;
|
||||
for(; (u32)(section[arm9SectionNum].address) >> 24 != 0x08 && arm9SectionNum < 4; arm9SectionNum++);
|
||||
|
||||
patchExceptionHandlersInstall((u8 *)firm + section[arm9SectionNum].offset, section[arm9SectionNum].size);
|
||||
patchSvcBreak9((u8 *)firm + section[arm9SectionNum].offset, section[arm9SectionNum].size, (u32)(section[arm9SectionNum].address));
|
||||
}
|
||||
|
||||
switch(firmType)
|
||||
@@ -337,6 +339,9 @@ static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhMode)
|
||||
u32 *exceptionsPage = getInfoForArm11ExceptionHandlers(arm11Section1, section[1].size, &stackAddress);
|
||||
installArm11Handlers(exceptionsPage, stackAddress);
|
||||
|
||||
//Stub svcBreak11 with "bkpt 255"
|
||||
patchSvcBreak11(arm11Section1, section[1].size);
|
||||
|
||||
//Make FCRAM (and VRAM as a side effect) globally executable from arm11 kernel
|
||||
patchKernelFCRAMAndVRAMMappingPermissions(arm11Section1, section[1].size);
|
||||
}
|
||||
@@ -351,7 +356,8 @@ static inline void patchLegacyFirm(u32 firmType)
|
||||
firm->arm9Entry = (u8 *)0x801301C;
|
||||
}
|
||||
|
||||
applyLegacyFirmPatches((u8 *)firm, firmType, console);}
|
||||
applyLegacyFirmPatches((u8 *)firm, firmType, console);
|
||||
}
|
||||
|
||||
static inline void patchSafeFirm(void)
|
||||
{
|
||||
|
||||
@@ -7,7 +7,21 @@
|
||||
#include "config.h"
|
||||
#include "../build/rebootpatch.h"
|
||||
|
||||
static u32 *exceptionsPage = NULL;
|
||||
static u32 *arm11ExceptionsPage = NULL;
|
||||
static u32 *arm11SvcTable = NULL;
|
||||
|
||||
static void findArm11ExceptionsPageAndSvcTable(u8 *pos, u32 size)
|
||||
{
|
||||
const u8 arm11ExceptionsPagePattern[] = {0x00, 0xB0, 0x9C, 0xE5};
|
||||
|
||||
if(arm11ExceptionsPage == NULL) arm11ExceptionsPage = (u32 *)memsearch(pos, arm11ExceptionsPagePattern, size, 4) - 0xB;
|
||||
if(arm11SvcTable == NULL && arm11ExceptionsPage != NULL)
|
||||
{
|
||||
u32 svcOffset = (-((arm11ExceptionsPage[2] & 0xFFFFFF) << 2) & (0xFFFFFF << 2)) - 8; //Branch offset + 8 for prefetch
|
||||
arm11SvcTable = (u32 *)(pos + *(u32 *)(pos + 0xFFFF0008 - svcOffset - 0xFFF00000 + 8) - 0xFFF00000); //SVC handler address
|
||||
while(*arm11SvcTable) arm11SvcTable++; //Look for SVC0 (NULL)
|
||||
}
|
||||
}
|
||||
|
||||
u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)
|
||||
{
|
||||
@@ -25,13 +39,11 @@ u32* getInfoForArm11ExceptionHandlers(u8 *pos, u32 size, u32 *stackAddr)
|
||||
//This function has to succeed. Crash if it doesn't (we'll get an exception dump of it anyways)
|
||||
|
||||
const u8 callExceptionDispatcherPattern[] = {0x0F, 0x00, 0xBD, 0xE8, 0x13, 0x00, 0x02, 0xF1};
|
||||
const u8 exceptionsPagePattern[] = {0x00, 0xB0, 0x9C, 0xE5};
|
||||
|
||||
|
||||
*stackAddr = *((u32 *)memsearch(pos, callExceptionDispatcherPattern, size, 8) + 3);
|
||||
|
||||
if(exceptionsPage == NULL) exceptionsPage = (u32 *)memsearch(pos, exceptionsPagePattern, size, 4) - 0xB;
|
||||
|
||||
return exceptionsPage;
|
||||
findArm11ExceptionsPageAndSvcTable(pos, size);
|
||||
return arm11ExceptionsPage;
|
||||
}
|
||||
|
||||
void patchSignatureChecks(u8 *pos, u32 size)
|
||||
@@ -131,6 +143,25 @@ void patchExceptionHandlersInstall(u8 *pos, u32 size)
|
||||
}
|
||||
}
|
||||
|
||||
void patchSvcBreak9(u8 *pos, u32 size, u32 k9addr)
|
||||
{
|
||||
//Stub svcBreak with "bkpt 65535" so we can debug the panic.
|
||||
//Thanks @yellows8 and others for mentioning this idea on #3dsdev.
|
||||
const u8 svcHandlerPattern[] = {0x08, 0xE0, 0x0D, 0xE5, 0x00, 0xE0, 0x4F, 0xE1}; //str lr, [sp]; mrs lr, spsr
|
||||
|
||||
u32 *arm9SvcTable = (u32 *)memsearch(pos, svcHandlerPattern, size, 8);
|
||||
while(*arm9SvcTable) arm9SvcTable++; //Look for SVC0 (NULL)
|
||||
*(u32 *)(pos + arm9SvcTable[0x3C] - k9addr) = 0xE12FFF7F;
|
||||
}
|
||||
|
||||
void patchSvcBreak11(u8 *pos, u32 size)
|
||||
{
|
||||
//Same as above, for NFIRM arm11
|
||||
|
||||
findArm11ExceptionsPageAndSvcTable(pos, size);
|
||||
*(u32 *)(pos + arm11SvcTable[0x3C] - 0xFFF00000) = 0xE12FFF7F;
|
||||
}
|
||||
|
||||
void patchUnitInfoValueSet(u8 *pos, u32 size)
|
||||
{
|
||||
//Look for UNITINFO value being set
|
||||
@@ -166,22 +197,16 @@ void reimplementSvcBackdoor(u8 *pos, u32 size)
|
||||
0x00, 0xD0, 0xA0, 0xE1, //mov sp, r0
|
||||
0x11, 0xFF, 0x2F, 0xE1}; //bx r1
|
||||
|
||||
const u8 pattern[] = {0x00, 0xB0, 0x9C, 0xE5}; //cpsid aif
|
||||
|
||||
if(exceptionsPage == NULL) exceptionsPage = (u32 *)memsearch(pos, pattern, size, 4) - 0xB;
|
||||
findArm11ExceptionsPageAndSvcTable(pos, size);
|
||||
|
||||
u32 svcOffset = (-((exceptionsPage[2] & 0xFFFFFF) << 2) & (0xFFFFFF << 2)) - 8; //Branch offset + 8 for prefetch
|
||||
u32 *svcTable = (u32 *)(pos + *(u32 *)(pos + 0xFFFF0008 - svcOffset - 0xFFF00000 + 8) - 0xFFF00000); //SVC handler address
|
||||
while(*svcTable) svcTable++; //Look for SVC0 (NULL)
|
||||
|
||||
if(!svcTable[0x7B])
|
||||
if(!arm11SvcTable[0x7B])
|
||||
{
|
||||
u32 *freeSpace;
|
||||
for(freeSpace = exceptionsPage; *freeSpace != 0xFFFFFFFF; freeSpace++);
|
||||
for(freeSpace = arm11ExceptionsPage; *freeSpace != 0xFFFFFFFF; freeSpace++);
|
||||
|
||||
memcpy(freeSpace, svcBackdoor, 40);
|
||||
|
||||
svcTable[0x7B] = 0xFFFF0000 + ((u8 *)freeSpace - (u8 *)exceptionsPage);
|
||||
arm11SvcTable[0x7B] = 0xFFFF0000 + ((u8 *)freeSpace - (u8 *)arm11ExceptionsPage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr);
|
||||
void patchFirmWrites(u8 *pos, u32 size);
|
||||
void patchFirmWriteSafe(u8 *pos, u32 size);
|
||||
void patchExceptionHandlersInstall(u8 *pos, u32 size);
|
||||
void patchSvcBreak9(u8 *pos, u32 size, u32 k9addr);
|
||||
void patchSvcBreak11(u8 *pos, u32 size);
|
||||
void patchUnitInfoValueSet(u8 *pos, u32 size);
|
||||
void patchKernelFCRAMAndVRAMMappingPermissions(u8 *pos, u32 size);
|
||||
void reimplementSvcBackdoor(u8 *pos, u32 size);
|
||||
|
||||
Reference in New Issue
Block a user