11#define BACKTRACE_DEBUG 0
14#define FUNCTION_ALIGNMENT 32
45#define MIPS_OP_ADDIU_SP(op) (((op) & 0xFFFF0000) == 0x27BD0000)
46#define MIPS_OP_DADDIU_SP(op) (((op) & 0xFFFF0000) == 0x67BD0000)
47#define MIPS_OP_JR_RA(op) (((op) & 0xFFFFFFFF) == 0x03E00008)
48#define MIPS_OP_SD_RA_SP(op) (((op) & 0xFFFF0000) == 0xFFBF0000)
49#define MIPS_OP_SW_RA_SP(op) (((op) & 0xFFFF0000) == 0xAFBF0000)
50#define MIPS_OP_SD_FP_SP(op) (((op) & 0xFFFF0000) == 0xFFBE0000)
51#define MIPS_OP_SW_FP_SP(op) (((op) & 0xFFFF0000) == 0xAFBE0000)
52#define MIPS_OP_LUI_GP(op) (((op) & 0xFFFF0000) == 0x3C1C0000)
53#define MIPS_OP_NOP(op) ((op) == 0x00000000)
54#define MIPS_OP_MOVE_FP_SP(op) ((op) == 0x03A0F025)
56#define debugf osSyncPrintf
65static u32 get_physical_address(
u32 addr) {
70static bool is_valid_address(
uint32_t addr) {
71 addr = get_physical_address(addr);
72 return addr >= 0x80000400 && addr < 0x80800000 && (addr & 3) == 0;
75static void backtrace_foreach(
void (*
cb)(
void *
arg,
void *ptr),
void *
arg) {
97 :
"=r"(
ra),
"=r"(
sp),
"=r"(
fp)
101 debugf(
"backtrace: start\n");
119 debugf(
"backtrace: %s, ra=%p, sp=%p, fp=%p ra_offset=%d, fp_offset=%d, stack_size=%d\n",
121 ra,
sp,
fp, func.ra_offset, func.fp_offset, func.stack_size);
127 debugf(
"backtrace: framepointer used but not saved onto stack at %p\n",
ra);
132 debugf(
"backtrace: interrupted because of invalid frame pointer 0x%08lx\n", (
uint32_t)
sp);
240 debugf(
"backtrace: %s, ra=%p, sp=%p, fp=%p ra_offset=%d, fp_offset=%d, stack_size=%d\n",
242 ra,
sp,
fp, func.ra_offset, func.fp_offset, func.stack_size);
248 debugf(
"backtrace: framepointer used but not saved onto stack at %p\n",
ra);
253 debugf(
"backtrace: interrupted because of invalid frame pointer 0x%08lx\n", (
uint32_t)
sp);
290static void backtrace_cb(
void *
arg,
void *ptr) {
304 backtrace_foreach(backtrace_cb, &
ctx);
317 backtrace_cb(&
ctx, (
void*)
pc);
332 #define symbolsPerChunk 0x1000
333 #define chunkSize ((sizeof(Symbol) * symbolsPerChunk))
340 osSyncPrintf(
"address2symbol: no symbols available (SYMBOL_TABLE_PTR is NULL)\n");
347 if (
symt.magic[0] !=
'S' ||
symt.magic[1] !=
'Y' ||
symt.magic[2] !=
'M' ||
symt.magic[3] !=
'S') {
348 osSyncPrintf(
"address2symbol: no symbols available (invalid magic '%c%c%c%c')\n",
symt.magic[0],
symt.magic[1],
symt.magic[2],
symt.magic[3]);
351 if (
symt.symbolCount <= 0) {
352 osSyncPrintf(
"address2symbol: no symbols available (symbolCount=%d)\n",
symt.symbolCount);
359 for (
i = 0;
i <
symt.symbolCount;
i++) {
368 if (
sym.address == address) {
371 }
else if (address <
sym.address) {
393 return (
char*)((
u32)dest + (addr & 3));
400 if (offset >= 0 && offset < 0x1000) {
430 for (
i = 0;
i < max;
i++) {
492 #define inthandler ((uint32_t*)0x8006A9F0)
493 #define inthandler_end ((uint32_t*)0x8006B35C)
499 .stack_size = 0, .ra_offset = 0, .fp_offset = 0
507 if (!is_valid_address(addr)) {
509 osSyncPrintf(
"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.
void osSyncPrintf(const char *fmt,...)