From fc28d890975b973d88eee2efd7b4eaa3a821dc0a Mon Sep 17 00:00:00 2001 From: Michel Heily Date: Tue, 25 Jun 2019 04:59:18 +0300 Subject: [PATCH] Implement a few debugger commands --- Cargo.lock | 65 +++++++++++++++++++++++++++ Cargo.toml | 3 +- src/debugger.rs | 115 +++++++++++++++++++++++++++++++++++++++++------- src/main.rs | 9 ++-- 4 files changed, 171 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 969b355..5fbe419 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/Cargo.toml b/Cargo.toml index 1595935..85ff2b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,4 +11,5 @@ num-traits = "^0.1" bit = "^0.1" clap = {version = "2.33", features = ["color", "yaml"]} rustyline = "5.0.0" -nom = "5.0.0" \ No newline at end of file +nom = "5.0.0" +colored = "1.8" \ No newline at end of file diff --git a/src/debugger.rs b/src/debugger.rs index 969288a..07348ea 100644 --- a/src/debugger.rs +++ b/src/debugger.rs @@ -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, } + #[derive(Debug, PartialEq)] pub enum DebuggerError { - ParsingError, + ParsingError(String), + InvalidCommand(String) } impl From> 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 = Result; 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::from_str_radix(input, 16) } -impl FromStr for DebuggerCommand { - type Err = DebuggerError; +fn from_dec(input: &str) -> Result { + u32::from_str_radix(input, 10) +} - fn from_str(text: &str) -> Result { - +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 { + // 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"); diff --git a/src/main.rs b/src/main.rs index c812a3e..0a3a0ba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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()?;