aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
blob: 62fd3900ff554b6101d7d37fa2988a7295945698 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use yaxpeax_arch::{AddressBase, Arch, Decoder, Instruction, LengthedInstruction};

use clap::*;
use num_traits::identities::Zero;

use std::fmt;

fn main() {
    let _ = include_str!("../Cargo.toml");
    let app = app_from_crate!()
        .arg(Arg::with_name("arch")
             .short("a")
             .long("--architecture")
             .takes_value(true)
             .possible_values(&["x86_64", "x86:32", "armv7", "armv8", "mips", "msp430", "pic17", "pic18", "m16c"])
             .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")
             .required(true)
             .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: &str = matches.value_of("data").unwrap_or("");
    let verbose = matches.occurrences_of("verbose") > 0;

    match arch_str {
        "x86_64" => decode_input::<yaxpeax_x86::long_mode::Arch>(buf, verbose),
        "x86:32" => decode_input::<yaxpeax_x86::protected_mode::Arch>(buf, verbose),
        "armv7" => decode_input::<yaxpeax_arm::armv7::ARMv7>(buf, verbose),
        "armv8" => decode_input::<yaxpeax_arm::armv8::a64::ARMv8>(buf, verbose),
        "mips" => decode_input::<yaxpeax_mips::MIPS>(buf, verbose),
        "msp430" => decode_input::<yaxpeax_msp430::MSP430>(buf, verbose),
        "pic17" => decode_input::<yaxpeax_pic17::PIC17>(buf, verbose),
        "pic18" => decode_input::<yaxpeax_pic18::PIC18>(buf, verbose),
        "m16c" => decode_input::<yaxpeax_m16c::M16C>(buf, verbose),
//        "pic24" => decode_input::<yaxpeax_pic24::PIC24>(buf),
        other => {
            println!("unsupported architecture: {}", other);
        }
    }
}

fn decode_input<A: Arch>(buf: &str, verbose: bool) where A::Instruction: fmt::Display {
    let buf = match hex::decode(buf) {
        Ok(buf) => buf,
        Err(e) => {
            eprintln!("Invalid input, {}. Expected a sequence of bytes as hex", e);
            return;
        }
    };
    let decoder = A::Decoder::default();
    let start = A::Address::zero();
    let mut addr = start;
    loop {
        match decoder.decode(buf[addr.to_linear()..].iter().cloned()) {
            Ok(inst) => {
                println!("{:#010x}: {:14}: {}", addr.to_linear(), hex::encode(&buf[addr.to_linear()..][..inst.len().to_linear()]), inst);
                if verbose {
                    println!("  {:?}", inst);
                    if !inst.well_defined() {
                        println!("  not well-defined");
                    }
                }
                addr += inst.len();
            },
            Err(e) => { println!("{:#010x}: {}", addr.to_linear(), e); break; },
        }
        if addr.to_linear() >= buf.len() {
            break;
        }
    }
}