aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-08-22 15:47:21 -0700
committeriximeow <me@iximeow.net>2021-08-22 15:47:52 -0700
commitd2ec91d2fa0b20fa7cb935ea279a90367f6dcc1e (patch)
tree6f7525e29f399226ba953e0b02d882397af45aa8
parentb9f2d5715a52cbf49bc2eac7b2f40bec7e2acba8 (diff)
commit to x86-supporting field annotationfield-annotation
-rw-r--r--Cargo.lock243
-rw-r--r--Cargo.toml16
-rw-r--r--src/main.rs313
3 files changed, 361 insertions, 211 deletions
diff --git a/Cargo.lock b/Cargo.lock
index fdbb538..c61f09e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -47,12 +47,6 @@ dependencies = [
]
[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
name = "clap"
version = "2.33.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -68,29 +62,10 @@ dependencies = [
]
[[package]]
-name = "crossterm"
-version = "0.19.0"
+name = "either"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c36c10130df424b2f3552fcc2ddcd9b28a27b1e54b358b45874f88d1ca6888c"
-dependencies = [
- "bitflags",
- "crossterm_winapi",
- "lazy_static",
- "libc",
- "mio",
- "parking_lot",
- "signal-hook",
- "winapi",
-]
-
-[[package]]
-name = "crossterm_winapi"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0da8964ace4d3e4a044fd027919b2237000b24315a37c916f61809f1ff2140b9"
-dependencies = [
- "winapi",
-]
+checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "funty"
@@ -100,9 +75,9 @@ checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
[[package]]
name = "hermit-abi"
-version = "0.1.18"
+version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
@@ -114,74 +89,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
-name = "instant"
-version = "0.1.9"
+name = "itertools"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
+checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf"
dependencies = [
- "cfg-if",
+ "either",
]
[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-
-[[package]]
name = "libc"
-version = "0.2.94"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
-
-[[package]]
-name = "lock_api"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb"
-dependencies = [
- "scopeguard",
-]
-
-[[package]]
-name = "log"
-version = "0.4.14"
+version = "0.2.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "mio"
-version = "0.7.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956"
-dependencies = [
- "libc",
- "log",
- "miow",
- "ntapi",
- "winapi",
-]
-
-[[package]]
-name = "miow"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "ntapi"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
-dependencies = [
- "winapi",
-]
+checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
[[package]]
name = "num-traits"
@@ -204,31 +124,6 @@ dependencies = [
]
[[package]]
-name = "parking_lot"
-version = "0.11.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
-dependencies = [
- "instant",
- "lock_api",
- "parking_lot_core",
-]
-
-[[package]]
-name = "parking_lot_core"
-version = "0.8.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
-dependencies = [
- "cfg-if",
- "instant",
- "libc",
- "redox_syscall",
- "smallvec",
- "winapi",
-]
-
-[[package]]
name = "proc-macro2"
version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -239,9 +134,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.26"
+version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
+checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
dependencies = [
"unicode-xid 0.2.2",
]
@@ -261,7 +156,7 @@ version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.28",
]
[[package]]
@@ -271,64 +166,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
[[package]]
-name = "redox_syscall"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "742739e41cd49414de871ea5e549afb7e2a3ac77b589bcbebe8c82fab37147fc"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "scopeguard"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
-
-[[package]]
name = "serde"
-version = "1.0.125"
+version = "1.0.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
+checksum = "f03b9878abf6d14e6779d3f24f07b2cfa90352cfec4acc5aab8f1ac7f146fae8"
[[package]]
name = "serde_derive"
-version = "1.0.125"
+version = "1.0.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
+checksum = "a024926d3432516606328597e0f224a51355a493b49fdd67e9209187cbe55ecc"
dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.28",
"quote 1.0.9",
- "syn 1.0.72",
-]
-
-[[package]]
-name = "signal-hook"
-version = "0.1.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e31d442c16f047a671b5a71e2161d6e68814012b7f5379d269ebd915fac2729"
-dependencies = [
- "libc",
- "mio",
- "signal-hook-registry",
+ "syn 1.0.74",
]
[[package]]
-name = "signal-hook-registry"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16f1d0fef1604ba8f7a073c7e701f213e056707210e9020af4528e0101ce11a6"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "smallvec"
-version = "1.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
-
-[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -347,11 +201,11 @@ dependencies = [
[[package]]
name = "syn"
-version = "1.0.72"
+version = "1.0.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1e8cdbefb79a9a5a65e0db8b47b723ee907b7c7f8496c76a1770b5c310bab82"
+checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c"
dependencies = [
- "proc-macro2 1.0.26",
+ "proc-macro2 1.0.28",
"quote 1.0.9",
"unicode-xid 0.2.2",
]
@@ -445,19 +299,13 @@ version = "0.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6d51fa58dc03a872cf25e864c5edeb57a00a0be1e99112fe9b620eed839f035"
dependencies = [
- "crossterm",
"num-traits",
- "serde",
- "serde_derive",
]
[[package]]
name = "yaxpeax-arch"
-version = "0.2.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0c90868b68ae34284714134e827062757881ab642e5746ecdcd567ffd582ff7"
+version = "0.2.6"
dependencies = [
- "crossterm",
"num-traits",
"serde",
"serde_derive",
@@ -470,9 +318,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfde0eac22b9044b4d1f07b9fba1e81114ddb529912035a56b64c5524d411966"
dependencies = [
"bitvec",
- "serde",
- "serde_derive",
- "yaxpeax-arch 0.2.5",
+ "yaxpeax-arch 0.2.6",
]
[[package]]
@@ -481,7 +327,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94153e4e363dd4b0bea761ce9615647f2a29a9c3d46d3467c776969eb2b4e91c"
dependencies = [
- "yaxpeax-arch 0.2.5",
+ "yaxpeax-arch 0.2.6",
]
[[package]]
@@ -490,10 +336,11 @@ version = "0.2.9"
dependencies = [
"clap",
"hex",
+ "itertools",
"num-traits",
"yaxpeax-6502",
"yaxpeax-arch 0.0.5",
- "yaxpeax-arch 0.2.5",
+ "yaxpeax-arch 0.2.6",
"yaxpeax-arm",
"yaxpeax-avr",
"yaxpeax-ia64",
@@ -510,11 +357,9 @@ dependencies = [
[[package]]
name = "yaxpeax-ia64"
version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3ea0f2b5728fb7eb1861532cd755ff7dd993843778d548df70a4aca95f9914e"
dependencies = [
"bitvec",
- "yaxpeax-arch 0.2.5",
+ "yaxpeax-arch 0.2.6",
]
[[package]]
@@ -523,7 +368,7 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cf556f365c2fa2104e4e9a36105d9a2f72085dfd7168c95abf4f0d7cdac0cff"
dependencies = [
- "yaxpeax-arch 0.2.5",
+ "yaxpeax-arch 0.2.6",
]
[[package]]
@@ -535,7 +380,7 @@ dependencies = [
"num-traits",
"serde",
"serde_derive",
- "yaxpeax-arch 0.2.5",
+ "yaxpeax-arch 0.2.6",
]
[[package]]
@@ -545,34 +390,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d83d243a75ff9312b78ef761596cf0bf3b625786176363d65e653a75042873a"
dependencies = [
"num_enum",
- "yaxpeax-arch 0.2.5",
+ "yaxpeax-arch 0.2.6",
]
[[package]]
name = "yaxpeax-msp430"
version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "63962bd68624664aa3a3391785f95388001e9d6107cdf8557e962153e4a854c5"
dependencies = [
- "yaxpeax-arch 0.2.5",
+ "yaxpeax-arch 0.2.6",
]
[[package]]
name = "yaxpeax-pic17"
-version = "0.1.0"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb717c23e96ce83de1569c512ab5508a6e39a194a73662e618608f0f1c41ada4"
+checksum = "15ca63b323712143e563e146af6a3df21fa3c75976985ee7b157470616c15c1e"
dependencies = [
- "yaxpeax-arch 0.2.5",
+ "yaxpeax-arch 0.2.6",
]
[[package]]
name = "yaxpeax-pic18"
-version = "0.1.0"
+version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf1fb0d482f0f7d23394e31e50bce78d8320760c790d86e324c1a1e49710097a"
+checksum = "f64bb0d36fc65721e5919e9febe316ae62cf0ba2510cddb01d1f182ddcc97f84"
dependencies = [
- "yaxpeax-arch 0.2.5",
+ "yaxpeax-arch 0.2.6",
]
[[package]]
@@ -586,12 +429,8 @@ dependencies = [
[[package]]
name = "yaxpeax-x86"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcf1fb167a86a30c9592ade2140efe3b396a42a4a429d4b98521b2e2b0ad6fcd"
+version = "1.1.0"
dependencies = [
"num-traits",
- "serde",
- "serde_derive",
- "yaxpeax-arch 0.2.5",
+ "yaxpeax-arch 0.2.6",
]
diff --git a/Cargo.toml b/Cargo.toml
index 1751d14..ab69d41 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,24 +13,28 @@ readme = "README.md"
name = "yaxdis"
path = "src/main.rs"
+[patch.crates-io]
+yaxpeax-arch-02 = { package = "yaxpeax-arch", path = "/toy/yaxpeax/yaxpeax-arch/" }
+
[dependencies]
clap = "2.33"
hex = "0.4.0"
num-traits = "0.2.10"
+itertools = "0.10.1"
# common interfaces for all yaxpeax decoders
-yaxpeax-arch-02 = { package = "yaxpeax-arch", version = "0.2.4" }
-yaxpeax-arch-01 = { package = "yaxpeax-arch", version = "0.0.5" }
+yaxpeax-arch-02 = { package = "yaxpeax-arch", version = "0.2.4" , default-features = false, features = ["std"] }
+yaxpeax-arch-01 = { package = "yaxpeax-arch", version = "0.0.5" , default-features = false }
-yaxpeax-arm = { version = "0.1.1" }
+yaxpeax-arm = { version = "0.1.1", default-features = false, features = ["std"] }
yaxpeax-avr = { version = "0.1.0" }
yaxpeax-m16c = { version = "0.1.0" }
yaxpeax-mips = { version = "0.1.0" }
-yaxpeax-msp430 = { version = "0.1.0" }
+yaxpeax-msp430 = { version = "0.1.0", path = "/toy/yaxpeax/arch/msp430" }
yaxpeax-lc87 = { version = "1.0.0" }
yaxpeax-pic17 = { version = "0.1.0" }
yaxpeax-pic18 = { version = "0.1.0" }
-yaxpeax-x86 = { version = "1.0.4" }
-yaxpeax-ia64 = { version = "0.2.1" }
+yaxpeax-x86 = { version = "1.1.0", default-features = false, features = ["fmt", "std"] }
+yaxpeax-ia64 = { version = "0.2.1", path = "/toy/yaxpeax/arch/ia64" }
yaxpeax-superh = { version = "0.1.0" }
yaxpeax-6502 = { version = "0.0.1" }
diff --git a/src/main.rs b/src/main.rs
index 0c6a5fc..9184601 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -83,16 +83,18 @@ fn main() {
match arch_str {
"x86_64" |
- "x86:64" => crate::current_arch::decode_input::<yaxpeax_x86::long_mode::Arch>(&buf, verbose),
+ "x86:64" => crate::current_arch::decode_input_with_annotation::<yaxpeax_x86::long_mode::Arch>(&buf, verbose),
"x86_32" |
- "x86:32" => crate::current_arch::decode_input::<yaxpeax_x86::protected_mode::Arch>(&buf, verbose),
+ "x86:32" => crate::current_arch::decode_input_with_annotation::<yaxpeax_x86::protected_mode::Arch>(&buf, verbose),
"x86_16" |
- "x86:16" => crate::current_arch::decode_input::<yaxpeax_x86::real_mode::Arch>(&buf, verbose),
+ "x86:16" => crate::current_arch::decode_input_with_annotation::<yaxpeax_x86::real_mode::Arch>(&buf, verbose),
+ // "ia64" => crate::current_arch::decode_input_with_annotation::<yaxpeax_ia64::IA64>(&buf, verbose),
"ia64" => crate::current_arch::decode_input::<yaxpeax_ia64::IA64>(&buf, verbose),
"avr" => crate::current_arch::decode_input::<yaxpeax_avr::AVR>(&buf, verbose),
"armv7" => crate::current_arch::decode_input::<yaxpeax_arm::armv7::ARMv7>(&buf, verbose),
"armv8" => crate::current_arch::decode_input::<yaxpeax_arm::armv8::a64::ARMv8>(&buf, verbose),
"mips" => crate::current_arch::decode_input::<yaxpeax_mips::MIPS>(&buf, verbose),
+ // "msp430" => crate::current_arch::decode_input_with_annotation::<yaxpeax_msp430::MSP430>(&buf, verbose),
"msp430" => crate::current_arch::decode_input::<yaxpeax_msp430::MSP430>(&buf, verbose),
"pic17" => crate::current_arch::decode_input::<yaxpeax_pic17::PIC17>(&buf, verbose),
"pic18" => crate::current_arch::decode_input::<yaxpeax_pic18::PIC18>(&buf, verbose),
@@ -158,9 +160,240 @@ fn with_parsed_superh<F: FnOnce(yaxpeax_superh::SuperHDecoder)>(
// yaxpeax-arch while older decoders are still being updated.
mod current_arch {
use yaxpeax_arch_02::{AddressBase, Arch, Decoder, Instruction, LengthedInstruction, Reader, U8Reader};
+ use yaxpeax_arch_02::{AnnotatingDecoder, FieldDescription, VecSink};
use std::fmt;
use num_traits::identities::Zero;
+ fn col2bit(col: usize) -> usize {
+ // ia64
+ // 127 - col
+ // msp430
+ /*
+ let word = col >> 4;
+ let bit = 15 - (col & 0xf);
+
+ (word << 4) | bit
+ */
+ // x86
+ let byte = col / 8;
+ let bit = (7 - (col % 8));
+ let bit = byte * 8 + bit;
+ bit
+ }
+ fn bit2col(bit: usize) -> usize {
+ let byte = bit / 8;
+ let bit = (7 - (bit % 8));
+ let bit = byte * 8 + bit;
+ bit
+ }
+
+ #[derive(Debug)]
+ struct BitRange {
+ start: u32,
+ end: u32,
+ lhs: u32,
+ rhs: u32,
+ }
+
+ impl BitRange {
+ fn across(start: u32, end: u32) -> BitRange {
+ let mut lhs = bit2col(start as usize) as u32;
+ let mut rhs = bit2col(start as usize) as u32;
+ for bit in start..=end {
+ lhs = std::cmp::min(lhs, bit2col(bit as usize) as u32);
+ rhs = std::cmp::max(rhs, bit2col(bit as usize) as u32);
+ }
+ BitRange { start, end, lhs, rhs }
+ }
+ }
+
+ struct ItemDescription<A: Arch> where A::Decoder: AnnotatingDecoder<A> {
+ ranges: Vec<BitRange>,
+ description: <<A as Arch>::Decoder as AnnotatingDecoder<A>>::FieldDescription,
+ }
+
+ impl<A: Arch> fmt::Debug for ItemDescription<A> where A::Decoder: AnnotatingDecoder<A> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{{ ranges: {:?}, description: {} }}", &self.ranges, &self.description)
+ }
+ }
+
+ // spans grouped together in some decoder-specified logical structure by
+ // `id`. `id` is a hint that data should be considered related for display
+ // purposes.
+ struct FieldRecord<A: Arch> where A::Decoder: AnnotatingDecoder<A> {
+ // spans grouped together by `FieldDescription` - one field may be
+ // described by multiple distinct spans, so those spans are recorded
+ // here. elements are ordered by the lowest bit of spans describing an
+ // element.
+ elements: Vec<ItemDescription<A>>,
+ id: u32,
+ }
+
+ impl<A: Arch> fmt::Debug for FieldRecord<A> where A::Decoder: AnnotatingDecoder<A> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{{ elements: {:?}, id: {} }}", &self.elements, &self.id)
+ }
+ }
+
+ fn show_field_descriptions<A: Arch>(fields: &[FieldRecord<A>], data: &[u8]) where A::Decoder: AnnotatingDecoder<A> {
+ let mut boundaries = [false; 256];
+ let mut separators = [false; 256];
+ let mut bits = [false; 256];
+ let mut rhs = [false; 256];
+ let mut lhs = [false; 256];
+ let mut field_order: Vec<(usize, usize)> = Vec::new();
+ let mut boundary_order: Vec<(usize, usize)> = Vec::new();
+
+ for (fi, field) in fields.iter().enumerate() {
+ for (ei, element) in field.elements.iter().enumerate() {
+ if element.description.is_separator() {
+ for (_ri, range) in element.ranges.iter().enumerate() {
+ boundaries[range.start as usize + 1] = true;
+ boundary_order.push((fi, range.start as usize + 1));
+ }
+ continue;
+ }
+ field_order.push((fi, ei));
+ for (_ri, range) in element.ranges.iter().enumerate() {
+ for i in range.start..=range.end {
+ bits[i as usize] = true;
+ }
+ separators[range.start as usize] = true;
+ lhs[range.lhs as usize] = true;
+ rhs[range.rhs as usize] = true;
+ }
+ }
+ }
+ boundary_order.sort_by(|l, r| r.1.cmp(&l.1));
+
+ // regardless of sections, the left-hand side of the terminal is a free boundary
+ lhs[0] = false;
+
+ let mut res = String::new();
+ res.push_str(" \n");
+
+ let mut fudge_bits = [false; 160];
+
+ for i in 0..160 {
+ if (i >> 3) >= data.len() {
+ continue;
+ }
+
+ let mut fudge = false;
+
+ if lhs[i] {
+ fudge = true;
+ }
+
+ if i > 0 && rhs[i - 1] {
+ fudge = true;
+ }
+
+ if fudge {
+ fudge_bits[i] = true;
+ }
+ }
+
+ let mut fudge = 0;
+ let mut col = [b' '; 160];
+
+ for i in 0..160 {
+ if (i >> 3) >= data.len() {
+ continue;
+ }
+
+ let bit = col2bit(i);
+
+ if fudge_bits[i] {
+ fudge += 1;
+ }
+
+ if data[(bit >> 3) as usize] & (1 << (bit as u8 & 7)) != 0 {
+ col[i + fudge] = b'1';
+ } else {
+ col[i + fudge] = b'0';
+ }
+ }
+ res.push_str(unsafe { std::str::from_utf8_unchecked(&col) });
+ res.push_str("\n");
+
+ for (fi, ei) in field_order.iter() {
+ let mut col = [b' '; 160];
+
+ for range in &fields[*fi as usize].elements[*ei as usize].ranges {
+ let mut fudge = 0;
+
+ for c in 0..128 {
+ let bit = col2bit(c as usize);
+
+ if boundaries[c] {
+ col[c + fudge] = b'|';
+ }
+ if fudge_bits[c as usize] {
+ fudge += 1;
+ }
+
+ if bit >= range.start as usize && bit <= range.end as usize {
+ let data_bit = data[(bit >> 3) as usize] & (1 << (bit as u8 & 7)) != 0;
+ col[c as usize + fudge] = if data_bit { b'1' } else { b'0' };
+ }
+ }
+ }
+
+ res.push_str(unsafe { std::str::from_utf8_unchecked(&col[..(data.len() * 8 + 30)]) });
+ res.push_str(" ");
+ res.push_str(&fields[*fi as usize].elements[*ei as usize].description.to_string());
+ res.push_str("\n");
+ }
+
+ let mut fudge = 0;
+ let mut col = [b' '; 160];
+
+ for i in 0..160 {
+ if (i >> 3) >= data.len() {
+ continue;
+ }
+
+ if boundaries[i] {
+ col[i + fudge] = b'|';
+ }
+ if fudge_bits[i] {
+ fudge += 1;
+ }
+ }
+ res.push_str(unsafe { std::str::from_utf8_unchecked(&col) });
+ res.push_str("\n");
+
+ for (field_index, bit) in boundary_order {
+ let mut fudge = 0;
+ let mut col = [b' '; 160];
+
+ for i in 0..160 {
+ if (i >> 3) >= data.len() {
+ continue;
+ }
+
+ if i == bit {
+ res.push_str(unsafe { std::str::from_utf8_unchecked(&col[..i + fudge]) });
+ break;
+ }
+
+ if boundaries[i] {
+ col[i + fudge] = b'|';
+ }
+ if fudge_bits[i] {
+ fudge += 1;
+ }
+ }
+ use std::fmt::Write;
+ let _ = write!(res, "{}", fields[field_index].elements[0].description);
+ res.push_str("\n");
+ }
+
+ println!("{}", res);
+ }
+
pub(crate) fn decode_input<A: Arch>(buf: &[u8], verbose: bool)
where
A::Instruction: fmt::Display, for<'data> U8Reader<'data>: Reader<A::Address, A::Word>,
@@ -168,6 +401,14 @@ mod current_arch {
decode_input_with_decoder::<A>(A::Decoder::default(), buf, verbose);
}
+ pub(crate) fn decode_input_with_annotation<A: Arch>(buf: &[u8], verbose: bool)
+ where
+ A::Instruction: fmt::Display, for<'data> U8Reader<'data>: Reader<A::Address, A::Word>,
+ A::Decoder: AnnotatingDecoder<A>,
+ {
+ decode_input_with_decoder_and_annotation::<A>(A::Decoder::default(), buf, verbose);
+ }
+
pub(crate) fn decode_input_with_decoder<A: Arch>(decoder: A::Decoder, buf: &[u8], verbose: bool)
where
A::Instruction: fmt::Display, for<'data> U8Reader<'data>: Reader<A::Address, A::Word>,
@@ -205,6 +446,72 @@ mod current_arch {
}
}
}
+
+ pub(crate) fn decode_input_with_decoder_and_annotation<A: Arch>(decoder: A::Decoder, buf: &[u8], verbose: bool)
+ where
+ A::Instruction: fmt::Display, for<'data> U8Reader<'data>: Reader<A::Address, A::Word>,
+ A::Decoder: AnnotatingDecoder<A>,
+ {
+ let start = A::Address::zero();
+ let mut addr = start;
+ loop {
+ let mut sink: VecSink<<A::Decoder as AnnotatingDecoder<A>>::FieldDescription> = VecSink::new();
+ let mut reader = U8Reader::new(&buf[addr.to_linear()..]);
+ let mut inst = A::Instruction::default();
+ match decoder.decode_with_annotation(&mut inst, &mut reader, &mut sink) {
+ Ok(()) => {
+ println!(
+ "{:#010x}: {:14}: {}",
+ addr.to_linear(),
+ hex::encode(
+ &buf[addr.to_linear()..]
+ [..A::Address::zero().wrapping_offset(inst.len()).to_linear()]
+ ),
+ inst
+ );
+ if verbose {
+ let mut fields: Vec<FieldRecord<A>> = Vec::new();
+
+ use itertools::Itertools;
+ let mut vs = sink.records;
+ vs.sort_by_key(|rec| rec.2.id());
+ for (id, group) in &vs.iter().group_by(|x| x.2.id()) {
+ let mut field = FieldRecord {
+ elements: Vec::new(),
+ id: id,
+ };
+
+ for (desc, spans) in &group.group_by(|x| x.2.to_owned()) {
+ let mut item = ItemDescription {
+ ranges: Vec::new(),
+ description: desc,
+ };
+
+ for span in spans {
+ item.ranges.push(BitRange::across(span.0, span.1));
+ }
+ field.elements.push(item);
+ }
+ fields.push(field);
+ }
+ show_field_descriptions(
+ &fields,
+ &buf[addr.to_linear()..]
+ [..A::Address::zero().wrapping_offset(inst.len()).to_linear()]
+ );
+ }
+ addr += inst.len();
+ }
+ Err(e) => {
+ println!("{:#010x}: {}", addr.to_linear(), e);
+ addr += A::Instruction::min_size();
+ }
+ }
+ if addr.to_linear() >= buf.len() {
+ break;
+ }
+ }
+ }
}
mod legacy_arch {