13#define BACKTRACE_DEBUG 0
16#define FUNCTION_ALIGNMENT 32
34#define MIPS_OP_ADDIU_SP(op) (((op) & 0xFFFF0000) == 0x27BD0000)
35#define MIPS_OP_DADDIU_SP(op) (((op) & 0xFFFF0000) == 0x67BD0000)
36#define MIPS_OP_JR_RA(op) (((op) & 0xFFFFFFFF) == 0x03E00008)
37#define MIPS_OP_SD_RA_SP(op) (((op) & 0xFFFF0000) == 0xFFBF0000)
38#define MIPS_OP_SW_RA_SP(op) (((op) & 0xFFFF0000) == 0xAFBF0000)
39#define MIPS_OP_SD_FP_SP(op) (((op) & 0xFFFF0000) == 0xFFBE0000)
40#define MIPS_OP_SW_FP_SP(op) (((op) & 0xFFFF0000) == 0xAFBE0000)
41#define MIPS_OP_LUI_GP(op) (((op) & 0xFFFF0000) == 0x3C1C0000)
42#define MIPS_OP_NOP(op) ((op) == 0x00000000)
43#define MIPS_OP_MOVE_FP_SP(op) ((op) == 0x03A0F025)
54static u32 get_physical_address(
u32 addr) {
59static bool is_valid_address(
uint32_t addr) {
60 addr = get_physical_address(addr);
61 return addr >= 0x80000400 && addr < 0x80800000 && (addr & 3) == 0;
64static void backtrace_foreach(
void (*
cb)(
void *
arg,
void *ptr),
void *
arg) {
86 :
"=r"(
ra),
"=r"(
sp),
"=r"(
fp)
90 debugf(
"backtrace: start\n");
108 debugf(
"backtrace: %s, ra=%p, sp=%p, fp=%p ra_offset=%d, fp_offset=%d, stack_size=%d\n",
110 ra,
sp,
fp, func.ra_offset, func.fp_offset, func.stack_size);
116 debugf(
"backtrace: framepointer used but not saved onto stack at %p\n",
ra);
121 debugf(
"backtrace: interrupted because of invalid frame pointer 0x%08lx\n", (
uint32_t)
sp);
229 debugf(
"backtrace: %s, ra=%p, sp=%p, fp=%p ra_offset=%d, fp_offset=%d, stack_size=%d\n",
231 ra,
sp,
fp, func.ra_offset, func.fp_offset, func.stack_size);
237 debugf(
"backtrace: framepointer used but not saved onto stack at %p\n",
ra);
242 debugf(
"backtrace: interrupted because of invalid frame pointer 0x%08lx\n", (
uint32_t)
sp);
279static void backtrace_cb(
void *
arg,
void *ptr) {
293 backtrace_foreach(backtrace_cb, &
ctx);
306 backtrace_cb(&
ctx, (
void*)
pc);
321 #define symbolsPerChunk 0x1000
322 #define chunkSize ((sizeof(Symbol) * symbolsPerChunk))
329 debugf(
"address2symbol: no symbols available (SYMBOL_TABLE_PTR is NULL)\n");
336 if (
symt.magic[0] !=
'S' ||
symt.magic[1] !=
'Y' ||
symt.magic[2] !=
'M' ||
symt.magic[3] !=
'S') {
337 debugf(
"address2symbol: no symbols available (invalid magic '%c%c%c%c')\n",
symt.magic[0],
symt.magic[1],
symt.magic[2],
symt.magic[3]);
340 if (
symt.symbolCount <= 0) {
341 debugf(
"address2symbol: no symbols available (symbolCount=%d)\n",
symt.symbolCount);
348 for (
i = 0;
i <
symt.symbolCount;
i++) {
357 if (
sym.address == address) {
360 }
else if (address <
sym.address) {
382 return (
char*)((
u32)dest + (addr & 3));
389 if (offset >= 0 && offset < 0x1000) {
419 for (
i = 0;
i < max;
i++) {
481 #define inthandler ((uint32_t*)0x8006A9F0)
482 #define inthandler_end ((uint32_t*)0x8006B35C)
488 .stack_size = 0, .ra_offset = 0, .fp_offset = 0
496 if (!is_valid_address(addr)) {
498 debugf(
"backtrace: interrupted because of invalid return address 0x%08x\n", addr);
BSS s32 PopupMenu_SelectedIndex
#define MIPS_OP_LUI_GP(op)
Matches: lui $gp, imm.
int backtrace(void **buffer, int size)
Walk the stack and return the current call stack.
#define MIPS_OP_DADDIU_SP(op)
Matches: daddiu $sp, $sp, imm.
#define MIPS_OP_SD_FP_SP(op)
Matches: sd $fp, imm($sp)
char * load_symbol_string(char *dest, u32 addr, int n)
void debug_backtrace(void)
Print a backtrace.
bool __bt_analyze_func(bt_func_t *func, uint32_t *ptr, uint32_t func_start, bool from_exception)
Analyze a function to find out its stack frame layout and properties (useful for backtracing).
int stack_size
Size of the stack frame.
int backtrace_thread(void **buffer, int size, OSThread *thread)
void backtrace_address_to_string(u32 address, char *dest)
Converts a function address to a string representation using its name, offset, and file.
int ra_offset
Offset of the return address from the top of the stack frame.
#define MIPS_OP_SD_RA_SP(op)
Matches: sd $ra, imm($sp)
s32 address2symbol(u32 address, Symbol *out)
Uses the symbol table to look up the symbol corresponding to the given address.
bt_func_type
The "type" of funciton as categorized by the backtrace heuristic (__bt_analyze_func)
@ BT_FUNCTION_FRAMEPOINTER
The function uses the register fp as frame pointer (normally, this happens only when the function use...
@ BT_LEAF
Leaf function (no calls), no stack frame allocated, sp/ra not modified.
@ BT_EXCEPTION
This is an exception handler (inthandler.S)
@ BT_FUNCTION
Regular function with a stack frame.
#define MIPS_OP_SW_RA_SP(op)
Matches: sw $ra, imm($sp)
#define MIPS_OP_NOP(op)
Matches: nop.
int fp_offset
Offset of the saved fp from the top of the stack frame; this is != 0 only if the function modifies fp...
#define MIPS_OP_ADDIU_SP(op)
Matches: addiu $sp, $sp, imm.
bt_func_type type
Type of the function.
#define MIPS_OP_SW_FP_SP(op)
Matches: sw $fp, imm($sp)
#define MIPS_OP_MOVE_FP_SP(op)
Matches: move $fp, $sp.
#define FUNCTION_ALIGNMENT
Function alignment enfored by the compiler (-falign-functions).
Description of a function for the purpose of backtracing (filled by __bt_analyze_func)
#define SYMBOL_TABLE_PTR_ROM_ADDR
ROM address of the pointer to the symbol table.