partial overlay breakpoint support via GDB

This commit is contained in:
Joshua Smith 2024-10-08 11:20:16 -05:00
parent 7f68c4e93d
commit 133f80ac2b
7 changed files with 87 additions and 14 deletions

View File

@ -36,7 +36,7 @@ For contacts and other pret projects, see [pret.github.io](https://pret.github.i
},
{
"description": "Set architecture",
"text": "set architecture auto"
"text": "set architecture armv5te"
},
{
"description": "Enable overlays",
@ -52,4 +52,6 @@ For contacts and other pret projects, see [pret.github.io](https://pret.github.i
3. Launch melonDS with GDB stub enabled and launch the pokeplatinum ROM (you may need to fiddle with the config file to make this work, melonDS GDB stub config is off and may not actually enable properly through the UI)
4. Run debugger through VS Code, it should connect to melonDS automatically.
4. Run debugger through VS Code, it should connect to melonDS automatically.
5. Pause the debugger and run `-exec overlay section-map build/overlay.map` (this cannot currently be included in setupCommands due to issues with architecture loading).

View File

@ -21,7 +21,7 @@ export MESON_RSP_THRESHOLD=16387
if [ "$target" = test ]; then
"${MESON:-meson}" test -C build "$@"
elif [ "$target" = rom ]; then
"${MESON:-meson}" compile -C build "pokeplatinum.us.nds" "debug.nef"
"${MESON:-meson}" compile -C build "pokeplatinum.us.nds" "debug.nef" "overlay.map"
else
"${MESON:-meson}" compile -C build "$target" "$@"
fi

View File

@ -16,14 +16,13 @@ BOOL Overlay_LoadByID(const FSOverlayID param0, int param1);
typedef struct {
unsigned long vma;
unsigned long size;
unsigned long lma;
FSOverlayID ovly_id;
unsigned long mapped;
} struct_overlayTable;
#define MAX_OVERLAYS 128
extern unsigned long _novlys;
extern const char _ovly_name[];
extern struct_overlayTable _ovly_table[MAX_OVERLAYS];
static void _ovly_debug_event(void);

View File

@ -229,7 +229,7 @@ pokeplatinum_nds = custom_target('pokeplatinum.us.nds',
)
############################################################
### NEF FIXER ###
### GDB HELPERS ###
############################################################
nef_fixer = custom_target('debug.nef',
output: [
@ -244,6 +244,19 @@ nef_fixer = custom_target('debug.nef',
build_by_default: true
)
ovly_mapper = custom_target('overlay.map',
output: [
'overlay.map'
],
input: [
main_lsf
],
command : [
overlay_mapper_py, '@INPUT@', '@OUTPUT@'
],
build_by_default: true
)
############################################################
### TESTS ###

View File

@ -35,7 +35,6 @@ BOOL Overlay_LoadByID(const FSOverlayID param0, int param1);
static UnkStruct_021BF370 Unk_021BF370;
/* Added to support GDB overlay debugging. */
const char _ovly_name[] = "overlay%d";
unsigned long _novlys = MAX_OVERLAYS;
struct_overlayTable _ovly_table[MAX_OVERLAYS] = {};
static void _ovly_debug_event(void) {}
@ -48,25 +47,26 @@ void UnloadOverlayGDB(const FSOverlayID overlayID)
void LoadOverlayGDB(const FSOverlayID overlayID)
{
FSOverlayInfo overlayInfo;
FSFileID fileInfo;
// dummies to force symbols to exist
// dummy to force symbols to exist
GF_ASSERT(overlayID < _novlys);
strcmp(_ovly_name, _ovly_name);
if(_ovly_table[overlayID].mapped != 0) return;
// 1. fetch overlay info to identify vma/lma
// 1. fetch overlay info to identify vma
GF_ASSERT(FS_LoadOverlayInfo(&overlayInfo, MI_PROCESSOR_ARM9, overlayID) == TRUE);
fileInfo = FS_GetOverlayFileID(&overlayInfo);
// 2. add entry to _ovly_table
// note that this is a little hacky. the VMA is correct but the LMA is not exposed by the OverlayManager
// and the size field is not correct compared to what's stored in the NEF.
// the standard overlay manager in GDB bases comparisons on VMA and LMA, so it's not viable here.
// requires a custom GDB build which uses section name and which can override section size.
// requires a custom GDB build which uses overlay mappings and which can override section size.
// see https://github.com/joshua-smith-12/binutils-gdb-nds
_ovly_table[overlayID].vma = overlayInfo.header.ram_address;
_ovly_table[overlayID].lma = 0;
_ovly_table[overlayID].size = overlayInfo.header.ram_size;
_ovly_table[overlayID].ovly_id = overlayID;
_ovly_table[overlayID].size = overlayInfo.header.ram_size;
_ovly_table[overlayID].mapped = 1;
_ovly_debug_event();
}

View File

@ -10,4 +10,5 @@ make_species_tables_py = find_program('make_species_tables.py', native: true)
make_tutorable_moves_py = find_program('make_tutorable_moves.py', native: true)
make_pokedex_data_py = find_program('make_pokedex_data.py', native: true)
make_pokedex_message_banks_py = find_program('make_pokedex_message_banks.py', native: true)
nef_fixer_py = find_program('nef_fixer.py', native: true)
nef_fixer_py = find_program('nef_fixer.py', native: true)
overlay_mapper_py = find_program('overlay_mapper.py', native: true)

View File

@ -0,0 +1,58 @@
#!/usr/bin/env python3
import subprocess
import os
import shutil
import sys
try:
os.remove("overlay.map")
except:
pass
source = sys.argv[1]
dest = sys.argv[2]
# TERRIBLE but necessary to allow using the LSF file
def base_path(path):
splitted = path.split("_")
maybe_path = ""
found_dir = ".." # need to escape builddir because this sucks
while len(splitted) > 1:
segment = splitted[0]
splitted = splitted[1:]
maybe_path += segment
if os.path.isdir(found_dir + "/" + maybe_path):
found_dir = found_dir + "/" + maybe_path
maybe_path = ""
else:
maybe_path += "_"
maybe_path += splitted[0]
return maybe_path[:-2] # remove '.o'
# VERY inflexible parsing!
overlays = {}
sources = {}
overlay_index = 0
current_overlay = None
in_block = False
with open(source) as f:
for line in f.readlines():
if current_overlay == None and not in_block and line.strip().startswith("Overlay"):
current_overlay = line.strip().replace("Overlay ", "")
overlays[current_overlay] = overlay_index
overlay_index += 1
elif not in_block and line.strip() == "{":
in_block = True
elif in_block and line.strip() == "}":
in_block = False
current_overlay = None
elif current_overlay != None and in_block and line.strip().startswith("Object"):
obj_name = base_path(line.strip().replace("Object ", "").split("/")[-1])
sources[obj_name] = current_overlay
with open(dest, mode="w") as f:
for ovly in overlays:
f.write(f"OVERLAY {ovly}:{overlays[ovly]}\n")
f.write("\n")
for s in sources:
f.write(f"SOURCE {s}:{sources[s]}\n")