diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 222 | 
1 files changed, 123 insertions, 99 deletions
| 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),      }  } | 
