aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorнаб <nabijaczleweli@nabijaczleweli.xyz>2021-01-06 19:53:22 +0100
committeriximeow <me@iximeow.net>2021-01-15 19:05:00 -0800
commit9523d4408ad1dc8f5658ed27c772ae68c829d792 (patch)
tree15cc34f358bea06ce81af1d2089f663f27f55ccc
parent06aa925affdaf9b4fbbb8ba68ec4530e662a25e7 (diff)
add superh
Made slightly less pretty by the many silicon- and run-time features of most SuperH processors
-rw-r--r--Cargo.lock10
-rw-r--r--Cargo.toml1
-rw-r--r--README.md2
-rw-r--r--src/main.rs77
4 files changed, 83 insertions, 7 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 89b12e1..9d68d4d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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"
diff --git a/Cargo.toml b/Cargo.toml
index 4552fc6..692655e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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" }
diff --git a/README.md b/README.md
index cd8f7a9..3df0fac 100644
--- a/README.md
+++ b/README.md
@@ -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.
diff --git a/src/main.rs b/src/main.rs
index 732f747..99d7ad3 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -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 {