~nabijaczleweli/yaxpeax-dis

3f1a3d7a1faea72605968a287082d157e5e85d44 — наб 3 months ago 06aa925 yaxpeax-superh-support
add superh
4 files changed, 83 insertions(+), 7 deletions(-)

M Cargo.lock
M Cargo.toml
M README.md
M src/main.rs
M Cargo.lock => Cargo.lock +10 -0
@@ 341,6 341,7 @@ dependencies = [
 "yaxpeax-msp430",
 "yaxpeax-pic17",
 "yaxpeax-pic18",
 "yaxpeax-superh",
 "yaxpeax-x86",
]



@@ 407,6 408,15 @@ dependencies = [
]

[[package]]
name = "yaxpeax-superh"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02789f779dd874674062a7407a1faadcb4dbbb70b313b465a2bdbb562bb4d1f7"
dependencies = [
 "yaxpeax-arch",
]

[[package]]
name = "yaxpeax-x86"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"

M Cargo.toml => Cargo.toml +1 -0
@@ 30,3 30,4 @@ yaxpeax-pic17 = { version = "0.0.3" }
yaxpeax-pic18 = { version = "0.0.3" }
yaxpeax-x86 = { version = "0.1.2" }
yaxpeax-ia64 = { version = "0.1.1" }
yaxpeax-superh = { version = "0.1.0" }

M README.md => README.md +1 -1
@@ 24,4 24,4 @@ or `yaxdis -a ia64 e38000000061e200000042c0e1803080`, producing:
`yaxdis` also takes a `-v` flag to emit more verbose information (really, a `Debug` display of decoded instructions).

## supported architectures / ! user beware !
`yaxdis` should support all architectures listed in the [yaxpeax-arch readme](https://git.iximeow.net/yaxpeax-arch/). that is currently `x86_64`, `armv7`, `armv8`, `mips`, `msp430`, `pic17`, `pic18`, `m16c`, `avr`, and `ia64`. specific levels of support and stability vary, beware.
`yaxdis` should support all architectures listed in the [yaxpeax-arch readme](https://git.iximeow.net/yaxpeax-arch/). that is currently `x86_64`, `armv7`, `armv8`, `mips`, `msp430`, `pic17`, `pic18`, `m16c`, `avr`, `ia64`, and `sh`/`sh2`/`j2`/`sh3`/`sh4`. specific levels of support and stability vary, beware.

M src/main.rs => src/main.rs +71 -6
@@ 6,6 6,7 @@ use num_traits::identities::Zero;
use std::fmt;
use std::fs::File;
use std::io::Read;
use std::collections::BTreeSet;

fn main() {
    let _ = include_str!("../Cargo.toml");


@@ 15,10 16,21 @@ fn main() {
                .short("a")
                .long("--architecture")
                .takes_value(true)
                .possible_values(&[
                    "x86_64", "x86:32", "ia64", "armv7", "armv8", "avr", "mips", "msp430", "pic17",
                    "pic18", "m16c",
                ])
                .validator(|a| {
                    if ["x86_64", "x86:32", "ia64", "armv7", "armv8", "avr", "mips", "msp430",
                        "pic17", "pic18", "m16c"].contains(&&a[..]) ||
                       (["sh", "sh2", "sh3", "sh4", "j2"].contains(
                             &&a[0..a.find(|c| c == '+' || c == '-').unwrap_or(a.len())]) &&
                        a.split(|c| c == '+' || c == '-').skip(1).all(
                            |f| ["be", "mmu", "fpu", "f64", "j2"].contains(&f))) {
                        Ok(())
                    } else {
                        Err("possible values: x86_64, x86:32, ia64, armv7, armv8, avr, mips, \
                                              msp430, pic17, pic18, m16c, \
                                              {sh{,2,3,4},j2}[[+-]{be,mmu,fpu,f64,j2}]*"
                            .to_string())
                    }
                })
                .help("architecture to disassemble input as."),
        )
        .arg(


@@ 85,16 97,69 @@ fn main() {
        "m16c" => decode_input::<yaxpeax_m16c::M16C>(&buf, verbose),
        //        "pic24" => decode_input::<yaxpeax_pic24::PIC24>(buf),
        other => {
            println!("unsupported architecture: {}", other);
            let seg_idx = arch_str.find(|c| c == '+' || c == '-').unwrap_or(arch_str.len());
            let wps = |base| with_parsed_superh(base, &arch_str[seg_idx..],
                |decoder| decode_input_with_decoder::<yaxpeax_superh::SuperH>(decoder, &buf, verbose));
            match &arch_str[0..seg_idx] {
                "sh" => wps(yaxpeax_superh::SuperHDecoder::SH1),
                "sh2" => wps(yaxpeax_superh::SuperHDecoder::SH2),
                "sh3" => wps(yaxpeax_superh::SuperHDecoder::SH3),
                "sh4" => wps(yaxpeax_superh::SuperHDecoder::SH4),
                "j2" => wps(yaxpeax_superh::SuperHDecoder::J2),
                _ => println!("unsupported architecture: {}", other),
            }
        }
    }
}

fn with_parsed_superh<F: FnOnce(yaxpeax_superh::SuperHDecoder)>(
    mut based_on: yaxpeax_superh::SuperHDecoder, mut from: &str, func: F
) {
    let mut features = based_on.features.iter().copied().collect::<BTreeSet<_>>();

    while !from.is_empty() {
        // This would be Not Trash if split_inclusive were stable; alas
        let op = from.chars().next().unwrap();
        from = &from[1..];

        let next_feat_idx = from.find(|c| c == '+' || c == '-').unwrap_or(from.len());
        let feat = &from[0..next_feat_idx];
        from = &from[next_feat_idx..];

        match (op, feat) {
            ('+', "be") => based_on.little_endian = false,
            ('-', "be") => based_on.little_endian = true,
            ('+', "f64") => based_on.fpscr_sz = true,
            ('-', "f64") => based_on.fpscr_sz = false,

            ('+', "mmu") => { features.insert(yaxpeax_superh::SuperHFeature::MMU); },
            ('-', "mmu") => { features.remove(&yaxpeax_superh::SuperHFeature::MMU); },
            ('+', "fpu") => { features.insert(yaxpeax_superh::SuperHFeature::FPU); },
            ('-', "fpu") => { features.remove(&yaxpeax_superh::SuperHFeature::FPU); },
            ('+', "j2") => { features.insert(yaxpeax_superh::SuperHFeature::J2); },
            ('-', "j2") => { features.remove(&yaxpeax_superh::SuperHFeature::J2); },

            pair => panic!("Who is {:?} and why was it not caught at parse time?", pair),
        }
    }

    func(yaxpeax_superh::SuperHDecoder {
        features: &features.into_iter().collect::<Vec<_>>()[..],
        ..based_on
    })
}

fn decode_input<A: Arch>(buf: &[u8], verbose: bool)
where
    A::Instruction: fmt::Display,
{
    let decoder = A::Decoder::default();
    decode_input_with_decoder::<A>(A::Decoder::default(), buf, verbose);
}

fn decode_input_with_decoder<A: Arch>(decoder: A::Decoder, buf: &[u8], verbose: bool)
where
    A::Instruction: fmt::Display,
{
    let start = A::Address::zero();
    let mut addr = start;
    loop {