Implement a few debugger commands

This commit is contained in:
Michel Heily 2019-06-25 04:59:18 +03:00
parent 107e34aca1
commit fc28d89097
4 changed files with 171 additions and 21 deletions

65
Cargo.lock generated
View file

@ -8,6 +8,11 @@ dependencies = [
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "approx"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "argon2rs"
version = "0.2.5"
@ -95,6 +100,16 @@ name = "cfg-if"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cgmath"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clap"
version = "2.33.0"
@ -118,6 +133,15 @@ dependencies = [
"bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "colored"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winconsole 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "constant_time_eq"
version = "0.1.3"
@ -178,6 +202,11 @@ name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lexical-core"
version = "0.4.1"
@ -277,6 +306,18 @@ dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand_core"
version = "0.3.1"
@ -335,6 +376,11 @@ dependencies = [
"redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rgb"
version = "0.8.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustboyadvance"
version = "0.1.0"
@ -342,6 +388,7 @@ dependencies = [
"bit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"enum-primitive-derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"nom 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
@ -544,6 +591,17 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winconsole"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cgmath 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rgb 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "yaml-rust"
version = "0.3.5"
@ -551,6 +609,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08abcc3b4e9339e33a3d0a5ed15d84a687350c05689d825e0f6655eef9e76a94"
"checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392"
"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71"
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
@ -563,8 +622,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
"checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d"
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
"checksum cgmath 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64a4b57c8f4e3a2e9ac07e0f6abc9c24b6fc9e1b54c3478cfb598f3d0023e51c"
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cdb90b60f2927f8d76139c72dbde7e10c3a2bc47c8594c9c7a66529f2687c03"
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
"checksum dirs 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1c4ef5a8b902d393339e2a2c7fe573af92ce7e0ee5a3ff827b4c9ad7e07e4fa1"
"checksum dirs-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "937756392ec77d1f2dd9dc3ac9d69867d109a2121479d72c364e42f4cab21e2d"
@ -572,6 +633,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
"checksum lexical-core 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d224b31f370c8dfc0dea1932d9e6bd451e65aef6f5f2318846664c04b42a796"
"checksum libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "6281b86796ba5e4366000be6e9e18bf35580adf9e63fbe2294aadb587613a319"
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
@ -585,6 +647,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
@ -592,6 +655,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252"
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe5204c3a17e97dde73f285d49be585df59ed84b50a872baf416e73b62c3828"
"checksum rgb 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)" = "4f089652ca87f5a82a62935ec6172a534066c7b97be003cc8f702ee9a7a59c92"
"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum rustyline 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67e12e40e0240de07f0dab4f4dd01bdb15d74dc977026d4ba91666c41c679ade"
@ -620,4 +684,5 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum winconsole 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ef84b96d10db72dd980056666d7f1e7663ce93d82fa33b63e71c966f4cf5032"
"checksum yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e66366e18dc58b46801afbf2ca7661a9f59cc8c5962c29892b6039b4f86fa992"

View file

@ -12,3 +12,4 @@ bit = "^0.1"
clap = {version = "2.33", features = ["color", "yaml"]}
rustyline = "5.0.0"
nom = "5.0.0"
colored = "1.8"

View file

@ -3,9 +3,13 @@ use std::str::FromStr;
use rustyline::error::ReadlineError;
use rustyline::Editor;
use colored::*;
use nom;
use nom::bytes;
use nom::IResult;
use nom::bytes::complete::{tag, take_till1, take_till, take_while_m_n, take_while1};
use nom::combinator::map_res;
use super::arm7tdmi::arm;
use super::arm7tdmi::cpu;
@ -15,16 +19,19 @@ use super::sysbus::SysBus;
pub struct Debugger {
cpu: cpu::Core,
sysbus: SysBus,
breakpoints: Vec<u32>,
}
#[derive(Debug, PartialEq)]
pub enum DebuggerError {
ParsingError,
ParsingError(String),
InvalidCommand(String)
}
impl From<nom::Err<(&str, nom::error::ErrorKind)>> for DebuggerError {
fn from(e: nom::Err<(&str, nom::error::ErrorKind)>) -> DebuggerError {
DebuggerError::ParsingError
DebuggerError::ParsingError("parsing of command failed".to_string())
}
}
@ -34,23 +41,63 @@ type DebuggerResult<T> = Result<T, DebuggerError>;
enum DebuggerCommand {
SingleStep,
Continue,
Disass { addr: u32, num_opcodes: u32 },
Stop,
Disass { addr: u32, num_opcodes: usize },
AddBreakpoint(u32),
ListBreakpoints,
Quit,
Nop,
}
use DebuggerCommand::*;
fn parse_debugger_command(input: &str) -> IResult<&str, DebuggerCommand> {
let (input, command_name) = bytes::complete::take_while1(|c: char| c.is_alphanumeric())(input)?;
println!("parsed command: {}", command_name);
unimplemented!()
fn from_hex(input: &str) -> Result<u32, std::num::ParseIntError> {
u32::from_str_radix(input, 16)
}
impl FromStr for DebuggerCommand {
type Err = DebuggerError;
fn from_dec(input: &str) -> Result<u32, std::num::ParseIntError> {
u32::from_str_radix(input, 10)
}
fn from_str(text: &str) -> Result<Self, Self::Err> {
fn whitespace(input: &str) -> IResult<&str, ()> {
let (input, _) = take_while1(char::is_whitespace)(input)?;
Ok((input, ()))
}
fn parse_hex_num(input: &str) -> IResult<&str, u32> {
let (input, _) = tag("0x")(input)?;
map_res(take_while_m_n(1, 8, |c: char| c.is_digit(16)), from_hex)(input)
}
fn parse_num(input: &str) -> IResult<&str, u32> {
map_res(take_while1(|c: char| c.is_digit(10)), from_dec)(input)
}
fn parse_word(input: &str) -> IResult<&str, &str> {
take_till(char::is_whitespace)(input)
}
fn parse_debugger_command(input: &str) -> DebuggerResult<DebuggerCommand> {
// TODO this code is shit!
let (input, command_name) = parse_word(input)?;
match command_name {
"s" | "step" => Ok(SingleStep),
"c" | "continue" => Ok(Continue),
"d" | "disass" => {
let (input, _) = whitespace(input).map_err(|_| DebuggerError::ParsingError("argument missing".to_string()))?;
let (input, addr) = parse_hex_num(input)?;
let (input, _) = whitespace(input).map_err(|_| DebuggerError::ParsingError("argument missing".to_string()))?;
let (_, num_opcodes) = parse_num(input)?;
let num_opcodes = num_opcodes as usize;
Ok(Disass{ addr, num_opcodes })
}
"b" | "break" => {
let (input, _) = whitespace(input).map_err(|_| DebuggerError::ParsingError("argument missing".to_string()))?;
let (_, addr) = parse_hex_num(input)?;
Ok(AddBreakpoint(addr))
}
"bl" => Ok(ListBreakpoints),
"q" | "quit" => Ok(Quit),
"" => Ok(Nop),
_ => Err(DebuggerError::InvalidCommand(command_name.to_string()))
}
}
@ -59,16 +106,52 @@ impl Debugger {
Debugger {
cpu: cpu,
sysbus: sysbus,
breakpoints: Vec::new(),
}
}
pub fn repl(&self) -> DebuggerResult<()> {
pub fn repl(&mut self) -> DebuggerResult<()> {
let mut rl = Editor::<()>::new();
loop {
let readline = rl.readline("(rustboyadvance-dbg) >> ");
let readline = rl.readline(&format!("({}) >> ", "rustboyadvance-dbg".cyan()));
match readline {
Ok(line) => {
let command = parse_debugger_command(&line)?;
let command = parse_debugger_command(&line);
match command {
Ok(Nop) => (),
Ok(SingleStep) => {
self.cpu.step(&mut self.sysbus).unwrap()
},
Ok(Quit) => {
print!("Quitting!");
break
},
Ok(AddBreakpoint(addr)) => {
if !self.breakpoints.contains(&addr) {
let new_index = self.breakpoints.len();
self.breakpoints.push(addr);
println!("added breakpoint [{}] 0x{:08x}", new_index, addr);
} else {
println!("breakpoint already exists!")
}
}
Ok(ListBreakpoints) => {
println!("breakpoint list:");
for (i, b) in self.breakpoints.iter().enumerate() {
println!("[{}] 0x{:08x}", i, b)
}
}
Err(DebuggerError::InvalidCommand(command)) => {
println!("invalid command: {}", command)
}
Err(DebuggerError::ParsingError(msg)) => {
println!("Parsing error: {:?}", msg)
}
Err(e) => {
return Err(e);
}
Ok(command) => println!("got command: {:?}", command),
}
}
Err(ReadlineError::Interrupted) => {
println!("CTRL-C");

View file

@ -19,9 +19,10 @@ use clap::{App, ArgMatches};
extern crate rustyline;
#[macro_use]
extern crate nom;
extern crate colored; // not needed in Rust 2018
pub mod sysbus;
use sysbus::SysBus;
@ -105,9 +106,9 @@ fn run_debug(matches: &ArgMatches) -> GBAResult<()> {
println!("Loading BIOS: {}", gba_bios_path);
let bios_bin = read_bin_file(gba_bios_path)?;
let sysbus = SysBus::new(bios_bin);
let core = cpu::Core::new();
let debugger = Debugger::new(core, sysbus);
let mut sysbus = SysBus::new(bios_bin);
let mut core = cpu::Core::new();
let mut debugger = Debugger::new(core, sysbus);
println!("starting debugger...");
debugger.repl()?;