From 453136149c57ca03b050875a5608a13beb0d32f3 Mon Sep 17 00:00:00 2001 From: someone2639 Date: Sat, 18 Sep 2021 21:56:17 -0400 Subject: [PATCH 01/15] print denorms --- src/game/crash_screen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/crash_screen.c b/src/game/crash_screen.c index d2b274b8..c5516fad 100644 --- a/src/game/crash_screen.c +++ b/src/game/crash_screen.c @@ -154,7 +154,7 @@ void crash_screen_print_float_reg(s32 x, s32 y, s32 regNum, void *addr) { if ((exponent >= -0x7e && exponent <= 0x7f) || bits == 0) { crash_screen_print(x, y, "F%02d:%.3e", regNum, *(f32 *) addr); } else { - crash_screen_print(x, y, "F%02d:---------", regNum); + crash_screen_print(x, y, "F%02d:%08X", regNum, *(u32 *) addr); } } From 612999f1b1edcc5bfde4cb9a785cd500ebe4c212 Mon Sep 17 00:00:00 2001 From: someone2639 Date: Sat, 18 Sep 2021 23:54:35 -0400 Subject: [PATCH 02/15] import my makefile rules; put map data at the end of the rom --- Makefile | 11 ++++++++--- sm64.ld | 37 ++++++++++++++++++++++++++++++------- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index d3bb9e83..2b493d56 100644 --- a/Makefile +++ b/Makefile @@ -575,7 +575,7 @@ $(BUILD_DIR)/src/usb/usb.o: CFLAGS += -Wno-unused-variable -Wno-sign-compare -Wn $(BUILD_DIR)/src/usb/debug.o: OPT_FLAGS := -O0 $(BUILD_DIR)/src/usb/debug.o: CFLAGS += -Wno-unused-parameter -Wno-maybe-uninitialized -ALL_DIRS := $(BUILD_DIR) $(addprefix $(BUILD_DIR)/,$(SRC_DIRS) $(GODDARD_SRC_DIRS) $(LIBZ_SRC_DIRS) $(ULTRA_BIN_DIRS) $(BIN_DIRS) $(TEXTURE_DIRS) $(TEXT_DIRS) $(SOUND_SAMPLE_DIRS) $(addprefix levels/,$(LEVEL_DIRS)) rsp include) $(YAY0_DIR) $(addprefix $(YAY0_DIR)/,$(VERSION)) $(SOUND_BIN_DIR) $(SOUND_BIN_DIR)/sequences/$(VERSION) +ALL_DIRS := $(BUILD_DIR) $(addprefix $(BUILD_DIR)/,$(SRC_DIRS) asm/debug $(GODDARD_SRC_DIRS) $(LIBZ_SRC_DIRS) $(ULTRA_BIN_DIRS) $(BIN_DIRS) $(TEXTURE_DIRS) $(TEXT_DIRS) $(SOUND_SAMPLE_DIRS) $(addprefix levels/,$(LEVEL_DIRS)) rsp include) $(YAY0_DIR) $(addprefix $(YAY0_DIR)/,$(VERSION)) $(SOUND_BIN_DIR) $(SOUND_BIN_DIR)/sequences/$(VERSION) # Make sure build directory exists before compiling anything DUMMY != mkdir -p $(ALL_DIRS) @@ -791,10 +791,15 @@ $(BUILD_DIR)/goddard.txt: $(BUILD_DIR)/sm64_prelim.elf $(call print,Getting Goddard size...) $(V)python3 tools/getGoddardSize.py $(BUILD_DIR)/sm64_prelim.map $(VERSION) +$(BUILD_DIR)/asm/debug/map.o: asm/debug/map.s $(BUILD_DIR)/sm64_prelim.elf + $(call print,Assembling:,$<,$@) + $(V)python3 tools/mapPacker.py $(BUILD_DIR)/sm64_prelim.map $(BUILD_DIR)/bin/addr.bin $(BUILD_DIR)/bin/name.bin + $(V)$(CROSS)gcc -c $(ASMFLAGS) $(foreach i,$(INCLUDE_DIRS),-Wa,-I$(i)) -x assembler-with-cpp -MMD -MF $(BUILD_DIR)/$*.d -o $@ $< + # Link SM64 ELF file -$(ELF): $(BUILD_DIR)/sm64_prelim.elf $(O_FILES) $(YAY0_OBJ_FILES) $(SEG_FILES) $(BUILD_DIR)/$(LD_SCRIPT) undefined_syms.txt $(BUILD_DIR)/libz.a $(BUILD_DIR)/libgoddard.a +$(ELF): $(BUILD_DIR)/sm64_prelim.elf $(BUILD_DIR)/asm/debug/map.o $(O_FILES) $(YAY0_OBJ_FILES) $(SEG_FILES) $(BUILD_DIR)/$(LD_SCRIPT) undefined_syms.txt $(BUILD_DIR)/libz.a $(BUILD_DIR)/libgoddard.a @$(PRINT) "$(GREEN)Linking ELF file: $(BLUE)$@ $(NO_COL)\n" - $(V)$(LD) --gc-sections -L $(BUILD_DIR) -T undefined_syms.txt -T $(BUILD_DIR)/$(LD_SCRIPT) -T goddard.txt -Map $(BUILD_DIR)/sm64.$(VERSION).map --no-check-sections $(addprefix -R ,$(SEG_FILES)) -o $@ $(O_FILES) -L$(LIBS_DIR) -l$(ULTRALIB) -Llib $(LINK_LIBRARIES) -u sprintf -u osMapTLB -Llib/gcclib/$(LIBGCCDIR) -lgcc -lnustd -lhvqm2 + $(V)$(LD) --gc-sections -L $(BUILD_DIR) -T undefined_syms.txt -T $(BUILD_DIR)/$(LD_SCRIPT) -T goddard.txt -Map $(BUILD_DIR)/sm64.$(VERSION).map --no-check-sections $(addprefix -R ,$(SEG_FILES)) -o $@ $(O_FILES) -L$(LIBS_DIR) -l$(ULTRALIB) -Llib $(LINK_LIBRARIES) -u sprintf -u osMapTLB -Llib/gcclib/$(LIBGCCDIR) -lgcc # Build ROM $(ROM): $(ELF) diff --git a/sm64.ld b/sm64.ld index 58d28918..8c61431f 100755 --- a/sm64.ld +++ b/sm64.ld @@ -150,6 +150,7 @@ SECTIONS BUILD_DIR/src/boot*.o(.text); BUILD_DIR/src/hvqm*.o(.text); + BUILD_DIR/src/usb*.o(.text); BUILD_DIR/src/audio*.o(.text); #ifdef S2DEX_TEXT_ENGINE lib/libs2d_engine.a:*(.text); @@ -168,6 +169,7 @@ SECTIONS /* data */ BUILD_DIR/src/boot*.o(.*data*); + BUILD_DIR/src/usb*.o(.*data*); BUILD_DIR/src/audio*.o(.*data*); #ifdef S2DEX_TEXT_ENGINE lib/libs2d_engine.a:*(.*data*); @@ -185,6 +187,7 @@ SECTIONS /* rodata */ BUILD_DIR/src/boot*.o(.rodata*); + BUILD_DIR/src/usb*.o(.rodata*); BUILD_DIR/src/audio*.o(.rodata*); #ifdef S2DEX_TEXT_ENGINE lib/libs2d_engine.a:*(.rodata*); @@ -199,15 +202,32 @@ SECTIONS BUILD_DIR/lib/rsp.o(.rodata*); lib/PR/hvqm/hvqm2sp1.o(.rodata*); +#ifndef PRELIMINARY + BUILD_DIR/src/game/crash_screen.o(.text*); + BUILD_DIR/src/game/crash_screen.o(.data*); + BUILD_DIR/src/game/crash_screen.o(.rodata*); + BUILD_DIR/src/game/map_parser.o(.text*); + BUILD_DIR/src/game/map_parser.o(.data*); + BUILD_DIR/src/game/map_parser.o(.rodata*); +#else + parse_map = 0x80345678; +#endif } END_SEG(main) - #ifndef PRELIMINARY - ASSERT((_mainSegmentRomEnd <= 0x101000), "Error: Please shrink your main segment to under 1MB.") - #endif BEGIN_NOLOAD(main) { +// pad out the space this would've taken +#ifdef PRELIMINARY + BUILD_DIR/src/game/crash_screen.o(.text*); + BUILD_DIR/src/game/crash_screen.o(.data*); + BUILD_DIR/src/game/crash_screen.o(.rodata*); + BUILD_DIR/src/game/map_parser.o(.text*); + BUILD_DIR/src/game/map_parser.o(.data*); + BUILD_DIR/src/game/map_parser.o(.rodata*); +#endif BUILD_DIR/src/boot*.o(.*bss*); BUILD_DIR/src/hvqm*.o(.*bss*); + BUILD_DIR/src/usb*.o(.*bss*); BUILD_DIR/src/audio*.o(.*bss*); #ifdef S2DEX_TEXT_ENGINE lib/libs2d_engine.a:*(.*bss*); @@ -233,23 +253,19 @@ SECTIONS { BUILD_DIR/src/game*.o(.text); BUILD_DIR/src/engine*.o(.text); - BUILD_DIR/src/usb*.o(.text); /* data */ BUILD_DIR/src/game*.o(.*data*); BUILD_DIR/src/engine*.o(.data*); BUILD_DIR/src/engine*.o(.sdata*); - BUILD_DIR/src/usb*.o(.*data*); /* rodata */ BUILD_DIR/src/game*.o(.rodata*); BUILD_DIR/src/engine*.o(.rodata*); - BUILD_DIR/src/usb*.o(.rodata*); } END_SEG(engine) BEGIN_NOLOAD(engine) { BUILD_DIR/src/game*.o(.*bss*); BUILD_DIR/src/engine*.o(.bss*); - BUILD_DIR/src/usb*.o(.*bss*); . = ALIGN(0x40); } END_NOLOAD(engine) @@ -497,6 +513,13 @@ SECTIONS } END_SEG(capcom) #endif + +#ifndef PRELIMINARY + BEGIN_SEG(mapData, 0x80700000) { + KEEP(BUILD_DIR/asm/debug/map.o(.data*)); + } + END_SEG(mapData) +#endif /* DWARF debug sections. Symbols in the DWARF debugging sections are relative to the beginning of the section so we begin them at 0. */ From 25d6ba568d232696ce57a00162dae8ed78c2f1c1 Mon Sep 17 00:00:00 2001 From: someone2639 Date: Sat, 18 Sep 2021 23:55:18 -0400 Subject: [PATCH 03/15] add map parser init --- src/game/crash_screen.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/game/crash_screen.c b/src/game/crash_screen.c index c5516fad..2b0b2819 100644 --- a/src/game/crash_screen.c +++ b/src/game/crash_screen.c @@ -6,6 +6,7 @@ #include "types.h" #include "puppyprint.h" #include "audio/external.h" +#include "farcall.h" #include "sm64.h" @@ -54,6 +55,8 @@ char *gFpcsrDesc[6] = { extern u64 osClockRate; +extern far char *parse_map(u32); +extern far void map_data_init(void); struct { OSThread thread; @@ -154,7 +157,7 @@ void crash_screen_print_float_reg(s32 x, s32 y, s32 regNum, void *addr) { if ((exponent >= -0x7e && exponent <= 0x7f) || bits == 0) { crash_screen_print(x, y, "F%02d:%.3e", regNum, *(f32 *) addr); } else { - crash_screen_print(x, y, "F%02d:%08X", regNum, *(u32 *) addr); + crash_screen_print(x, y, "F%02d:%08XD", regNum, *(u32 *) addr); } } @@ -198,8 +201,14 @@ void draw_crash_screen(OSThread *thread) { #endif crash_screen_draw_rect(25, 45, 270, 185); #if !PUPPYPRINT_DEBUG - crash_screen_print(30, 50, "AT:%08XH V0:%08XH V1:%08XH", (u32) tc->at, (u32) tc->v0, + if ((u32)parse_map == 0x80345678) { + crash_screen_print(30, 50, "AT:%08XH V0:%08XH V1:%08XH", (u32) tc->at, (u32) tc->v0, (u32) tc->v1); + } else { + crash_screen_print(30, 50, "CRASH AT: %s", parse_map(tc->pc)); + } + // crash_screen_print(30, 50, "AT:%08XH V0:%08XH V1:%08XH", (u32) tc->at, (u32) tc->v0, + // (u32) tc->v1); crash_screen_print(30, 60, "A0:%08XH A1:%08XH A2:%08XH", (u32) tc->a0, (u32) tc->a1, (u32) tc->a2); crash_screen_print(30, 70, "A3:%08XH T0:%08XH T1:%08XH", (u32) tc->a3, (u32) tc->t0, @@ -286,6 +295,9 @@ void thread2_crash_screen(UNUSED void *arg) { profiler_update(faultTime, first); #endif } while (thread == NULL); + if ((u32) map_data_init != 0x80345678) { + map_data_init(); + } gCrashScreen.thread.priority = 15; stop_sounds_in_continuous_banks(); stop_background_music(sBackgroundMusicQueue[0].seqId); From 3d570ffe446a44499f071fd797290697b7dfd0ae Mon Sep 17 00:00:00 2001 From: someone2639 Date: Sat, 18 Sep 2021 23:55:37 -0400 Subject: [PATCH 04/15] add map bin tracker --- asm/debug/map.s | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 asm/debug/map.s diff --git a/asm/debug/map.s b/asm/debug/map.s new file mode 100644 index 00000000..fc881942 --- /dev/null +++ b/asm/debug/map.s @@ -0,0 +1,17 @@ +.include "macros.inc" +.section .data +.balign 16 +glabel gMapEntries +.incbin "bin/addr.bin" +glabel gMapEntryEnd + +.balign 16 +glabel gMapStrings +.incbin "bin/name.bin" +glabel gMapStringsEnd + +.balign 16 +glabel gMapEntrySize +.word (gMapEntryEnd - gMapEntries) / 4 +glabel gMapStringSize +.word (gMapStringsEnd - gMapStrings) From ee3fd0b81d42c0b1a72e532f50feb3b1022f6cd5 Mon Sep 17 00:00:00 2001 From: someone2639 Date: Sat, 18 Sep 2021 23:55:48 -0400 Subject: [PATCH 05/15] map parsing code added --- src/game/map_parser.c | 58 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 src/game/map_parser.c diff --git a/src/game/map_parser.c b/src/game/map_parser.c new file mode 100644 index 00000000..ac05e4c3 --- /dev/null +++ b/src/game/map_parser.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include "segments.h" + +struct MapEntry { + u32 addr; + u32 nm_offset; + u32 nm_len; + u32 pad; +}; +extern u8 gMapStrings[]; +extern struct MapEntry gMapEntries[]; +extern u32 gMapEntrySize; +extern u8 _mapDataSegmentRomStart[]; + +u8 *gMapStringAddr; +struct MapEntry *gMapEntryAddr; + +// code provided by Wiseguy +static s32 headless_dma(u32 devAddr, void *dramAddr, u32 size) +{ + register u32 stat; + stat = IO_READ(PI_STATUS_REG); + while (stat & (PI_STATUS_IO_BUSY | PI_STATUS_DMA_BUSY)) { + stat = IO_READ(PI_STATUS_REG); + } + IO_WRITE(PI_DRAM_ADDR_REG, K0_TO_PHYS(dramAddr)); + IO_WRITE(PI_CART_ADDR_REG, K1_TO_PHYS((u32)osRomBase | devAddr)); + IO_WRITE(PI_WR_LEN_REG, size - 1); + return 0; +} +static u32 headless_pi_status(void) +{ + return IO_READ(PI_STATUS_REG); +} +// end of code provided by Wiseguy + + +void map_data_init(void) { + headless_dma(_mapDataSegmentRomStart, 0x80700000, 0x100000); + while (headless_pi_status() & (PI_STATUS_DMA_BUSY | PI_STATUS_ERROR)); +} + +char *parse_map(u32 pc) { + u32 i; + + for (i = 0; i < gMapEntrySize; i++) { + if (gMapEntries[i].addr >= pc) break; + } + + if (i == gMapEntrySize - 1) { + return "Unknown"; + } else { + return (char*) ((u32)gMapStrings + gMapEntries[i - 1].nm_offset); + } +} From d045f95b5c366e58d94a5f4b475155e7fc1a4c1c Mon Sep 17 00:00:00 2001 From: someone2639 Date: Sat, 18 Sep 2021 23:56:00 -0400 Subject: [PATCH 06/15] import map packer script; remove debug print --- tools/mapPacker.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 tools/mapPacker.py diff --git a/tools/mapPacker.py b/tools/mapPacker.py new file mode 100644 index 00000000..d9954522 --- /dev/null +++ b/tools/mapPacker.py @@ -0,0 +1,42 @@ +import sys, struct + +class MapEntry(): + def __init__(self, nm, addr): + self.name = nm + self.addr = addr + self.strlen = (len(nm) + 4) & (~3) + def __str__(self): + return "%s %s %d" % (self.addr, self.name, self.strlen) + def __repr__(self): + return "%s %s %d" % (self.addr, self.name, self.strlen) + + +structDef = ">LLLL" + +symNames = [] + +with open(sys.argv[1]) as f: + for line in f: + if "0x000000008" in line and "=" not in line and "." not in line and "*" not in line and "load address" not in line: + tokens = line.split() + symNames.append(MapEntry(tokens[1], int(tokens[0], 16))) + + + +f1 = open(sys.argv[2], "wb+") +f2 = open(sys.argv[3], "wb+") + +symNames.sort(key=lambda x: x.addr) + +off = 0 +for x in symNames: + f1.write(struct.pack(structDef, x.addr, off, len(x.name), 0)) + f2.write(struct.pack(">%ds" % x.strlen, bytes(x.name, encoding="ascii"))) + off += x.strlen + + +f1.close() +f2.close() + +# print('\n'.join([str(hex(x.addr)) + " " + x.name for x in symNames])) + From cb7357531a1ca1e01c4df74cf73387c68e9210e9 Mon Sep 17 00:00:00 2001 From: someone2639 Date: Sun, 19 Sep 2021 00:33:39 -0400 Subject: [PATCH 07/15] allow map debug to be turned off --- sm64.ld | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/sm64.ld b/sm64.ld index 8c61431f..8a35e8fd 100755 --- a/sm64.ld +++ b/sm64.ld @@ -144,6 +144,15 @@ SECTIONS . = _hvqbufSegmentBssEnd; #endif +/* hardcoded symbols to satisfy preliminary link for map parser */ +#ifndef DEBUG_MAP_STACKTRACE + parse_map = 0x80345678; + _mapDataSegmentRomStart = 0; + gMapEntries = 0; + gMapEntrySize = 0; + gMapStrings = 0; +#endif + BEGIN_SEG(main, .) SUBALIGN(16) { KEEP(BUILD_DIR/asm/entry.o(.text)); @@ -202,29 +211,10 @@ SECTIONS BUILD_DIR/lib/rsp.o(.rodata*); lib/PR/hvqm/hvqm2sp1.o(.rodata*); -#ifndef PRELIMINARY - BUILD_DIR/src/game/crash_screen.o(.text*); - BUILD_DIR/src/game/crash_screen.o(.data*); - BUILD_DIR/src/game/crash_screen.o(.rodata*); - BUILD_DIR/src/game/map_parser.o(.text*); - BUILD_DIR/src/game/map_parser.o(.data*); - BUILD_DIR/src/game/map_parser.o(.rodata*); -#else - parse_map = 0x80345678; -#endif } END_SEG(main) BEGIN_NOLOAD(main) { -// pad out the space this would've taken -#ifdef PRELIMINARY - BUILD_DIR/src/game/crash_screen.o(.text*); - BUILD_DIR/src/game/crash_screen.o(.data*); - BUILD_DIR/src/game/crash_screen.o(.rodata*); - BUILD_DIR/src/game/map_parser.o(.text*); - BUILD_DIR/src/game/map_parser.o(.data*); - BUILD_DIR/src/game/map_parser.o(.rodata*); -#endif BUILD_DIR/src/boot*.o(.*bss*); BUILD_DIR/src/hvqm*.o(.*bss*); BUILD_DIR/src/usb*.o(.*bss*); @@ -514,7 +504,7 @@ SECTIONS END_SEG(capcom) #endif -#ifndef PRELIMINARY +#ifdef DEBUG_MAP_STACKTRACE BEGIN_SEG(mapData, 0x80700000) { KEEP(BUILD_DIR/asm/debug/map.o(.data*)); } From 9c3ee2be96b23caf3dae8be11da9a58d3a2c6740 Mon Sep 17 00:00:00 2001 From: someone2639 Date: Sun, 19 Sep 2021 00:34:21 -0400 Subject: [PATCH 08/15] remove unnecessary bss --- src/game/map_parser.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/game/map_parser.c b/src/game/map_parser.c index ac05e4c3..de5fe935 100644 --- a/src/game/map_parser.c +++ b/src/game/map_parser.c @@ -15,8 +15,6 @@ extern struct MapEntry gMapEntries[]; extern u32 gMapEntrySize; extern u8 _mapDataSegmentRomStart[]; -u8 *gMapStringAddr; -struct MapEntry *gMapEntryAddr; // code provided by Wiseguy static s32 headless_dma(u32 devAddr, void *dramAddr, u32 size) From 4afc5a674958e9370e19f29650c6be09dcee5de0 Mon Sep 17 00:00:00 2001 From: someone2639 Date: Sun, 19 Sep 2021 00:42:06 -0400 Subject: [PATCH 09/15] allow a vector for debug stacktrace to be turned off in the makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 2b493d56..cffca80d 100644 --- a/Makefile +++ b/Makefile @@ -766,7 +766,7 @@ $(BUILD_DIR)/rsp/%.bin $(BUILD_DIR)/rsp/%_data.bin: rsp/%.s # Run linker script through the C preprocessor $(BUILD_DIR)/$(LD_SCRIPT): $(LD_SCRIPT) $(BUILD_DIR)/goddard.txt $(call print,Preprocessing linker script:,$<,$@) - $(V)$(CPP) $(CPPFLAGS) -DBUILD_DIR=$(BUILD_DIR) -MMD -MP -MT $@ -MF $@.d -o $@ $< + $(V)$(CPP) $(CPPFLAGS) -DBUILD_DIR=$(BUILD_DIR) -D DEBUG_MAP_STACKTRACE -MMD -MP -MT $@ -MF $@.d -o $@ $< # Link libgoddard $(BUILD_DIR)/libgoddard.a: $(GODDARD_O_FILES) From f8dbc176f4c170d7a6bb2828d4f8d99706d155fb Mon Sep 17 00:00:00 2001 From: someone2639 Date: Sun, 19 Sep 2021 12:28:49 -0400 Subject: [PATCH 10/15] add markers for text end for stacktrace --- sm64.ld | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sm64.ld b/sm64.ld index 8a35e8fd..6ce35aa2 100755 --- a/sm64.ld +++ b/sm64.ld @@ -175,6 +175,7 @@ SECTIONS */libhvqm2.a:*.o(.text); BUILD_DIR/lib/rsp.o(.text); lib/PR/hvqm/hvqm2sp1.o(.text); + _mainSegmentTextEnd = .; /* data */ BUILD_DIR/src/boot*.o(.*data*); @@ -243,6 +244,7 @@ SECTIONS { BUILD_DIR/src/game*.o(.text); BUILD_DIR/src/engine*.o(.text); + _engineSegmentTextEnd = .; /* data */ BUILD_DIR/src/game*.o(.*data*); BUILD_DIR/src/engine*.o(.data*); @@ -336,6 +338,7 @@ SECTIONS BEGIN_SEG(goddard, RAM_END - GODDARD_SIZE) { KEEP(BUILD_DIR/src/menu*.o(.text)); + _goddardSegmentTextEnd = .; KEEP(BUILD_DIR/src/menu*.o(.data*)); KEEP(BUILD_DIR/src/menu*.o(.rodata*)); #ifdef KEEP_MARIO_HEAD From 8806460e72c129fc30c78686c6176d625a1dee01 Mon Sep 17 00:00:00 2001 From: someone2639 Date: Sun, 19 Sep 2021 12:29:05 -0400 Subject: [PATCH 11/15] add stack traversal --- src/game/map_parser.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/game/map_parser.c b/src/game/map_parser.c index de5fe935..c52df074 100644 --- a/src/game/map_parser.c +++ b/src/game/map_parser.c @@ -4,6 +4,8 @@ #include #include "segments.h" +#define STACK_TRAVERSAL_LIMIT 100 + struct MapEntry { u32 addr; u32 nm_offset; @@ -49,8 +51,38 @@ char *parse_map(u32 pc) { } if (i == gMapEntrySize - 1) { - return "Unknown"; + return NULL; } else { return (char*) ((u32)gMapStrings + gMapEntries[i - 1].nm_offset); } } + +extern u8 _mainSegmentStart[]; +extern u8 _mainSegmentTextEnd[]; +extern u8 _engineSegmentStart[]; +extern u8 _engineSegmentTextEnd[]; +extern u8 _goddardSegmentStart[]; +extern u8 _goddardSegmentTextEnd[]; + +char *find_function_in_stack(u32 *sp) { + for (int i = 0; i < STACK_TRAVERSAL_LIMIT; i++) { + u32 val = *sp; + val = *(u32 *)val; + *sp = *sp + 4; + + if ((val >= (u32)_mainSegmentStart) && (val <= (u32)_mainSegmentTextEnd)) { + return parse_map(val); + } + else if ((val >= (u32)_engineSegmentStart) && (val <= (u32)_engineSegmentTextEnd)) { + return parse_map(val); + } + else if ((val >= (u32)_goddardSegmentStart) && (val <= (u32)_goddardSegmentTextEnd)) { + return parse_map(val); + } + + + } + return NULL; +} + + From 078ee5f595d594891e433793da91bb267ce29bac Mon Sep 17 00:00:00 2001 From: someone2639 Date: Sun, 19 Sep 2021 12:29:23 -0400 Subject: [PATCH 12/15] add 3rd crashscreen page that prints stack trace --- src/game/crash_screen.c | 50 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/src/game/crash_screen.c b/src/game/crash_screen.c index 3f47756d..197f32e3 100644 --- a/src/game/crash_screen.c +++ b/src/game/crash_screen.c @@ -15,8 +15,9 @@ #include "printf.h" enum crashPages { - PAGE_STACK, + PAGE_CONTEXT, PAGE_LOG, + PAGE_STACKTRACE, PAGE_COUNT }; @@ -68,6 +69,7 @@ char *gFpcsrDesc[6] = { extern u64 osClockRate; extern far char *parse_map(u32); extern far void map_data_init(void); +extern far char *find_function_in_stack(u32 *); struct { OSThread thread; @@ -187,7 +189,7 @@ void crash_screen_print_fpcsr(u32 fpcsr) { } } -void draw_crash_stack(OSThread *thread, s32 cause) +void draw_crash_context(OSThread *thread, s32 cause) { __OSThreadContext *tc = &thread->context; @@ -200,7 +202,8 @@ void draw_crash_stack(OSThread *thread, s32 cause) crash_screen_print(30, 50, "AT:%08XH V0:%08XH V1:%08XH", (u32) tc->at, (u32) tc->v0, (u32) tc->v1); } else { - crash_screen_print(30, 50, "CRASH AT: %s", parse_map(tc->pc)); + char *fname = parse_map(tc->pc); + crash_screen_print(30, 50, "CRASH AT: %s", fname == NULL ? "UNKNOWN" : fname); } // crash_screen_print(30, 50, "AT:%08XH V0:%08XH V1:%08XH", (u32) tc->at, (u32) tc->v0, (u32) tc->v1); crash_screen_print(30, 60, "A0:%08XH A1:%08XH A2:%08XH", (u32) tc->a0, (u32) tc->a1, (u32) tc->a2); @@ -250,6 +253,42 @@ void draw_crash_log(OSThread *thread, s32 cause) } +// prints any function pointers it finds in the stack +// format: +// SP address: function name +void draw_stacktrace(OSThread *thread, s32 cause) { + __OSThreadContext *tc = &thread->context; + u32 temp_sp = tc->sp + 0x14; + + crash_screen_draw_rect(25, 20, 270, 25); + crash_screen_print(30, 25, "STACK TRACE FROM %08X:", temp_sp); + if ((u32) parse_map == 0x80345678) { + crash_screen_print(30, 35, "CURRFUNC: NONE"); + } else { + crash_screen_print(30, 35, "CURRFUNC: %s", parse_map(tc->pc)); + } + + osWritebackDCacheAll(); + + for (int i = 0; i < 16; i++) { + if ((u32) find_function_in_stack == 0x80345678) { + crash_screen_print(30, 45 + (i * 10), "STACK TRACE DISABLED"); + break; + } else { + char *fname = find_function_in_stack(&temp_sp); + if (fname == NULL || (*(u32*)temp_sp & 0x80000000 == 0)) { + crash_screen_print(30, 45 + (i * 10), "%08X: UNKNOWN", temp_sp); + } else { + crash_screen_print(30, 45 + (i * 10), "%08X: %s", temp_sp, fname); + } + } + } + + +} + + + void draw_crash_screen(OSThread *thread) { s32 cause; @@ -291,8 +330,9 @@ void draw_crash_screen(OSThread *thread) crash_screen_print(15, 10, "Page:%d L/Z: Left R: Right", crashPage); switch (crashPage) { - case PAGE_STACK: draw_crash_stack(thread, cause); break; - case PAGE_LOG: draw_crash_log(thread, cause); break; + case PAGE_CONTEXT: draw_crash_context(thread, cause); break; + case PAGE_LOG: draw_crash_log(thread, cause); break; + case PAGE_STACKTRACE: draw_stacktrace(thread, cause); break; } osWritebackDCacheAll(); From c97acfb2d88620c1e064149d3950b9103456a9d8 Mon Sep 17 00:00:00 2001 From: someone2639 Date: Sun, 19 Sep 2021 12:35:48 -0400 Subject: [PATCH 13/15] add 2 more stacktrace entries to fill the page --- src/game/crash_screen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/crash_screen.c b/src/game/crash_screen.c index 197f32e3..f26cd92b 100644 --- a/src/game/crash_screen.c +++ b/src/game/crash_screen.c @@ -270,7 +270,7 @@ void draw_stacktrace(OSThread *thread, s32 cause) { osWritebackDCacheAll(); - for (int i = 0; i < 16; i++) { + for (int i = 0; i < 18; i++) { if ((u32) find_function_in_stack == 0x80345678) { crash_screen_print(30, 45 + (i * 10), "STACK TRACE DISABLED"); break; From fa2d2a8052c6d8f498bed195d200e3d15b2af06d Mon Sep 17 00:00:00 2001 From: someone2639 Date: Sun, 19 Sep 2021 12:39:10 -0400 Subject: [PATCH 14/15] fix crash screen behavior when stacktrace is theoretically disabled --- sm64.ld | 1 + src/game/crash_screen.c | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/sm64.ld b/sm64.ld index 6ce35aa2..16b79416 100755 --- a/sm64.ld +++ b/sm64.ld @@ -147,6 +147,7 @@ SECTIONS /* hardcoded symbols to satisfy preliminary link for map parser */ #ifndef DEBUG_MAP_STACKTRACE parse_map = 0x80345678; + find_function_in_stack = 0x80345678; _mapDataSegmentRomStart = 0; gMapEntries = 0; gMapEntrySize = 0; diff --git a/src/game/crash_screen.c b/src/game/crash_screen.c index f26cd92b..63bd5a6c 100644 --- a/src/game/crash_screen.c +++ b/src/game/crash_screen.c @@ -275,6 +275,10 @@ void draw_stacktrace(OSThread *thread, s32 cause) { crash_screen_print(30, 45 + (i * 10), "STACK TRACE DISABLED"); break; } else { + if ((u32) find_function_in_stack == 0x80345678) { + return; + } + char *fname = find_function_in_stack(&temp_sp); if (fname == NULL || (*(u32*)temp_sp & 0x80000000 == 0)) { crash_screen_print(30, 45 + (i * 10), "%08X: UNKNOWN", temp_sp); From e80150657eb1bee0587c1500dbc5b68753b2bcba Mon Sep 17 00:00:00 2001 From: someone2639 Date: Mon, 20 Sep 2021 17:17:09 -0400 Subject: [PATCH 15/15] allow debug map stacktrace to be turned off --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cffca80d..4a3447ff 100644 --- a/Makefile +++ b/Makefile @@ -108,6 +108,8 @@ else ifeq ($(VERSION),sh) GRUCODE ?= f3dzex endif +DEBUG_MAP_STACKTRACE_FLAG := -D DEBUG_MAP_STACKTRACE + TARGET := sm64.$(VERSION) @@ -766,7 +768,7 @@ $(BUILD_DIR)/rsp/%.bin $(BUILD_DIR)/rsp/%_data.bin: rsp/%.s # Run linker script through the C preprocessor $(BUILD_DIR)/$(LD_SCRIPT): $(LD_SCRIPT) $(BUILD_DIR)/goddard.txt $(call print,Preprocessing linker script:,$<,$@) - $(V)$(CPP) $(CPPFLAGS) -DBUILD_DIR=$(BUILD_DIR) -D DEBUG_MAP_STACKTRACE -MMD -MP -MT $@ -MF $@.d -o $@ $< + $(V)$(CPP) $(CPPFLAGS) -DBUILD_DIR=$(BUILD_DIR) $(DEBUG_MAP_STACKTRACE_FLAG) -MMD -MP -MT $@ -MF $@.d -o $@ $< # Link libgoddard $(BUILD_DIR)/libgoddard.a: $(GODDARD_O_FILES)