12#include "irx_imports.h"
18IRX_ID(
"Exception_Manager", 1, 1);
22static uiptr *exception_table;
24static u32 *default_handler_funccode;
27extern u32 exception_handler_shellcode_start[];
28extern u32 exception_handler_shellcode_end[];
31static void update_exception_handler_table(
void);
34static void allocate_list(
void);
36int _start(
int ac,
char **av)
44 for ( i = 0; i < (
sizeof(exception_handlers) /
sizeof(exception_handlers[0])); i += 1 )
46 exception_handlers[i] = NULL;
48 default_handler_funccode = NULL;
51 exception_table = (
void *)0x440;
53 for ( i = 0; i < (
unsigned int)(exception_handler_shellcode_end - exception_handler_shellcode_start); i += 1 )
57 cur_instruction = exception_handler_shellcode_start[i];
58 if ( cur_instruction == 0x8F5A0000 || cur_instruction == 0x8F7B0000 )
60 cur_instruction |= (u16)(uiptr)exception_table;
63 dst_ptr[i] = cur_instruction;
65 RegisterDefaultExceptionHandler(&default_exception_handler);
66 RegisterLibraryEntries(&_exp_excepman);
72 return RegisterPriorityExceptionHandler(exception, 2, handler);
75int RegisterPriorityExceptionHandler(
int exception,
int priority,
exception_handler_t handler)
84 return KE_EXPHANDLER_USED;
85 if ( (
unsigned int)exception >= (
sizeof(exception_handlers) /
sizeof(exception_handlers[0])) )
86 return KE_ILLEGAL_EXPCODE;
87 priority_masked = priority & 3;
88 exception_handler_new = unlink_head_of_list();
89 eh_ptr = &exception_handlers[exception];
90 exception_handler_new->info = ((uiptr)handler & 0xFFFFFFFC) | priority_masked;
97 if ( ((*eh_ptr)->info & 3) >= priority_masked )
100 }
while ( eh_cur2->next );
103 exception_handler_new->next = eh_cur1;
104 *eh_ptr = exception_handler_new;
105 update_exception_handler_table();
112 return KE_EXPHANDLER_USED;
114 default_handler_funccode = handler->funccode;
115 update_exception_handler_table();
124 if ( (
unsigned int)exception >= (
sizeof(exception_handlers) /
sizeof(exception_handlers[0])) )
125 return KE_ILLEGAL_EXPCODE;
127 if ( !exception_handler->next )
128 return KE_EXPHANDLER_NOUSE;
131 next = exception_handler->next;
134 exception_handler = exception_handler->next;
136 return KE_EXPHANDLER_NOUSE;
138 exception_handler->next = next->next;
139 *(u32 *)(next->info & 0xFFFFFFFC) = 0;
140 link_to_head_of_list(next);
141 update_exception_handler_table();
149 if ( !default_handler_funccode )
150 return KE_EXPHANDLER_NOUSE;
155 if ( cur_handler->funccode == handler->funccode )
157 cur_handler = cur_handler->next;
159 return KE_EXPHANDLER_NOUSE;
161 default_handler_funccode = cur_handler->next->funccode;
162 cur_handler->next = 0;
163 update_exception_handler_table();
167void *GetExHandlersTable(
void)
169 return &exception_table;
172static void update_exception_handler_table(
void)
177 for ( i = 0; i < (
sizeof(exception_handlers) /
sizeof(exception_handlers[0])); i += 1 )
179 exception_handler = exception_handlers[i];
180 if ( exception_handler )
182 while ( exception_handler->next )
184 *(u32 *)(exception_handler->info & 0xFFFFFFFC) = (exception_handler->next->info & 0xFFFFFFFC) + 8;
185 exception_handler = exception_handler->next;
187 *(u32 *)(exception_handler->info & 0xFFFFFFFC) = (uiptr)default_handler_funccode;
190 for ( i = 0; i < (
sizeof(exception_handlers) /
sizeof(exception_handlers[0])); i += 1 )
192 exception_handler = exception_handlers[i];
193 if ( exception_handler )
194 exception_table[i] = (exception_handler->info & 0xFFFFFFFC) + 8;
196 exception_table[i] = (uiptr)default_handler_funccode;
204 if ( !exception_list )
206 exception_list_save = exception_list;
207 if ( exception_list )
208 exception_list = exception_list->next;
209 return exception_list_save;
214 handler->next = exception_list;
215 exception_list = handler;
218static void allocate_list(
void)
223 for ( i = 0; i < 0x1F; i += 1 )
225 exception_list[i].next = &exception_list[i + 1];
227 exception_list[i].next = NULL;
232 "\t" ".set push" "\n"
233 "\t" ".set noat" "\n"
234 "\t" ".set noreorder" "\n"
235 "\t" "exception_handler_shellcode_start:" "\n"
252 "\t" "sw $k0, 0x420($zero)" "\n"
253 "\t" "mfc0 $k1, $14" "\n"
254 "\t" "mfc0 $k0, $13" "\n"
255 "\t" "sw $k1, 0x424($zero)" "\n"
256 "\t" "sw $k0, 0x428($zero)" "\n"
257 "\t" "mfc0 $k1, $12" "\n"
258 "\t" "mfc0 $k0, $7" "\n"
259 "\t" "sw $k1, 0x42C($zero)" "\n"
260 "\t" "sw $k0, 0x430($zero)" "\n"
261 "\t" "addiu $k1, $zero, 0x3C" "\n"
262 "\t" "lw $k1, 0x0($k1)" "\n"
263 "\t" "mtc0 $zero, $7" "\n"
268 "\t" "sw $at, 0x400($zero)" "\n"
269 "\t" "sw $k0, 0x410($zero)" "\n"
270 "\t" "mfc0 $k0, $14" "\n"
271 "\t" "mfc0 $at, $12" "\n"
272 "\t" "sw $k0, 0x404($zero)" "\n"
273 "\t" "sw $at, 0x408($zero)" "\n"
274 "\t" "mfc0 $k0, $13" "\n"
276 "\t" "sw $k0, 0x40C($zero)" "\n"
277 "\t" "andi $k0, $k0, 0x3C" "\n"
278 "\t" "lw $k0, 0x0($k0)" "\n"
288 "\t" "exception_handler_shellcode_end:" "\n"
293 "\t" ".set push" "\n"
294 "\t" ".set noat" "\n"
295 "\t" ".set noreorder" "\n"
296 "\t" "default_exception_handler:" "\n"
299 "\t" "exception_handler_infloop:" "\n"
300 "\t" "b exception_handler_infloop" "\n"
int RegisterExceptionHandler(int exception, exception_handler_t handler)