diff options
-rw-r--r-- | Cargo.lock | 134 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/main.rs | 222 |
3 files changed, 232 insertions, 126 deletions
@@ -3,15 +3,6 @@ version = 3 [[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - -[[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -48,17 +39,32 @@ dependencies = [ [[package]] name = "clap" -version = "2.34.0" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "d01c9347757e131122b19cd19a05c85805b68c2352a97b623efdc3c295290299" dependencies = [ - "ansi_term", "atty", "bitflags", + "clap_derive", + "indexmap", + "lazy_static", + "os_str_bytes", "strsim", + "termcolor", "textwrap", - "unicode-width", - "vec_map", +] + +[[package]] +name = "clap_derive" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "448c8b00367288ad41804ac7a9e0fe58f2324a36901cb5d6b6db58be86d1db8f" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.84", ] [[package]] @@ -74,6 +80,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" [[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" + +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + +[[package]] name = "hermit-abi" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -89,6 +107,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] +name = "indexmap" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] name = "itertools" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -98,12 +126,24 @@ dependencies = [ ] [[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] name = "libc" version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" [[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + +[[package]] name = "num-traits" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -124,6 +164,39 @@ dependencies = [ ] [[package]] +name = "os_str_bytes" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" +dependencies = [ + "memchr", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2 1.0.36", + "quote 1.0.14", + "syn 1.0.84", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2 1.0.36", + "quote 1.0.14", + "version_check", +] + +[[package]] name = "proc-macro2" version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -184,9 +257,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" @@ -217,19 +290,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] -name = "textwrap" -version = "0.11.0" +name = "termcolor" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" dependencies = [ - "unicode-width", + "winapi-util", ] [[package]] -name = "unicode-width" -version = "0.1.9" +name = "textwrap" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" [[package]] name = "unicode-xid" @@ -244,10 +317,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] -name = "vec_map" -version = "0.8.2" +name = "version_check" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "winapi" @@ -266,6 +339,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -17,7 +17,7 @@ path = "src/main.rs" yaxpeax-arch-02 = { package = "yaxpeax-arch", path = "/toy/yaxpeax/yaxpeax-arch/" } [dependencies] -clap = "2.33" +clap = { version = "3", features = ["derive"] } hex = "0.4.0" num-traits = "0.2.10" itertools = "0.10.1" diff --git a/src/main.rs b/src/main.rs index ab0a0a4..42aa338 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,56 +1,103 @@ -use std::fs::File; -use std::io::{Read, Write}; -use std::{fmt, io}; +use std::io::Write; +use std::{fmt, io, fs}; +use std::str::FromStr; +use std::path::PathBuf; + +use clap::Parser; + +#[derive(Debug)] +enum Architecture { + X86_64, + X86_32, + X86_16, + IA64, + AVR, + ARMv7, + ARMv7Thumb, + ARMv8, + MIPS, + MSP430, + PIC17, + PIC18, + M16C, + N6502, + LC87, + // PIC24, + SuperH(yaxpeax_superh::SuperHDecoder), +} + +impl fmt::Display for Architecture { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(self, f) + } +} + +impl FromStr for Architecture { + type Err = &'static str; + fn from_str(arch_str: &str) -> Result<Self, Self::Err> { + use Architecture::*; + let err_str = "possible values: x86_64, x86_32, x86_16, x86:64, x86:32, x86:16, \ + ia64, armv7, armv7-t, armv8, avr, mips, msp430, pic17, pic18, \ + m16c, 6502, lc87, {sh{,2,3,4},j2}[[+-]{be,mmu,fpu,f64,j2}]*"; + let arch = match arch_str { + "x86_64" | "x86:64" => X86_64, + "x86_32" | "x86:32" => X86_32, + "x86_16" | "x86:16" => X86_16, + "ia64" => IA64, + "avr" => AVR, + "armv7" => ARMv7, + "armv7-t" => ARMv7Thumb, + "armv8" => ARMv8, + "mips" => MIPS, + "msp430" => MSP430, + "pic17" => PIC17, + "pic18" => PIC18, + "m16c" => M16C, + "6502" => N6502, + "lc87" => LC87, + // "pic24" => PIC24, + _ => { + let seg_idx = arch_str.find(&['+', '-'][..]).unwrap_or(arch_str.len()); + let (base, features) = arch_str.split_at(seg_idx); + let decoder = match base { + "sh" => yaxpeax_superh::SuperHDecoder::SH1, + "sh2" => yaxpeax_superh::SuperHDecoder::SH2, + "sh3" => yaxpeax_superh::SuperHDecoder::SH3, + "sh4" => yaxpeax_superh::SuperHDecoder::SH4, + "j2" => yaxpeax_superh::SuperHDecoder::J2, + _ => return Err(err_str), + }; + SuperH(parse_superh(decoder, features)) + } + }; + Ok(arch) + } +} + +#[derive(Parser)] +#[clap(about, version, author)] +struct Args { + /// architecture to disassemble input as. + #[clap(short, long, default_value = "x86_64")] + architecture: Architecture, + + /// file of bytes to decode + #[clap(short, long, parse(from_os_str), conflicts_with = "data")] + file: Option<PathBuf>, + + /// increased detail when decoding instructions + #[clap(short, long, parse(from_occurrences))] + verbose: u8, + + /// hex bytes to decode by the selected architecture. for example, try -a x86_64 33c0c3 + #[clap(required_unless_present = "file")] + data: Option<String>, +} fn main() { - use clap::*; - let _ = include_str!("../Cargo.toml"); - let app = app_from_crate!() - .arg( - Arg::with_name("arch") - .short("a") - .long("--architecture") - .takes_value(true) - .validator(|a| { - if ["x86_64", "x86_32", "x86_16", - "x86:64", "x86:32", "x86:16", - "ia64", "armv7", "armv7-t","armv8", "avr", "mips", "msp430", - "pic17", "pic18", "m16c", "6502", "lc87"].contains(&&a[..]) || - (["sh", "sh2", "sh3", "sh4", "j2"].contains( - &&a[0..a.find(&['+', '-'][..]).unwrap_or(a.len())]) && - a.split(&['+', '-'][..]).skip(1).all( - |f| ["be", "mmu", "fpu", "f64", "j2"].contains(&f))) { - Ok(()) - } else { - Err("possible values: x86_64, x86_32, x86_16, x86:64, x86:32, x86:16, \ - ia64, armv7, armv7-t, armv8, avr, mips, msp430, pic17, pic18, \ - m16c, 6502, lc87, {sh{,2,3,4},j2}[[+-]{be,mmu,fpu,f64,j2}]*" - .to_string()) - } - }) - .help("architecture to disassemble input as."), - ) - .arg( - Arg::with_name("file") - .short("f") - .long("file") - .takes_value(true) - .help("file of bytes to decode"), - ) - .arg( - Arg::with_name("verbose") - .short("v") - .long("--verbose") - .help("increased detail when decoding instructions"), - ) - .arg(Arg::with_name("data").help( - "hex bytes to decode by the selected architecture. for example, try -a x86_64 33c0c3", - )); - - let matches = app.get_matches(); - - let arch_str = matches.value_of("arch").unwrap_or("x86_64"); - let buf: Vec<u8> = match matches.value_of("data") { + let args = Args::parse(); + + let buf: Vec<u8> = match args.data { Some(data) => match hex::decode(data) { Ok(buf) => buf, Err(e) => { @@ -59,62 +106,39 @@ fn main() { } }, None => { - let mut v = Vec::new(); - match matches.value_of("file") { - Some(name) => match File::open(name) { - Ok(mut f) => { - f.read_to_end(&mut v).expect("can read the file"); - v - } - Err(e) => { - eprintln!("error opening {}: {}", name, e); - return; - } - }, - None => { - eprintln!("data must be provided by either an argument consisting of hex bytes, or by the --file argument."); + let name = args.file.unwrap(); + match fs::read(&name) { + Ok(v) => v, + Err(e) => { + eprintln!("error reading {}: {}", name.display(), e); return; } } } }; - let verbose = matches.occurrences_of("verbose") > 0; + let verbose = args.verbose > 0; let printer = Printer { stdout: io::stdout(), verbose }; - match arch_str { - "x86_64" | - "x86:64" => arch_02::decode_input_and_annotate::<yaxpeax_x86::long_mode::Arch>(&buf, &printer), - "x86_32" | - "x86:32" => arch_02::decode_input_and_annotate::<yaxpeax_x86::protected_mode::Arch>(&buf, &printer), - "x86_16" | - "x86:16" => arch_02::decode_input_and_annotate::<yaxpeax_x86::real_mode::Arch>(&buf, &printer), - "ia64" => arch_02::decode_input::<yaxpeax_ia64::IA64>(&buf, &printer), - "avr" => arch_02::decode_input::<yaxpeax_avr::AVR>(&buf, &printer), - "armv7" => arch_02::decode_input::<yaxpeax_arm::armv7::ARMv7>(&buf, &printer), - "armv7-t" => arch_02::decode_armv7_thumb(&buf, &printer), - "armv8" => arch_02::decode_input::<yaxpeax_arm::armv8::a64::ARMv8>(&buf, &printer), - "mips" => arch_02::decode_input::<yaxpeax_mips::MIPS>(&buf, &printer), - "msp430" => arch_02::decode_input_and_annotate::<yaxpeax_msp430::MSP430>(&buf, &printer), - "pic17" => arch_02::decode_input::<yaxpeax_pic17::PIC17>(&buf, &printer), - "pic18" => arch_02::decode_input::<yaxpeax_pic18::PIC18>(&buf, &printer), - "m16c" => arch_02::decode_input::<yaxpeax_m16c::M16C>(&buf, &printer), - "6502" => arch_02::decode_input::<yaxpeax_6502::N6502>(&buf, &printer), - "lc87" => arch_02::decode_input::<yaxpeax_lc87::LC87>(&buf, &printer), - // "pic24" => decode_input::<yaxpeax_pic24::PIC24>(buf), - other => { - let seg_idx = arch_str.find(&['+', '-'][..]).unwrap_or(arch_str.len()); - let decode = |base| arch_02::decode_input_with_decoder::<yaxpeax_superh::SuperH>( - parse_superh(base, &arch_str[seg_idx..]), &buf, &printer); - match &arch_str[0..seg_idx] { - "sh" => decode(yaxpeax_superh::SuperHDecoder::SH1), - "sh2" => decode(yaxpeax_superh::SuperHDecoder::SH2), - "sh3" => decode(yaxpeax_superh::SuperHDecoder::SH3), - "sh4" => decode(yaxpeax_superh::SuperHDecoder::SH4), - "j2" => decode(yaxpeax_superh::SuperHDecoder::J2), - _ => println!("unsupported architecture: {}", other), - } - } + use Architecture::*; + match args.architecture { + X86_64 => arch_02::decode_input_and_annotate::<yaxpeax_x86::long_mode::Arch>(&buf, &printer), + X86_32 => arch_02::decode_input_and_annotate::<yaxpeax_x86::protected_mode::Arch>(&buf, &printer), + X86_16 => arch_02::decode_input_and_annotate::<yaxpeax_x86::real_mode::Arch>(&buf, &printer), + IA64 => arch_02::decode_input::<yaxpeax_ia64::IA64>(&buf, &printer), + AVR => arch_02::decode_input::<yaxpeax_avr::AVR>(&buf, &printer), + ARMv7 => arch_02::decode_input::<yaxpeax_arm::armv7::ARMv7>(&buf, &printer), + ARMv7Thumb => arch_02::decode_armv7_thumb(&buf, &printer), + ARMv8 => arch_02::decode_input::<yaxpeax_arm::armv8::a64::ARMv8>(&buf, &printer), + MIPS => arch_02::decode_input::<yaxpeax_mips::MIPS>(&buf, &printer), + MSP430 => arch_02::decode_input_and_annotate::<yaxpeax_msp430::MSP430>(&buf, &printer), + PIC17 => arch_02::decode_input::<yaxpeax_pic17::PIC17>(&buf, &printer), + PIC18 => arch_02::decode_input::<yaxpeax_pic18::PIC18>(&buf, &printer), + M16C => arch_02::decode_input::<yaxpeax_m16c::M16C>(&buf, &printer), + N6502 => arch_02::decode_input::<yaxpeax_6502::N6502>(&buf, &printer), + LC87 => arch_02::decode_input::<yaxpeax_lc87::LC87>(&buf, &printer), + // PIC24 => decode_input::<yaxpeax_pic24::PIC24>(buf), + SuperH(decoder) => arch_02::decode_input_with_decoder::<yaxpeax_superh::SuperH>(decoder, &buf, &printer), } } |