aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2020-01-15 01:17:42 -0800
committeriximeow <me@iximeow.net>2020-01-15 01:17:42 -0800
commitc03917812aa6ce5a731d743298cb2ab46627189a (patch)
tree698d38f653a44fb3cf4dfba688db67c36ba3fe61
parentb7ac0d56035dda259d9c666c03bc70ace5e58f41 (diff)
no_std!!
this makes yaxpeax-x86 no_std. no externally-visible changes!
-rw-r--r--Cargo.toml13
-rw-r--r--src/display.rs179
-rw-r--r--src/lib.rs33
3 files changed, 156 insertions, 69 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 7931af4..a6b96b9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,7 +8,7 @@ repository = "http://git.iximeow.net/yaxpeax-x86/"
description = "x86 decoders for the yaxpeax project"
[dependencies]
-yaxpeax-arch = { path = "../../yaxpeax-arch" }
+yaxpeax-arch = { path = "../../yaxpeax-arch", default-features = false, features = []}
"num-traits" = "0.2"
"termion" = "1.4.0"
"serde" = "1.0"
@@ -32,10 +32,15 @@ opt-level = 3
lto = true
[features]
-default = []
+default = ["std", "colors", "use-serde"]
+
+# opt-in for some apis that are really much nicer with String
+std = []
+
+use-serde = ["yaxpeax-arch/use-serde"]
+
+colors = ["yaxpeax-arch/colors"]
# This enables some capstone benchmarks over the same
# instruction bytes used to bench this code.
capstone_bench = []
-
-use-serde = []
diff --git a/src/display.rs b/src/display.rs
index bea5340..4c97d5c 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -1,9 +1,9 @@
extern crate yaxpeax_arch;
extern crate termion;
-use std::fmt;
+use core::fmt;
-use yaxpeax_arch::{Colorize, ColorSettings, ShowContextual, YaxColors};
+use yaxpeax_arch::{Colorize, ShowContextual, NoColors, YaxColors};
use yaxpeax_arch::display::*;
use ::{RegSpec, RegisterBank, Opcode, Operand, InstDecoder, Instruction, Segment, PrefixRex, OperandSpec, DecodeError};
@@ -172,36 +172,36 @@ impl fmt::Display for RegSpec {
impl fmt::Display for Operand {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- self.colorize(None, fmt)
+ self.colorize(&NoColors, fmt)
}
}
-impl <T: std::fmt::Write> Colorize<T> for Operand {
- fn colorize(&self, colors: Option<&ColorSettings>, f: &mut T) -> std::fmt::Result {
+impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color, Y> for Operand {
+ fn colorize(&self, colors: &Y, f: &mut T) -> fmt::Result {
match self {
&Operand::ImmediateU8(imm) => {
- write!(f, "{}", colors.number(format!("{:#x}", imm)))
+ write!(f, "{}", colors.number(u8_hex(imm)))
}
&Operand::ImmediateI8(imm) => {
write!(f, "{}",
colors.number(signed_i8_hex(imm)))
},
&Operand::ImmediateU16(imm) => {
- write!(f, "{}", colors.number(format!("{:#x}", imm)))
+ write!(f, "{}", colors.number(u16_hex(imm)))
}
&Operand::ImmediateI16(imm) => {
write!(f, "{}",
colors.number(signed_i16_hex(imm)))
},
&Operand::ImmediateU32(imm) => {
- write!(f, "{}", colors.number(format!("{:#x}", imm)))
+ write!(f, "{}", colors.number(u32_hex(imm)))
}
&Operand::ImmediateI32(imm) => {
write!(f, "{}",
colors.number(signed_i32_hex(imm)))
},
&Operand::ImmediateU64(imm) => {
- write!(f, "{}", colors.number(format!("{:#x}", imm)))
+ write!(f, "{}", colors.number(u64_hex(imm)))
}
&Operand::ImmediateI64(imm) => {
write!(f, "{}",
@@ -211,22 +211,15 @@ impl <T: std::fmt::Write> Colorize<T> for Operand {
write!(f, "{}", colors.register(spec))
}
&Operand::DisplacementU32(imm) => {
- write!(f, "[{}]", colors.address(format!("{:#x}", imm)))
+ write!(f, "[{}]", colors.address(u32_hex(imm)))
}
&Operand::DisplacementU64(imm) => {
- write!(f, "[{}]", colors.address(format!("{:#x}", imm)))
+ write!(f, "[{}]", colors.address(u64_hex(imm)))
}
- &Operand::RegDisp(ref spec, ref disp) => {
- let (sign, disp) = if *disp < 0 {
- (true, (-std::num::Wrapping(*disp)).0)
- } else {
- (false, *disp)
- };
- write!(f, "[{} {} {}]",
- colors.register(spec),
- if sign { "-" } else { "+" },
- colors.number(format!("{:#x}", disp))
- )
+ &Operand::RegDisp(ref spec, disp) => {
+ write!(f, "[{} ", colors.register(spec))?;
+ format_number_i32(colors, f, disp, NumberStyleHint::HexSignedWithSignSplit)?;
+ write!(f, "]")
},
&Operand::RegDeref(ref spec) => {
write!(f, "[{}]", colors.register(spec))
@@ -238,11 +231,12 @@ impl <T: std::fmt::Write> Colorize<T> for Operand {
)
},
&Operand::RegScaleDisp(ref spec, scale, disp) => {
- write!(f, "[{} * {} + {}]",
+ write!(f, "[{} * {} ",
colors.register(spec),
colors.number(scale),
- colors.number(format!("{:#x}", disp))
- )
+ )?;
+ format_number_i32(colors, f, disp, NumberStyleHint::HexSignedWithSignSplit)?;
+ write!(f, "]")
},
&Operand::RegIndexBase(ref base, ref index) => {
write!(f, "[{} + {}]",
@@ -251,11 +245,12 @@ impl <T: std::fmt::Write> Colorize<T> for Operand {
)
}
&Operand::RegIndexBaseDisp(ref base, ref index, disp) => {
- write!(f, "[{} + {} + {}]",
+ write!(f, "[{} + {} ",
colors.register(base),
colors.register(index),
- colors.register(format!("{:#x}", disp))
- )
+ )?;
+ format_number_i32(colors, f, disp, NumberStyleHint::HexSignedWithSignSplit)?;
+ write!(f, "]")
},
&Operand::RegIndexBaseScale(ref base, ref index, scale) => {
write!(f, "[{} + {} * {}]",
@@ -265,21 +260,15 @@ impl <T: std::fmt::Write> Colorize<T> for Operand {
)
}
&Operand::RegIndexBaseScaleDisp(ref base, ref index, scale, disp) => {
- write!(f, "[{} + {} * {} + {}]",
+ write!(f, "[{} + {} * {} ",
colors.register(base),
colors.register(index),
colors.number(scale),
- colors.number(format!("{:#x}", disp))
- )
+ )?;
+ format_number_i32(colors, f, disp, NumberStyleHint::HexSignedWithSignSplit)?;
+ write!(f, "]")
},
&Operand::Nothing => { Ok(()) },
- // &Operand::Many(_) => { panic!("many not covered"); }
- &Operand::Many(ref ops) => {
- for op in ops.iter() {
- write!(f, ", {}", op)?;
- }
- Ok(())
- }
}
}
}
@@ -1052,8 +1041,8 @@ impl fmt::Display for Opcode {
}
}
-impl <T: std::fmt::Write> Colorize<T> for Opcode {
- fn colorize(&self, colors: Option<&ColorSettings>, out: &mut T) -> std::fmt::Result {
+impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color, Y> for Opcode {
+ fn colorize(&self, colors: &Y, out: &mut T) -> fmt::Result {
match self {
Opcode::VHADDPS |
Opcode::VHSUBPS |
@@ -1831,7 +1820,7 @@ impl <T: std::fmt::Write> Colorize<T> for Opcode {
impl fmt::Display for Instruction {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- self.colorize(None, fmt)
+ self.colorize(&NoColors, fmt)
}
}
@@ -1848,16 +1837,114 @@ impl fmt::Display for Instruction {
* so write to some Write thing i guess. bite me. i really just want to
* stop thinking about how to support printing instructions...
*/
-impl <T: std::fmt::Write> Colorize<T> for Instruction {
- fn colorize(&self, colors: Option<&ColorSettings>, out: &mut T) -> std::fmt::Result {
+impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> Colorize<T, Color, Y> for Instruction {
+ fn colorize(&self, colors: &Y, out: &mut T) -> fmt::Result {
// TODO: I DONT LIKE THIS, there is no address i can give contextualize here,
// the address operand maybe should be optional..
- self.contextualize(colors, 0, None, out)
+ self.contextualize(colors, 0, Some(&NoContext), out)
+ }
+}
+
+/// No per-operand context when contextualizing an instruction!
+struct NoContext;
+
+impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> ShowContextual<u64, NoContext, Color, T, Y> for Instruction {
+ fn contextualize(&self, colors: &Y, _address: u64, _context: Option<&NoContext>, out: &mut T) -> fmt::Result {
+ if self.prefixes.lock() {
+ write!(out, "lock ")?;
+ }
+
+ if [Opcode::MOVS, Opcode::CMPS, Opcode::LODS, Opcode::STOS, Opcode::INS, Opcode::OUTS].contains(&self.opcode) {
+ // only a few of you actually use the prefix...
+ if self.prefixes.rep() {
+ write!(out, "rep ")?;
+ } else if self.prefixes.repz() {
+ write!(out, "repz ")?;
+ } else if self.prefixes.repnz() {
+ write!(out, "repnz ")?;
+ }
+ }
+
+ self.opcode.colorize(colors, out)?;
+
+ match self.operands[0] {
+ OperandSpec::Nothing => {
+ return Ok(());
+ },
+ _ => {
+ write!(out, " ")?;
+ if let Some(prefix) = self.segment_override_for_op(0) {
+ write!(out, "{}:", prefix)?;
+ }
+ }
+ }
+ let x = Operand::from_spec(self, self.operands[0]);
+ x.colorize(colors, out)?;
+
+ for i in 1..4 {
+ match self.opcode {
+ Opcode::MOVSX_b |
+ Opcode::MOVZX_b => {
+ match &self.operands[i] {
+ &OperandSpec::Nothing => {
+ return Ok(());
+ },
+ &OperandSpec::RegMMM => {
+ write!(out, ", ")?;
+ }
+ _ => {
+ write!(out, ", byte ")?;
+ if let Some(prefix) = self.segment_override_for_op(1) {
+ write!(out, "{}:", prefix)?;
+ }
+ }
+ }
+ let x = Operand::from_spec(self, self.operands[i]);
+ x.colorize(colors, out)?
+ },
+ Opcode::MOVSX_w |
+ Opcode::MOVZX_w => {
+ match &self.operands[i] {
+ &OperandSpec::Nothing => {
+ return Ok(());
+ },
+ &OperandSpec::RegMMM => {
+ write!(out, ", ")?;
+ }
+ _ => {
+ write!(out, ", word ")?;
+ if let Some(prefix) = self.segment_override_for_op(1) {
+ write!(out, "{}:", prefix)?;
+ }
+ }
+ }
+ let x = Operand::from_spec(self, self.operands[i]);
+ x.colorize(colors, out)?
+ },
+ _ => {
+ match &self.operands[i] {
+ &OperandSpec::Nothing => {
+ return Ok(());
+ },
+ _ => {
+ write!(out, ", ")?;
+ if let Some(prefix) = self.segment_override_for_op(1) {
+ write!(out, "{}:", prefix)?;
+ }
+ let x = Operand::from_spec(self, self.operands[i]);
+ x.colorize(colors, out)?
+ }
+ }
+ }
+ }
+ }
+ Ok(())
}
}
-impl <T: std::fmt::Write> ShowContextual<u64, [Option<String>], T> for Instruction {
- fn contextualize(&self, colors: Option<&ColorSettings>, _address: u64, context: Option<&[Option<String>]>, out: &mut T) -> std::fmt::Result {
+#[cfg(feature="std")]
+impl <T: fmt::Write, Color: fmt::Display, Y: YaxColors<Color>> ShowContextual<u64, [Option<alloc::string::String>], Color, T, Y> for Instruction {
+ fn contextualize(&self, colors: &Y, _address: u64, context: Option<&[Option<alloc::string::String>]>, out: &mut T) -> fmt::Result {
if self.prefixes.lock() {
write!(out, "lock ")?;
}
diff --git a/src/lib.rs b/src/lib.rs
index 1530866..6941b9e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,15 +1,20 @@
+#![no_std]
+
#[cfg(feature="use-serde")]
#[macro_use] extern crate serde_derive;
#[cfg(feature="use-serde")]
extern crate serde;
+#[cfg(feature="std")]
+extern crate alloc;
+
extern crate yaxpeax_arch;
extern crate termion;
mod vex;
mod display;
-use std::hint::unreachable_unchecked;
+use core::hint::unreachable_unchecked;
use yaxpeax_arch::{Arch, Decoder, LengthedInstruction};
@@ -26,8 +31,8 @@ pub struct RegSpec {
pub bank: RegisterBank
}
-use std::hash::Hash;
-use std::hash::Hasher;
+use core::hash::Hash;
+use core::hash::Hasher;
impl Hash for RegSpec {
fn hash<H: Hasher>(&self, state: &mut H) {
let code = ((self.bank as u16) << 8) | (self.num as u16);
@@ -228,7 +233,6 @@ pub enum Operand {
RegScaleDisp(RegSpec, u8, i32),
RegIndexBaseScale(RegSpec, RegSpec, u8),
RegIndexBaseScaleDisp(RegSpec, RegSpec, u8, i32),
- Many(Vec<Operand>),
Nothing,
}
@@ -359,25 +363,16 @@ impl Operand {
Operand::Nothing => {
false
}
- Operand::Many(els) => {
- for el in els.iter() {
- if el.is_memory() {
- return true;
- }
- }
-
- false
- }
}
}
}
#[test]
fn operand_size() {
- assert_eq!(std::mem::size_of::<OperandSpec>(), 1);
- assert_eq!(std::mem::size_of::<RegSpec>(), 2);
- // assert_eq!(std::mem::size_of::<Prefixes>(), 4);
- // assert_eq!(std::mem::size_of::<Instruction>(), 40);
+ assert_eq!(core::mem::size_of::<OperandSpec>(), 1);
+ assert_eq!(core::mem::size_of::<RegSpec>(), 2);
+ // assert_eq!(core::mem::size_of::<Prefixes>(), 4);
+ // assert_eq!(core::mem::size_of::<Instruction>(), 40);
}
#[allow(non_camel_case_types)]
@@ -4089,7 +4084,7 @@ struct OpcodeRecord(Interpretation, OperandCode);
#[test]
fn opcode_record_size() {
// there are more than 256 opcodes...
- assert_eq!(std::mem::size_of::<OpcodeRecord>(), 4);
+ assert_eq!(core::mem::size_of::<OpcodeRecord>(), 4);
}
const OPCODES: [OpcodeRecord; 256] = [
@@ -4567,7 +4562,7 @@ fn width_to_gp_reg_bank(width: u8, rex: bool) -> RegisterBank {
fn read_instr<T: Iterator<Item=u8>>(decoder: &InstDecoder, mut bytes_iter: T, instruction: &mut Instruction) -> Result<(), DecodeError> {
let mut length = 0u8;
let mut alternate_opcode_map: Option<OpcodeMap> = None;
-// use std::intrinsics::unlikely;
+// use core::intrinsics::unlikely;
let mut prefixes = Prefixes::new(0);
fn escapes_are_prefixes_actually(prefixes: &mut Prefixes, opc_map: &mut Option<OpcodeMap>) {