You've already forked HackerSM64
mirror of
https://github.com/HackerN64/HackerSM64.git
synced 2026-01-21 10:35:32 -08:00
Update stack trace page + other fixes
This commit is contained in:
@@ -99,22 +99,22 @@ const char* str_null_fallback(const char* str, const char* fallback) {
|
||||
|
||||
//! TODO: One list with both id and pri.
|
||||
static const IdNamePair sThreadIDNames[] = {
|
||||
{ .id = THREAD_0, .name = "libultra?", }, // Uses sThreadPriNames.
|
||||
{ .id = THREAD_1_IDLE, .name = "idle", },
|
||||
{ .id = THREAD_2, .name = "unused", },
|
||||
{ .id = THREAD_3_MAIN, .name = "main", },
|
||||
{ .id = THREAD_4_SOUND, .name = "sound", }, //! TODO: libultra scheduler also uses ID 4 and has no set priority. Is there a way to differentiate the two?
|
||||
{ .id = THREAD_5_GAME_LOOP, .name = "game loop", },
|
||||
{ .id = THREAD_6_RUMBLE, .name = "rumble", },
|
||||
{ .id = THREAD_7_HVQM, .name = "hvqm", },
|
||||
{ .id = THREAD_8_TIMEKEEPER, .name = "timekeeper", },
|
||||
{ .id = THREAD_9_DA_COUNTER, .name = "da counter", },
|
||||
{ .id = THREAD_13_FAULT, .name = "unf fault", },
|
||||
{ .id = THREAD_14_USB, .name = "unf usb", },
|
||||
{ .id = THREAD_15_RDB, .name = "unf rdb", },
|
||||
{ .id = THREAD_1000_CRASH_SCREEN_0, .name = "crash screen 0", },
|
||||
{ .id = THREAD_1001_CRASH_SCREEN_1, .name = "crash screen 1", },
|
||||
{ .id = THREAD_1002_CRASH_SCREEN_2, .name = "crash screen 2", },
|
||||
{ .id = THREAD_0, .name = "libultra?", }, // Uses sThreadPriNames.
|
||||
{ .id = THREAD_1_IDLE, .name = "idle", },
|
||||
{ .id = THREAD_2, .name = "unused", },
|
||||
{ .id = THREAD_3_MAIN, .name = "main", },
|
||||
{ .id = THREAD_4_SOUND, .name = "sound", }, //! TODO: libultra scheduler also uses ID 4 and has no set priority. Is there a way to differentiate the two?
|
||||
{ .id = THREAD_5_GAME_LOOP, .name = "game loop", },
|
||||
{ .id = THREAD_6_RUMBLE, .name = "rumble", },
|
||||
{ .id = THREAD_7_HVQM, .name = "hvqm", },
|
||||
{ .id = THREAD_8_TIMEKEEPER, .name = "timekeeper", },
|
||||
{ .id = THREAD_9_DA_COUNTER, .name = "da counter", },
|
||||
{ .id = THREAD_13_FAULT, .name = "unf fault", },
|
||||
{ .id = THREAD_14_USB, .name = "unf usb", },
|
||||
{ .id = THREAD_15_RDB, .name = "unf rdb", },
|
||||
{ .id = THREAD_1000_CRASH_SCREEN_0, .name = "crash screen 0", },
|
||||
{ .id = THREAD_1001_CRASH_SCREEN_1, .name = "crash screen 1", },
|
||||
{ .id = THREAD_1002_CRASH_SCREEN_2, .name = "crash screen 2", },
|
||||
};
|
||||
static const IdNamePair sThreadPriNames[] = {
|
||||
{ .id = OS_PRIORITY_SIMGR, .name = "si manager", },
|
||||
|
||||
@@ -99,7 +99,7 @@ void draw_segments_list(CSTextCoord_u32 line) {
|
||||
// Line 2:
|
||||
if (showAddresses && isLoaded) {
|
||||
if (isHardcoded) {
|
||||
cs_print(TEXT_X(1), y, STR_COLOR_PREFIX"hardcoded", COLOR_RGBA32_GRAY);
|
||||
cs_print(TEXT_X(1), y, STR_COLOR_PREFIX"hardcoded", COLOR_RGBA32_CRASH_HEADER);
|
||||
} else {
|
||||
const RGBA32 romColor = COLOR_RGBA32_LIGHT_BLUE;
|
||||
CSTextCoord_u32 romStrStart = cs_print(TEXT_X(1), y, STR_COLOR_PREFIX"loaded:", COLOR_RGBA32_CRASH_HEADER);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "crash_screen/util/insn_disasm.h"
|
||||
#include "crash_screen/util/map_parser.h"
|
||||
#include "crash_screen/cs_controls.h"
|
||||
#include "crash_screen/cs_descriptions.h"
|
||||
#include "crash_screen/cs_draw.h"
|
||||
#include "crash_screen/cs_main.h"
|
||||
#include "crash_screen/cs_pages.h"
|
||||
@@ -26,7 +27,7 @@
|
||||
|
||||
struct CSSetting cs_settings_group_page_stack[] = {
|
||||
[CS_OPT_HEADER_PAGE_STACK ] = { .type = CS_OPT_TYPE_HEADER, .name = "STACK TRACE", .valNames = &gValNames_bool, .val = SECTION_EXPANDED_DEFAULT, .defaultVal = SECTION_EXPANDED_DEFAULT, .lowerBound = FALSE, .upperBound = TRUE, },
|
||||
[CS_OPT_STACK_SHOW_ADDRESSES ] = { .type = CS_OPT_TYPE_SETTING, .name = "Show stack addresses", .valNames = &gValNames_bool, .val = FALSE, .defaultVal = FALSE, .lowerBound = FALSE, .upperBound = TRUE, },
|
||||
[CS_OPT_STACK_SHOW_ADDRESSES ] = { .type = CS_OPT_TYPE_SETTING, .name = "Show addresses in stack", .valNames = &gValNames_bool, .val = FALSE, .defaultVal = FALSE, .lowerBound = FALSE, .upperBound = TRUE, },
|
||||
[CS_OPT_STACK_SHOW_OFFSETS ] = { .type = CS_OPT_TYPE_SETTING, .name = "Show function offsets", .valNames = &gValNames_bool, .val = TRUE, .defaultVal = TRUE, .lowerBound = FALSE, .upperBound = TRUE, },
|
||||
[CS_OPT_END_STACK ] = { .type = CS_OPT_TYPE_END, },
|
||||
};
|
||||
@@ -144,14 +145,14 @@ _Bool fill_function_stack_trace(void) {
|
||||
Address* sp = (Address*)((Address)t_sp);
|
||||
|
||||
if (IS_DEBUG_MAP_ENABLED()) {
|
||||
const Address t_ra = tc->ra; // thread $ra
|
||||
Address* ra = (Address*)((Address)t_ra - LINK_SIZE);
|
||||
const Address t_ra = ((Address)tc->ra - LINK_SIZE); // thread $ra - link
|
||||
Address* ra = (Address*)t_ra;
|
||||
_Bool err = FALSE;
|
||||
|
||||
if (!stacktrace_step(&sp, &ra, epc)) {
|
||||
// $EPC is in a leaf function, so get the next entry from $ra because it's not in the stack.
|
||||
if (stacktrace_step(&sp, &ra, ((Address)t_ra - LINK_SIZE))) {
|
||||
append_stack_entry_to_buffer((Address)t_sp, (t_ra - LINK_SIZE));
|
||||
if (stacktrace_step(&sp, &ra, t_ra)) {
|
||||
append_stack_entry_to_buffer(t_sp, t_ra);
|
||||
} else {
|
||||
set_stack_trace_error_mesg(stack_error_leaf_not_at_top);
|
||||
err = TRUE;
|
||||
@@ -165,8 +166,9 @@ _Bool fill_function_stack_trace(void) {
|
||||
success = TRUE;
|
||||
break;
|
||||
}
|
||||
append_stack_entry_to_buffer((Address)ra, (*ra - LINK_SIZE));
|
||||
if (!stacktrace_step(&sp, &ra, ((Address)*ra - LINK_SIZE))) {
|
||||
Address raddr = ((Address)*ra - LINK_SIZE);
|
||||
append_stack_entry_to_buffer((Address)ra, raddr);
|
||||
if (!stacktrace_step(&sp, &ra, raddr)) {
|
||||
set_stack_trace_error_mesg(stack_error_leaf_not_at_top);
|
||||
break;
|
||||
}
|
||||
@@ -178,18 +180,20 @@ _Bool fill_function_stack_trace(void) {
|
||||
// Just uses all aligned .text addresses in the stack.
|
||||
if (!success) {
|
||||
// Align sp to lower 32 of 64:
|
||||
sp = (Address*)(ALIGNFLOOR((Address)sp, sizeof(Doubleword)) + sizeof(Address));
|
||||
Address* ra = (Address*)(ALIGNFLOOR((Address)sp, sizeof(Doubleword)) + sizeof(Address));
|
||||
|
||||
// Loop through the stack buffer and find all the addresses that point to a function.
|
||||
while (sStackTraceBufferEnd < STACK_TRACE_BUFFER_SIZE) {
|
||||
if (*sp == (Address)__osCleanupThread) {
|
||||
if (*ra == (Address)__osCleanupThread) {
|
||||
success = TRUE;
|
||||
break;
|
||||
} else if (addr_is_in_text_segment(*sp)) {
|
||||
append_stack_entry_to_buffer((Address)sp, (*sp - LINK_SIZE));
|
||||
}
|
||||
Address raddr = ((Address)*ra - LINK_SIZE);
|
||||
if (addr_is_in_text_segment(raddr)) {
|
||||
append_stack_entry_to_buffer((Address)ra, raddr);
|
||||
}
|
||||
|
||||
sp += 2;
|
||||
ra += 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,6 +249,11 @@ void stack_trace_print_entries(CSTextCoord_u32 line, CSTextCoord_u32 numLines) {
|
||||
((currIndex == 0) ? COLOR_RGBA32_CRASH_AT : COLOR_RGBA32_WHITE),
|
||||
function->stackAddr
|
||||
);
|
||||
} else if (row > 0) {
|
||||
charX += cs_print(TEXT_X(charX), y,
|
||||
STR_COLOR_PREFIX"at ",
|
||||
COLOR_RGBA32_GRAY
|
||||
);
|
||||
}
|
||||
|
||||
Address currAddr = function->currAddr;
|
||||
@@ -273,6 +282,7 @@ void stack_trace_print_entries(CSTextCoord_u32 line, CSTextCoord_u32 numLines) {
|
||||
STR_COLOR_PREFIX"%s",
|
||||
COLOR_RGBA32_CRASH_FUNCTION_NAME, get_map_symbol_name(symbol)
|
||||
);
|
||||
// cs_print_addr_location_info(TEXT_X(charX), y, (CRASH_SCREEN_NUM_CHARS_X - charX), currAddr, TRUE);
|
||||
} else {
|
||||
// "[address in function]"
|
||||
cs_print(TEXT_X(charX), y,
|
||||
@@ -292,14 +302,24 @@ void stack_trace_print_entries(CSTextCoord_u32 line, CSTextCoord_u32 numLines) {
|
||||
// prints any function pointers it finds in the stack format:
|
||||
// SP address: function name
|
||||
void page_stack_draw(void) {
|
||||
OSThread* thread = gInspectThread;
|
||||
CSTextCoord_u32 line = 1;
|
||||
CSTextCoord_u32 charX = 0;
|
||||
|
||||
charX += cs_print(TEXT_X(charX), TEXT_Y(line++),
|
||||
(STR_COLOR_PREFIX"SP: "STR_COLOR_PREFIX STR_HEX_WORD" "STR_COLOR_PREFIX"in thread: "STR_COLOR_PREFIX"%d %s"),
|
||||
COLOR_RGBA32_CRASH_VARIABLE, COLOR_RGBA32_WHITE,
|
||||
(Address)thread->context.sp,
|
||||
COLOR_RGBA32_CRASH_HEADER, COLOR_RGBA32_CRASH_THREAD_NAME,
|
||||
thread->id, str_null_fallback(get_thread_name(thread), "unknown")
|
||||
);
|
||||
|
||||
cs_draw_divider(DIVIDER_Y(line));
|
||||
charX = 0;
|
||||
if (cs_get_setting_val(CS_OPT_GROUP_PAGE_STACK, CS_OPT_STACK_SHOW_ADDRESSES)) {
|
||||
cs_print(TEXT_X(0), TEXT_Y(line), "IN STACK:");
|
||||
charX = STRLEN("00000000:");
|
||||
}
|
||||
|
||||
cs_print(TEXT_X(charX), TEXT_Y(line), STR_COLOR_PREFIX"FUNCTION:", COLOR_RGBA32_CRASH_FUNCTION_NAME);
|
||||
|
||||
#ifdef INCLUDE_DEBUG_MAP
|
||||
|
||||
@@ -159,7 +159,7 @@ void cs_draw_register_info_long(CSTextCoord_u32 charX, CSTextCoord_u32 line, Reg
|
||||
|
||||
// FP is part of FPCSR.
|
||||
if (reg.valInfo.type == REG_VAL_TYPE_CONDBIT) {
|
||||
name = "FP";
|
||||
name = "FC";
|
||||
data = ((Reg_FPR_31)data).C;
|
||||
}
|
||||
|
||||
|
||||
@@ -437,7 +437,7 @@ void reginspect_draw_contents(RegisterId regId) {
|
||||
line += gCSNumLinesPrinted;
|
||||
if (checkThread && (regInfo->offset != REGINFO_NULL_OFFSET)) {
|
||||
cs_print(TEXT_X(2), TEXT_Y(line), STR_COLOR_PREFIX" on thread %d (%s)", COLOR_RGBA32_CRASH_VARIABLE,
|
||||
gInspectThread->id, get_thread_name(gInspectThread)
|
||||
gInspectThread->id, str_null_fallback(get_thread_name(gInspectThread), "unknown")
|
||||
);
|
||||
line += gCSNumLinesPrinted;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ ALIGNED32 static const RegisterInfo sRegInfo_CPU[CPU_NUM_REGISTERS] = {
|
||||
[REG_CPU_K0] = DEF_CPU_SREG(k0, "K0", FALSE, REG_DESC_KERNEL), [REG_CPU_K1] = DEF_CPU_SREG(k1, "K1", FALSE, REG_DESC_KERNEL),
|
||||
[REG_CPU_GP] = DEF_CPU_TREG(gp, "GP", TRUE, REG_DESC_GP ),
|
||||
[REG_CPU_SP] = DEF_CPU_TREG(sp, "SP", TRUE, REG_DESC_SP ),
|
||||
[REG_CPU_FP] = DEF_CPU_TREG(s8, "S8", FALSE, REG_DESC_FP ),
|
||||
[REG_CPU_FP] = DEF_CPU_TREG(s8, "FP", FALSE, REG_DESC_FP ), //! TODO: "FP" or "S8"?
|
||||
[REG_CPU_RA] = DEF_CPU_TREG(ra, "RA", TRUE, REG_DESC_RA ),
|
||||
};
|
||||
#define CASE_CPU_REG(_idx, _reg) CASE_REG(CPU, _idx, _reg)
|
||||
|
||||
Reference in New Issue
Block a user