From 754f28d76c6c0def07561337969699accb843423 Mon Sep 17 00:00:00 2001 From: iximeow Date: Wed, 21 Jul 2021 00:19:36 -0700 Subject: update decoders to yaxpeax_arch 0.2 versions, add lc87 and x86_16 --- src/main.rs | 175 +++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 119 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index f577a42..0c6a5fc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,5 @@ -use yaxpeax_arch::{AddressBase, Arch, Decoder, Instruction, LengthedInstruction}; - use clap::*; -use num_traits::identities::Zero; -use std::fmt; use std::fs::File; use std::io::Read; use std::collections::BTreeSet; @@ -17,17 +13,19 @@ fn main() { .long("--architecture") .takes_value(true) .validator(|a| { - if ["x86_64", "x86:32", "ia64", "armv7", "armv8", "avr", "mips", "msp430", - "pic17", "pic18", "m16c", "6502"].contains(&&a[..]) || + if ["x86_64", "x86_32", "x86_16", + "x86:64", "x86:32", "x86:16", + "ia64", "armv7", "armv8", "avr", "mips", "msp430", + "pic17", "pic18", "m16c", "6502", "lc87"].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, 6502, \ - {sh{,2,3,4},j2}[[+-]{be,mmu,fpu,f64,j2}]*" + Err("possible values: x86_64, x86_32, x86_16, x86:64, x86:32, x86:16, \ + ia64, armv7, armv8, avr, mips, msp430, pic17, pic18, \ + m16c, 6502, lc87, {sh{,2,3,4},j2}[[+-]{be,mmu,fpu,f64,j2}]*" .to_string()) } }) @@ -84,23 +82,28 @@ fn main() { let verbose = matches.occurrences_of("verbose") > 0; match arch_str { - "x86_64" => decode_input::(&buf, verbose), - "x86:32" => decode_input::(&buf, verbose), - "ia64" => decode_input::(&buf, verbose), - "avr" => decode_input::(&buf, verbose), - "armv7" => decode_input::(&buf, verbose), - "armv8" => decode_input::(&buf, verbose), - "mips" => decode_input::(&buf, verbose), - "msp430" => decode_input::(&buf, verbose), - "pic17" => decode_input::(&buf, verbose), - "pic18" => decode_input::(&buf, verbose), - "m16c" => decode_input::(&buf, verbose), - "6502" => decode_input::(&buf, verbose), + "x86_64" | + "x86:64" => crate::current_arch::decode_input::(&buf, verbose), + "x86_32" | + "x86:32" => crate::current_arch::decode_input::(&buf, verbose), + "x86_16" | + "x86:16" => crate::current_arch::decode_input::(&buf, verbose), + "ia64" => crate::current_arch::decode_input::(&buf, verbose), + "avr" => crate::current_arch::decode_input::(&buf, verbose), + "armv7" => crate::current_arch::decode_input::(&buf, verbose), + "armv8" => crate::current_arch::decode_input::(&buf, verbose), + "mips" => crate::current_arch::decode_input::(&buf, verbose), + "msp430" => crate::current_arch::decode_input::(&buf, verbose), + "pic17" => crate::current_arch::decode_input::(&buf, verbose), + "pic18" => crate::current_arch::decode_input::(&buf, verbose), + "m16c" => crate::current_arch::decode_input::(&buf, verbose), + "6502" => crate::legacy_arch::decode_input::(&buf, verbose), + "lc87" => crate::current_arch::decode_input::(&buf, verbose), // "pic24" => decode_input::(buf), 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::(decoder, &buf, verbose)); + |decoder| crate::legacy_arch::decode_input_with_decoder::(decoder, &buf, verbose)); match &arch_str[0..seg_idx] { "sh" => wps(yaxpeax_superh::SuperHDecoder::SH1), "sh2" => wps(yaxpeax_superh::SuperHDecoder::SH2), @@ -150,46 +153,106 @@ fn with_parsed_superh( }) } -fn decode_input(buf: &[u8], verbose: bool) -where - A::Instruction: fmt::Display, -{ - decode_input_with_decoder::(A::Decoder::default(), buf, verbose); -} +// yaxpeax-arch, implemented by all decoders here, is required at incompatible versions by +// different decoders. implement the actual decode-and-print behavior on both versions of +// yaxpeax-arch while older decoders are still being updated. +mod current_arch { + use yaxpeax_arch_02::{AddressBase, Arch, Decoder, Instruction, LengthedInstruction, Reader, U8Reader}; + use std::fmt; + use num_traits::identities::Zero; -fn decode_input_with_decoder(decoder: A::Decoder, buf: &[u8], verbose: bool) -where - A::Instruction: fmt::Display, -{ - 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()..] - [..A::Address::zero().wrapping_offset(inst.len()).to_linear()] - ), - inst - ); - if verbose { - println!(" {:?}", inst); - if !inst.well_defined() { - println!(" not well-defined"); + pub(crate) fn decode_input(buf: &[u8], verbose: bool) + where + A::Instruction: fmt::Display, for<'data> U8Reader<'data>: Reader, + { + decode_input_with_decoder::(A::Decoder::default(), buf, verbose); + } + + pub(crate) fn decode_input_with_decoder(decoder: A::Decoder, buf: &[u8], verbose: bool) + where + A::Instruction: fmt::Display, for<'data> U8Reader<'data>: Reader, + { + let start = A::Address::zero(); + let mut addr = start; + loop { + let mut reader = U8Reader::new(&buf[addr.to_linear()..]); + match decoder.decode(&mut reader) { + Ok(inst) => { + println!( + "{:#010x}: {:14}: {}", + addr.to_linear(), + hex::encode( + &buf[addr.to_linear()..] + [..A::Address::zero().wrapping_offset(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); + addr += A::Instruction::min_size(); } - addr += inst.len(); } - Err(e) => { - println!("{:#010x}: {}", addr.to_linear(), e); - addr += A::Instruction::min_size(); + if addr.to_linear() >= buf.len() { + break; } } - if addr.to_linear() >= buf.len() { - break; + } +} + +mod legacy_arch { + use yaxpeax_arch_01::{AddressBase, Arch, Decoder, Instruction, LengthedInstruction}; + use std::fmt; + use num_traits::identities::Zero; + + pub(crate) fn decode_input(buf: &[u8], verbose: bool) + where + A::Instruction: fmt::Display, + { + decode_input_with_decoder::(A::Decoder::default(), buf, verbose); + } + + pub(crate) fn decode_input_with_decoder(decoder: A::Decoder, buf: &[u8], verbose: bool) + where + A::Instruction: fmt::Display, + { + 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()..] + [..A::Address::zero().wrapping_offset(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); + addr += A::Instruction::min_size(); + } + } + if addr.to_linear() >= buf.len() { + break; + } } } } -- cgit v1.1