Skip to content

Commit

Permalink
address2symbol: only consider symbols in loaded segments
Browse files Browse the repository at this point in the history
  • Loading branch information
bates64 committed Oct 23, 2024
1 parent 0dd32dd commit 8896cff
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 25 deletions.
4 changes: 2 additions & 2 deletions include/macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
#define PANIC() IS_DEBUG_PANIC("Panic")
#define PANIC_MSG(msg, args...) \
do { \
char panicMsg[0x40]; \
char panicMsg[0x60]; \
sprintf(panicMsg, msg, ##args); \
IS_DEBUG_PANIC(panicMsg); \
} while (0)
Expand All @@ -53,7 +53,7 @@
}
#define ASSERT_MSG(condition, msg, args...) \
if (!(condition)) { \
char assertMsg[0x40]; \
char assertMsg[0x60]; \
sprintf(assertMsg, msg, ##args); \
IS_DEBUG_PANIC(assertMsg); \
}
Expand Down
32 changes: 32 additions & 0 deletions src/43F0.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "common.h"
#include "nu/nusys.h"
#include "gcc/string.h"
#include "dx/debug_menu.h"
#include "ld_addrs.h"

u16 heap_nextMallocID = 0;

Expand Down Expand Up @@ -435,6 +437,8 @@ void copy_matrix(Matrix4f src, Matrix4f dest) {
bcopy(src, dest, sizeof(Matrix4f));
}

static struct { u32 ram; u32 rom } loadedSegmentMap[128]; // dict ram -> rom

// maybe u32
u32 dma_copy(Addr romStart, Addr romEnd, void* vramDest) {
u32 length = romEnd - romStart;
Expand All @@ -450,9 +454,37 @@ u32 dma_copy(Addr romStart, Addr romEnd, void* vramDest) {
nuPiReadRom((u32)romStart + i, vramDest + i, length - i);
}

// Mark segment as loaded and return length
for (s32 i = 0; i < ARRAY_COUNT(loadedSegmentMap); i++) {
if (loadedSegmentMap[i].ram == (u32)vramDest) {
loadedSegmentMap[i].rom = (u32)romStart;
return length;
}
}
for (s32 i = 0; i < ARRAY_COUNT(loadedSegmentMap); i++) {
if (loadedSegmentMap[i].ram == 0) {
loadedSegmentMap[i].ram = (u32)vramDest;
loadedSegmentMap[i].rom = (u32)romStart;
return length;
}
}
debug_print("loadedSegmentMap overflow\n");
return length;
}

b32 dma_is_segment_loaded(u32 romStart) {
// main is loaded by boot.s, and is always loaded
if (romStart == main_ROM_START)
return TRUE;

for (s32 i = 0; i < ARRAY_COUNT(loadedSegmentMap); i++) {
if (loadedSegmentMap[i].rom == romStart) {
return TRUE;
}
}
return FALSE;
}

s32 dma_write(Addr romStart, Addr romEnd, void* vramDest) {
u32 length = romEnd - romStart;
s32 i;
Expand Down
4 changes: 2 additions & 2 deletions src/crash_screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const char* gFPCSRFaultCauses[6] = {
"Inexact operation",
};

char crashScreenAssertMessage[0x30] = {0};
char crashScreenAssertMessage[0x60] = {0};

void crash_screen_set_assert_info(const char* message) {
strncpy(crashScreenAssertMessage, message, sizeof(crashScreenAssertMessage));
Expand Down Expand Up @@ -330,7 +330,7 @@ void crash_screen_draw(OSThread* faultedThread) {

for (; i < max; i++) {
backtrace_address_to_string(bt[i], buf);
crash_screen_printf_proportional(x + 10, y += 10, "at %s", buf);
crash_screen_printf_proportional(x + 10, y += 10, "in %s", buf);
}

y += 5;
Expand Down
21 changes: 13 additions & 8 deletions src/dx/backtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,8 @@ int backtrace_thread(void **buffer, int size, OSThread *thread) {
return ctx.i;
}

b32 dma_is_segment_loaded(u32 romStart);

/**
* @brief Uses the symbol table to look up the symbol corresponding to the given address.
*
Expand All @@ -328,7 +330,7 @@ int backtrace_thread(void **buffer, int size, OSThread *thread) {
* @return Offset into out->address, -1 if not found
*/
s32 address2symbol(u32 address, Symbol* out) {
#define symbolsPerChunk 0x1000
#define symbolsPerChunk 0x100
#define chunkSize ((sizeof(Symbol) * symbolsPerChunk))

static u32 romHeader[0x10];
Expand Down Expand Up @@ -364,6 +366,9 @@ s32 address2symbol(u32 address, Symbol* out) {

Symbol sym = chunk[i % symbolsPerChunk];

if (!dma_is_segment_loaded(sym.segmentRomStart))
continue;

if (sym.address == address) {
*out = sym;
return 0;
Expand Down Expand Up @@ -396,22 +401,22 @@ void backtrace_address_to_string(u32 address, char* dest) {
Symbol sym;
s32 offset = address2symbol(address, &sym);

if (offset >= 0 && offset < 0x1000) { // 0x1000 = arbitrary func size limit
if (offset >= 0 && offset < 0x4000) { // 0x4000 = arbitrary func size limit
char name[32];
char file[32];
char* namep = load_symbol_string(name, sym.nameOffset, ARRAY_COUNT(name));
char* filep = load_symbol_string(file, sym.fileOffset, ARRAY_COUNT(file));

if (filep == NULL)
if (offset == 0)
//if (offset == 0)
sprintf(dest, "%s", namep);
else
sprintf(dest, "%s+0x%X", namep, offset);
//else
// sprintf(dest, "%s+0x%X", namep, offset);
else
if (offset == 0)
//if (offset == 0)
sprintf(dest, "%s (%s)", namep, filep);
else
sprintf(dest, "%s (%s+0x%X)", namep, filep, offset);
//else
// sprintf(dest, "%s (%s+0x%X)", namep, filep, offset);
} else {
sprintf(dest, "0x%08X", address);
}
Expand Down
1 change: 1 addition & 0 deletions src/dx/backtrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ typedef struct Symbol {
u32 address; ///< RAM address.
u32 nameOffset; ///< Offset of the symbol name string.
u32 fileOffset; ///< Offset of the file name and line string.
u32 segmentRomStart; ///< ROM start of segment.
} Symbol;

typedef struct SymbolTable {
Expand Down
6 changes: 6 additions & 0 deletions src/dx/debug_menu.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#include "common.h"
#include "dx/config.h"

#ifndef __DX_DEBUG_MENU_H__
#define __DX_DEBUG_MENU_H__

#if DX_DEBUG_MENU || defined(DX_QUICK_LAUNCH_BATTLE)

#define DX_DEBUG_DUMMY_ID 0xDEAD
Expand Down Expand Up @@ -69,3 +73,5 @@ API_CALLABLE(_dxDebugFloatPrintf);
Call(_dxDebugFloatPrintf, Ref(__FILE__), __LINE__, Ref(text), a, b, c, d, e, f, g)

#endif

#endif
40 changes: 27 additions & 13 deletions tools/build/append_symbol_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,24 @@


def readelf(elf: str) -> List[Tuple[int, str, str, int]]:
addr2name = {} # funcs
addr2name = {} # funcs and globals
addr2line = {} # debug info
segment2romstart = {} # segment name -> rom start address

process = subprocess.Popen(["mips-linux-gnu-readelf", "-s", elf, "--wide", "-wL", "--demangle"], stdout=subprocess.PIPE)
process = subprocess.Popen(["mips-linux-gnu-objdump", elf, "-t", "--wide", "--dwarf=decodedline", "--demangle"], stdout=subprocess.PIPE)
for line in io.TextIOWrapper(process.stdout, encoding="utf-8"):
parts = line.split()

# 75082: 8048d5bc 44 FUNC GLOBAL DEFAULT 1845 func_802BC0B8_E2E9E8
if len(parts) == 8 and parts[3] in ["FUNC", "OBJECT"]:
addr = int(parts[1], 16)
# 8004bbd0 g F .main 00000060 GetSelfAnimationFromTable
if len(parts) == 6 and parts[2] in ["F", "O"]:
addr = int(parts[0], 16)
segment = parts[3][1:]
name = parts[-1]
if segment.endswith("_bss") or segment == "ABS*": # ignore BSS
continue
if name.startswith("dead_"):
continue
addr2name[addr] = name
addr2name[addr] = (name, segment)

# npc.c 120 0x8003910c x
elif len(parts) >= 4 and parts[2].startswith("0x"):
Expand All @@ -33,12 +37,19 @@ def readelf(elf: str) -> List[Tuple[int, str, str, int]]:
addr = int(parts[2], 0)
addr2line[addr] = (file_basename, line_number)

# 00001000 g *ABS* 00000000 main_ROM_START
elif len(parts) == 5 and parts[-1].endswith("_ROM_START"):
addr = int(parts[0], 16)
segment = parts[-1][0:-len("_ROM_START")]
segment2romstart[segment] = addr

sorted_addr2name_addrs = sorted(addr2name.keys())

symbols = []
for addr, (file_basename, line_number) in addr2line.items():
if addr in addr2name:
symbols.append((addr, addr2name[addr], file_basename, line_number))
name, segment = addr2name[addr]
symbols.append((addr, name, file_basename, line_number, segment2romstart[segment]))
else:
# find closest addr2name < addr
closest_addr = None
Expand All @@ -48,13 +59,14 @@ def readelf(elf: str) -> List[Tuple[int, str, str, int]]:
else:
break
if closest_addr is not None:
symbols.append((addr, addr2name[closest_addr], file_basename, line_number))
name, segment = addr2name[addr]
symbols.append((addr, name, file_basename, line_number, segment2romstart[segment]))

# non-debug builds
if len(symbols) == 0:
print("no debug symbols found, using func names only")
for addr, name in addr2name.items():
symbols.append((addr, name, "", -1))
for addr, (name, segment) in addr2name.items():
symbols.append((addr, name, "", -1, segment2romstart[segment]))

# sort by address
symbols.sort(key=lambda x: x[0])
Expand Down Expand Up @@ -89,7 +101,7 @@ def readelf(elf: str) -> List[Tuple[int, str, str, int]]:
f.write(b"SYMS")
f.write(struct.pack(">I", len(symbols)))

sizeof_symbol = 4 + 4 + 4 # sizeof(Symbol)
sizeof_symbol = 4 + 4 + 4 + 4 # sizeof(Symbol)
strings_begin = f.tell() + sizeof_symbol * len(symbols)
strings = bytearray()
string_map = {}
Expand All @@ -103,7 +115,7 @@ def add_string(s: str):
strings += b"\0"
return string_map[s]

for addr, name, file_basename, line_number in symbols:
for addr, name, file_basename, line_number, segment_rom_start in symbols:
# file_line = file_line.replace(root_dir + "/", "")

f.write(struct.pack(">I", addr))
Expand All @@ -114,14 +126,16 @@ def add_string(s: str):
else:
f.write(struct.pack(">I", add_string(f"{file_basename}:{line_number}"))) # can make more efficient

f.write(struct.pack(">I", segment_rom_start))

f.write(strings)

# Pad to the nearest 16-byte alignment
padding_size = (f.tell() + 15) & ~15
padding_bytes = b"\x00" * (padding_size - f.tell())
f.write(padding_bytes)

print("symbol table size: {} kib".format((f.tell() - symbol_table_addr) / 1024))
print("symbol table size: {} kib ({} symbols)".format((f.tell() - symbol_table_addr) / 1024, len(symbols)))

print(f"updating SYMBOL_TABLE_PTR_ROM_ADDR")
f.seek(SYMBOL_TABLE_PTR_ROM_ADDR)
Expand Down

0 comments on commit 8896cff

Please sign in to comment.