debugger: Add some symbol support

Former-commit-id: 44010b1599c373f2141f918dccb53135752ac283
This commit is contained in:
Michel Heily 2020-04-29 23:52:43 +03:00
parent 31161eb5e5
commit 2caf8c26ad
3 changed files with 59 additions and 4 deletions

View file

@ -32,6 +32,7 @@ gdbstub = { version = "0.1.2", optional = true, features = ["std"] }
ringbuf = "0.2.1" ringbuf = "0.2.1"
goblin = { version = "0.2", optional = true } goblin = { version = "0.2", optional = true }
fuzzy-matcher = { version = "0.3.4", optional = true }
[target.'cfg(target_arch="wasm32")'.dependencies] [target.'cfg(target_arch="wasm32")'.dependencies]
instant = { version = "0.1.2", features = [ "wasm-bindgen" ] } instant = { version = "0.1.2", features = [ "wasm-bindgen" ] }
@ -44,7 +45,7 @@ criterion = "0.3"
[features] [features]
default = ["arm7tdmi_dispatch_table"] default = ["arm7tdmi_dispatch_table"]
debugger = ["nom", "rustyline"] debugger = ["nom", "rustyline", "fuzzy-matcher"]
gdb = ["gdbstub"] gdb = ["gdbstub"]
elf_support = ["goblin"] elf_support = ["goblin"]
# Uses lookup tables when executing instructions instead of `match` statements. # Uses lookup tables when executing instructions instead of `match` statements.

View file

@ -15,6 +15,9 @@ use super::{parser::Value, Debugger, DebuggerError, DebuggerResult};
use ansi_term::Colour; use ansi_term::Colour;
use fuzzy_matcher::skim::SkimMatcherV2;
use fuzzy_matcher::FuzzyMatcher;
use hexdump; use hexdump;
#[derive(Debug, PartialEq, Clone, Copy)] #[derive(Debug, PartialEq, Clone, Copy)]
@ -61,6 +64,7 @@ pub enum Command {
TraceToggle(TraceFlags), TraceToggle(TraceFlags),
SaveState(String), SaveState(String),
LoadState(String), LoadState(String),
ListSymbols(Option<String>),
} }
impl Debugger { impl Debugger {
@ -215,6 +219,28 @@ impl Debugger {
.restore_state(&save) .restore_state(&save)
.expect("failed to deserialize"); .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",), _ => 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)), _ => Err(DebuggerError::InvalidCommand(command)),
} }
} }

View file

@ -66,6 +66,7 @@ impl Debugger {
} }
fn decode_reg(&self, s: &str) -> DebuggerResult<usize> { fn decode_reg(&self, s: &str) -> DebuggerResult<usize> {
// TODO also allow r11..r15
let reg_names = vec![ let reg_names = vec![
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "fp", "ip", "sp", "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "fp", "ip", "sp",
"lr", "pc", "lr", "pc",
@ -103,10 +104,21 @@ impl Debugger {
fn val_address(&self, arg: &Value) -> DebuggerResult<Addr> { fn val_address(&self, arg: &Value) -> DebuggerResult<Addr> {
match arg { match arg {
Value::Num(n) => Ok(*n), Value::Num(n) => Ok(*n),
Value::Identifier(reg) => { Value::Identifier(ident) => {
let reg = self.decode_reg(&reg)?; 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)) Ok(self.gba.cpu.get_reg(reg))
} }
}
v => Err(DebuggerError::InvalidArgument(format!( v => Err(DebuggerError::InvalidArgument(format!(
"addr: expected a number or register, got {:?}", "addr: expected a number or register, got {:?}",
v v