diff --git a/rustboyadvance-core/Cargo.toml b/rustboyadvance-core/Cargo.toml index 601784f..f21b298 100644 --- a/rustboyadvance-core/Cargo.toml +++ b/rustboyadvance-core/Cargo.toml @@ -32,6 +32,7 @@ gdbstub = { version = "0.1.2", optional = true, features = ["std"] } ringbuf = "0.2.1" goblin = { version = "0.2", optional = true } +fuzzy-matcher = { version = "0.3.4", optional = true } [target.'cfg(target_arch="wasm32")'.dependencies] instant = { version = "0.1.2", features = [ "wasm-bindgen" ] } @@ -44,7 +45,7 @@ criterion = "0.3" [features] default = ["arm7tdmi_dispatch_table"] -debugger = ["nom", "rustyline"] +debugger = ["nom", "rustyline", "fuzzy-matcher"] gdb = ["gdbstub"] elf_support = ["goblin"] # Uses lookup tables when executing instructions instead of `match` statements. diff --git a/rustboyadvance-core/src/debugger/command.rs b/rustboyadvance-core/src/debugger/command.rs index cb6e9b4..9d6d307 100644 --- a/rustboyadvance-core/src/debugger/command.rs +++ b/rustboyadvance-core/src/debugger/command.rs @@ -15,6 +15,9 @@ use super::{parser::Value, Debugger, DebuggerError, DebuggerResult}; use ansi_term::Colour; +use fuzzy_matcher::skim::SkimMatcherV2; +use fuzzy_matcher::FuzzyMatcher; + use hexdump; #[derive(Debug, PartialEq, Clone, Copy)] @@ -61,6 +64,7 @@ pub enum Command { TraceToggle(TraceFlags), SaveState(String), LoadState(String), + ListSymbols(Option), } impl Debugger { @@ -215,6 +219,28 @@ impl Debugger { .restore_state(&save) .expect("failed to deserialize"); } + ListSymbols(Some(pattern)) => { + if let Some(symbols) = self.gba.sysbus.cartridge.get_symbols() { + let matcher = SkimMatcherV2::default(); + for (k, v) in symbols + .iter() + .filter(|(k, _v)| matcher.fuzzy_match(k, &pattern).is_some()) + { + println!("{}=0x{:08x}", k, v); + } + } else { + println!("symbols not loaded!"); + } + } + ListSymbols(None) => { + if let Some(symbols) = self.gba.sysbus.cartridge.get_symbols() { + for (k, v) in symbols.iter() { + println!("{}=0x{:08x}", k, v); + } + } else { + println!("symbols not loaded!"); + } + } _ => println!("Not Implemented",), } } @@ -460,6 +486,22 @@ impl Debugger { } } } + "list-symbols" | "list-syms" | "symbols" | "syms" => match args.len() { + 0 => Ok(Command::ListSymbols(None)), + 1 => { + if let Value::Identifier(pattern) = &args[0] { + Ok(Command::ListSymbols(Some(pattern.to_string()))) + } else { + Err(DebuggerError::InvalidArgument(String::from( + "expected a pattern", + ))) + } + } + _ => Err(DebuggerError::InvalidCommandFormat(format!( + "usage: {} [pattern]", + command + ))), + }, _ => Err(DebuggerError::InvalidCommand(command)), } } diff --git a/rustboyadvance-core/src/debugger/mod.rs b/rustboyadvance-core/src/debugger/mod.rs index 32d1e6d..0e1fe84 100644 --- a/rustboyadvance-core/src/debugger/mod.rs +++ b/rustboyadvance-core/src/debugger/mod.rs @@ -66,6 +66,7 @@ impl Debugger { } fn decode_reg(&self, s: &str) -> DebuggerResult { + // TODO also allow r11..r15 let reg_names = vec![ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "fp", "ip", "sp", "lr", "pc", @@ -103,9 +104,20 @@ impl Debugger { fn val_address(&self, arg: &Value) -> DebuggerResult { match arg { Value::Num(n) => Ok(*n), - Value::Identifier(reg) => { - let reg = self.decode_reg(®)?; - Ok(self.gba.cpu.get_reg(reg)) + Value::Identifier(ident) => { + let symbol = if let Some(symbols) = self.gba.sysbus.cartridge.get_symbols() { + symbols.get(ident) + } else { + None + }; + + if let Some(address) = symbol { + Ok(*address) + } else { + // otherwise, decode as register (TODO special token to separate symbol and register) + let reg = self.decode_reg(&ident)?; + Ok(self.gba.cpu.get_reg(reg)) + } } v => Err(DebuggerError::InvalidArgument(format!( "addr: expected a number or register, got {:?}",