-adding exception handler to JGE. Copy the exception.prx file to the same directory as the EBOOT from now on
This commit is contained in:
wagic.the.homebrew@gmail.com
2009-09-23 03:33:02 +00:00
parent e577f3e378
commit 3ce216d5e6
12 changed files with 612 additions and 32 deletions

View File

@@ -0,0 +1,34 @@
Exception Handler for Kernel 3.71
---------------------------------
All credits goes to crazyc (for the prx code) and SamuraiX (sample usage code)
What is it?
-----------
exception.prx is a prx that handle exception and can be used
to show usefull information abuot a crash.
How to build:
-------------
To build exception.prx
$cd prx
$make
To build the test program:
$cd test
$make
How to use it:
--------------
Include utility/exception.h in your main.c and init the handler with:
initExceptionHandler();
Copy exception.prx in the same directory your EBOOT is.
Please check the test program. ;)
Note:
--> For Wagic, the code is already included in JGE's main.cpp. You just need to copy the prx with the EBOOT

Binary file not shown.

View File

@@ -0,0 +1,214 @@
#include "as_reg_compat.h"
.set noreorder
.set noat
#define BadVAddr $8 // Address for the most recent address-related exception
#define Status $12 // Processor status and control
#define Cause $13 // Cause of last general exception
#define EPC $14 // Program counter at last exception
#define PRId $15 // Processor identification and revision
#define FSR $31
#define FIR $0
#define REG_GPR_0 (6*4)
#define REG_GPR_1 (REG_GPR_0 + 4)
#define REG_GPR_2 (REG_GPR_1 + 4)
#define REG_GPR_3 (REG_GPR_2 + 4)
#define REG_GPR_4 (REG_GPR_3 + 4)
#define REG_GPR_5 (REG_GPR_4 + 4)
#define REG_GPR_6 (REG_GPR_5 + 4)
#define REG_GPR_7 (REG_GPR_6 + 4)
#define REG_GPR_8 (REG_GPR_7 + 4)
#define REG_GPR_9 (REG_GPR_8 + 4)
#define REG_GPR_10 (REG_GPR_9 + 4)
#define REG_GPR_11 (REG_GPR_10 + 4)
#define REG_GPR_12 (REG_GPR_11 + 4)
#define REG_GPR_13 (REG_GPR_12 + 4)
#define REG_GPR_14 (REG_GPR_13 + 4)
#define REG_GPR_15 (REG_GPR_14 + 4)
#define REG_GPR_16 (REG_GPR_15 + 4)
#define REG_GPR_17 (REG_GPR_16 + 4)
#define REG_GPR_18 (REG_GPR_17 + 4)
#define REG_GPR_19 (REG_GPR_18 + 4)
#define REG_GPR_20 (REG_GPR_19 + 4)
#define REG_GPR_21 (REG_GPR_20 + 4)
#define REG_GPR_22 (REG_GPR_21 + 4)
#define REG_GPR_23 (REG_GPR_22 + 4)
#define REG_GPR_24 (REG_GPR_23 + 4)
#define REG_GPR_25 (REG_GPR_24 + 4)
#define REG_GPR_26 (REG_GPR_25 + 4)
#define REG_GPR_27 (REG_GPR_26 + 4)
#define REG_GPR_28 (REG_GPR_27 + 4)
#define REG_GPR_29 (REG_GPR_28 + 4)
#define REG_GPR_30 (REG_GPR_29 + 4)
#define REG_GPR_31 (REG_GPR_30 + 4)
#define REG_STATUS (REG_GPR_31 + 4)
#define REG_LO (REG_STATUS + 4)
#define REG_HI (REG_LO + 4)
#define REG_BADVADDR (REG_HI + 4)
#define REG_CAUSE (REG_BADVADDR + 4)
#define REG_EPC (REG_CAUSE + 4)
#define REG_FPR_0 (REG_EPC + 4)
#define REG_FPR_1 (REG_FPR_0 + 4)
#define REG_FPR_2 (REG_FPR_1 + 4)
#define REG_FPR_3 (REG_FPR_2 + 4)
#define REG_FPR_4 (REG_FPR_3 + 4)
#define REG_FPR_5 (REG_FPR_4 + 4)
#define REG_FPR_6 (REG_FPR_5 + 4)
#define REG_FPR_7 (REG_FPR_6 + 4)
#define REG_FPR_8 (REG_FPR_7 + 4)
#define REG_FPR_9 (REG_FPR_8 + 4)
#define REG_FPR_10 (REG_FPR_9 + 4)
#define REG_FPR_11 (REG_FPR_10 + 4)
#define REG_FPR_12 (REG_FPR_11 + 4)
#define REG_FPR_13 (REG_FPR_12 + 4)
#define REG_FPR_14 (REG_FPR_13 + 4)
#define REG_FPR_15 (REG_FPR_14 + 4)
#define REG_FPR_16 (REG_FPR_15 + 4)
#define REG_FPR_17 (REG_FPR_16 + 4)
#define REG_FPR_18 (REG_FPR_17 + 4)
#define REG_FPR_19 (REG_FPR_18 + 4)
#define REG_FPR_20 (REG_FPR_19 + 4)
#define REG_FPR_21 (REG_FPR_20 + 4)
#define REG_FPR_22 (REG_FPR_21 + 4)
#define REG_FPR_23 (REG_FPR_22 + 4)
#define REG_FPR_24 (REG_FPR_23 + 4)
#define REG_FPR_25 (REG_FPR_24 + 4)
#define REG_FPR_26 (REG_FPR_25 + 4)
#define REG_FPR_27 (REG_FPR_26 + 4)
#define REG_FPR_28 (REG_FPR_27 + 4)
#define REG_FPR_29 (REG_FPR_28 + 4)
#define REG_FPR_30 (REG_FPR_29 + 4)
#define REG_FPR_31 (REG_FPR_30 + 4)
#define REG_FSR (REG_FPR_31 + 4)
#define REG_FIR (REG_FSR + 4)
#define REG_FP (REG_FIR + 4)
.extern exception_regs
.extern curr_handler
.global _pspDebugExceptionHandler
.ent _pspDebugExceptionHandler
_pspDebugExceptionHandler:
nop
nop
lw $v0, exception_regs
sw $0, REG_GPR_0($v0)
sw $1, REG_GPR_1($v0)
cfc0 $1, $4 # Get original v0
sw $1, REG_GPR_2($v0)
cfc0 $1, $5 # Get original v1
sw $1, REG_GPR_3($v0)
sw $4, REG_GPR_4($v0)
sw $5, REG_GPR_5($v0)
sw $6, REG_GPR_6($v0)
sw $7, REG_GPR_7($v0)
sw $8, REG_GPR_8($v0)
sw $9, REG_GPR_9($v0)
sw $10, REG_GPR_10($v0)
sw $11, REG_GPR_11($v0)
sw $12, REG_GPR_12($v0)
sw $13, REG_GPR_13($v0)
sw $14, REG_GPR_14($v0)
sw $15, REG_GPR_15($v0)
sw $16, REG_GPR_16($v0)
sw $17, REG_GPR_17($v0)
sw $18, REG_GPR_18($v0)
sw $19, REG_GPR_19($v0)
sw $20, REG_GPR_20($v0)
sw $21, REG_GPR_21($v0)
sw $22, REG_GPR_22($v0)
sw $23, REG_GPR_23($v0)
sw $24, REG_GPR_24($v0)
sw $25, REG_GPR_25($v0)
sw $26, REG_GPR_26($v0)
sw $27, REG_GPR_27($v0)
sw $28, REG_GPR_28($v0)
sw $29, REG_GPR_29($v0)
sw $30, REG_GPR_30($v0)
sw $31, REG_GPR_31($v0)
mflo $v1
sw $v1, REG_LO($v0)
mfhi $v1
sw $v1, REG_HI($v0)
mfc0 $v1, BadVAddr
sw $v1, REG_BADVADDR($v0)
mfc0 $v1, Cause
sw $v1, REG_CAUSE($v0)
mfc0 $v1, EPC
sw $v1, REG_EPC($v0)
mfc0 $v1, Status
sw $v1, REG_STATUS($v0)
# Check if cop1 is enable and skip if not
lui $a0, 0x2000
and $a0, $a0, $v1
beq $a0, $0, 1f
nop
swc1 $0, REG_FPR_0($v0)
swc1 $1, REG_FPR_1($v0)
swc1 $2, REG_FPR_2($v0)
swc1 $3, REG_FPR_3($v0)
swc1 $4, REG_FPR_4($v0)
swc1 $5, REG_FPR_5($v0)
swc1 $6, REG_FPR_6($v0)
swc1 $7, REG_FPR_7($v0)
swc1 $8, REG_FPR_8($v0)
swc1 $9, REG_FPR_9($v0)
swc1 $10, REG_FPR_10($v0)
swc1 $11, REG_FPR_11($v0)
swc1 $12, REG_FPR_12($v0)
swc1 $13, REG_FPR_13($v0)
swc1 $14, REG_FPR_14($v0)
swc1 $15, REG_FPR_15($v0)
swc1 $16, REG_FPR_16($v0)
swc1 $17, REG_FPR_17($v0)
swc1 $18, REG_FPR_18($v0)
swc1 $19, REG_FPR_19($v0)
swc1 $20, REG_FPR_20($v0)
swc1 $21, REG_FPR_21($v0)
swc1 $22, REG_FPR_22($v0)
swc1 $23, REG_FPR_23($v0)
swc1 $24, REG_FPR_24($v0)
swc1 $25, REG_FPR_25($v0)
swc1 $26, REG_FPR_26($v0)
swc1 $27, REG_FPR_27($v0)
swc1 $28, REG_FPR_28($v0)
swc1 $29, REG_FPR_29($v0)
swc1 $30, REG_FPR_30($v0)
swc1 $31, REG_FPR_31($v0)
cfc1 $t0, FSR
sw $t0, REG_FSR($v0)
cfc1 $t0, FIR
sw $t0, REG_FIR($v0)
ctc1 $0, FSR # Clear any cause flags
# Jump target for ignore cop1
1:
sw $sp, REG_FP($v0)
move $a0, $v0
lw $2, curr_handler
mtc0 $2, $14
nop
nop
eret
nop
nop
.end _pspDebugExceptionHandler
#include "pspimport.s"
IMPORT_START "ExceptionManagerForKernel",0x00010011
IMPORT_FUNC "ExceptionManagerForKernel",0x565C0B0E,sceKernelRegisterDefaultExceptionHandler371

View File

@@ -0,0 +1,7 @@
PSP_BEGIN_EXPORTS
PSP_EXPORT_START(syslib, 0, 0x8000)
PSP_EXPORT_FUNC_HASH(module_start)
PSP_EXPORT_VAR_HASH(module_info)
PSP_EXPORT_END
PSP_END_EXPORTS

View File

@@ -0,0 +1,25 @@
#include <pspkernel.h>
#include <psppower.h>
#include <pspdebug.h>
PSP_MODULE_INFO("exception", 0x1007, 1, 1); // better not unload
PspDebugErrorHandler curr_handler;
PspDebugRegBlock *exception_regs;
void _pspDebugExceptionHandler(void);
int sceKernelRegisterDefaultExceptionHandler(void *func);
int sceKernelRegisterDefaultExceptionHandler371(void *func);
int module_start(SceSize args, void *argp)
{
if(args != 8) return -1;
curr_handler = (PspDebugErrorHandler)((int *)argp)[0];
exception_regs = (PspDebugRegBlock *)((int *)argp)[1];
if(!curr_handler || !exception_regs) return -1;
if(sceKernelDevkitVersion() < 0x03070110)
return sceKernelRegisterDefaultExceptionHandler((void *)_pspDebugExceptionHandler);
else
return sceKernelRegisterDefaultExceptionHandler371((void *)_pspDebugExceptionHandler);
}

View File

@@ -0,0 +1,20 @@
TARGET = exception
OBJS = main.o exception_asm.o
# Define to build this as a prx (instead of a static elf)
BUILD_PRX=1
# Define the name of our custom exports (minus the .exp extension)
PRX_EXPORTS=exports.exp
USE_KERNEL_LIBC = 1
USE_KERNEL_LIBS = 1
INCDIR =
CFLAGS = -Os -G0 -Wall -nostartfiles
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)
LIBDIR =
PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak

View File

@@ -0,0 +1,73 @@
#include <pspkernel.h>
#include <pspctrl.h>
#include <pspdebug.h>
#include <pspsdk.h>
#include "../utility/exception.h"
PSP_MODULE_INFO("Exception Handler Test", 0, 1, 0);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER);
//PSP_HEAP_SIZE_KB(22000);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Globals:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int runningFlag = 1;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Callbacks:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* Exit callback */
int exit_callback(int arg1, int arg2, void *common) {
runningFlag = 0;
return 0;
}
/* Callback thread */
int CallbackThread(SceSize args, void *argp) {
int cbid;
cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
sceKernelRegisterExitCallback(cbid);
sceKernelSleepThreadCB();
return 0;
}
/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void) {
int thid = 0;
thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, PSP_THREAD_ATTR_USER, 0);
if(thid >= 0)
sceKernelStartThread(thid, 0, 0);
return thid;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Main:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main(){
pspDebugScreenInit();
SetupCallbacks();
pspDebugScreenPrintf("Expcetion Handler Test\n");
initExceptionHandler();
pspDebugScreenPrintf("Press X for a breakpoint\n");
pspDebugScreenPrintf("Press O for a bus error\n");
SceCtrlData pad;
while(runningFlag){
sceCtrlReadBufferPositive(&pad, 1);
if (pad.Buttons & PSP_CTRL_CROSS){
/* Cause a break exception */
asm(
"break\r\n"
);
}else if (pad.Buttons & PSP_CTRL_CIRCLE){
/* Cause a bus error */
_sw(0, 0);
}
}
sceKernelExitGame();
return 0;
}

View File

@@ -0,0 +1,19 @@
TARGET = exception_handler_test
OBJS = ../utility/exception.o main.o
#To build for custom firmware:
BUILD_PRX = 1
#CFLAGS = -O3 -G0 -Wall
CFLAGS = -O3 -frename-registers -G0 -Wall
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)
LIBDIR =
LIBS =
LDFLAGS =
EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = Exception Handler Test
#PSP_EBOOT_ICON = ICON0.PNG
PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak

View File

@@ -0,0 +1,107 @@
#include <pspkernel.h>
#include <pspsdk.h>
#include <pspctrl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
PspDebugRegBlock exception_regs;
extern SceModule module_info;
extern int _ftext;
static const char *codeTxt[32] =
{
"Interrupt", "TLB modification", "TLB load/inst fetch", "TLB store",
"Address load/inst fetch", "Address store", "Bus error (instr)",
"Bus error (data)", "Syscall", "Breakpoint", "Reserved instruction",
"Coprocessor unusable", "Arithmetic overflow", "Unknown 14",
"Unknown 15", "Unknown 16", "Unknown 17", "Unknown 18", "Unknown 19",
"Unknown 20", "Unknown 21", "Unknown 22", "Unknown 23", "Unknown 24",
"Unknown 25", "Unknown 26", "Unknown 27", "Unknown 28", "Unknown 29",
"Unknown 31"
};
static const unsigned char regName[32][5] =
{
"zr", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
};
void ExceptionHandler(PspDebugRegBlock * regs)
{
int i;
SceCtrlData pad;
pspDebugScreenInit();
pspDebugScreenSetBackColor(0x00FF0000);
pspDebugScreenSetTextColor(0xFFFFFFFF);
pspDebugScreenClear();
pspDebugScreenPrintf("Your PSP has just crashed!\n");
pspDebugScreenPrintf("Exception details:\n\n");
pspDebugScreenPrintf("Exception - %s\n", codeTxt[(regs->cause >> 2) & 31]);
pspDebugScreenPrintf("EPC - %08X / %s.text + %08X\n", (int)regs->epc, module_info.modname, (unsigned int)(regs->epc-(int)&_ftext));
pspDebugScreenPrintf("Cause - %08X\n", (int)regs->cause);
pspDebugScreenPrintf("Status - %08X\n", (int)regs->status);
pspDebugScreenPrintf("BadVAddr - %08X\n", (int)regs->badvaddr);
for(i=0; i<32; i+=4) pspDebugScreenPrintf("%s:%08X %s:%08X %s:%08X %s:%08X\n", regName[i], (int)regs->r[i], regName[i+1], (int)regs->r[i+1], regName[i+2], (int)regs->r[i+2], regName[i+3], (int)regs->r[i+3]);
sceKernelDelayThread(1000000);
pspDebugScreenPrintf("\n\nPress X to dump information on file exception.log and quit");
pspDebugScreenPrintf("\nPress O to quit");
for (;;){
sceCtrlReadBufferPositive(&pad, 1);
if (pad.Buttons & PSP_CTRL_CROSS){
FILE *log = fopen("exception.log", "w");
if (log != NULL){
char testo[512];
sprintf(testo, "Exception details:\n\n");
fwrite(testo, 1, strlen(testo), log);
sprintf(testo, "Exception - %s\n", codeTxt[(regs->cause >> 2) & 31]);
fwrite(testo, 1, strlen(testo), log);
sprintf(testo, "EPC - %08X / %s.text + %08X\n", (int)regs->epc, module_info.modname, (unsigned int)(regs->epc-(int)&_ftext));
fwrite(testo, 1, strlen(testo), log);
sprintf(testo, "Cause - %08X\n", (int)regs->cause);
fwrite(testo, 1, strlen(testo), log);
sprintf(testo, "Status - %08X\n", (int)regs->status);
fwrite(testo, 1, strlen(testo), log);
sprintf(testo, "BadVAddr - %08X\n", (int)regs->badvaddr);
fwrite(testo, 1, strlen(testo), log);
for(i=0; i<32; i+=4){
sprintf(testo, "%s:%08X %s:%08X %s:%08X %s:%08X\n", regName[i], (int)regs->r[i], regName[i+1], (int)regs->r[i+1], regName[i+2], (int)regs->r[i+2], regName[i+3], (int)regs->r[i+3]);
fwrite(testo, 1, strlen(testo), log);
}
fclose(log);
}
break;
}else if (pad.Buttons & PSP_CTRL_CIRCLE){
break;
}
sceKernelDelayThread(100000);
}
sceKernelExitGame();
}
void initExceptionHandler()
{
SceKernelLMOption option;
int args[2], fd, modid;
memset(&option, 0, sizeof(option));
option.size = sizeof(option);
option.mpidtext = PSP_MEMORY_PARTITION_KERNEL;
option.mpiddata = PSP_MEMORY_PARTITION_KERNEL;
option.position = 0;
option.access = 1;
if((modid = sceKernelLoadModule("exception.prx", 0, &option)) >= 0)
{
args[0] = (int)ExceptionHandler;
args[1] = (int)&exception_regs;
sceKernelStartModule(modid, 8, args, &fd, NULL);
}
}

View File

@@ -0,0 +1,3 @@
void initExceptionHandler();