From c03917812aa6ce5a731d743298cb2ab46627189a Mon Sep 17 00:00:00 2001 From: iximeow Date: Wed, 15 Jan 2020 01:17:42 -0800 Subject: no_std!! this makes yaxpeax-x86 no_std. no externally-visible changes! --- Cargo.toml | 13 +++-- src/display.rs | 179 ++++++++++++++++++++++++++++++++++++++++++--------------- src/lib.rs | 33 +++++------ 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 Colorize for Operand { - fn colorize(&self, colors: Option<&ColorSettings>, f: &mut T) -> std::fmt::Result { +impl > Colorize 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 Colorize 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 Colorize 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 Colorize 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 Colorize 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 Colorize for Opcode { - fn colorize(&self, colors: Option<&ColorSettings>, out: &mut T) -> std::fmt::Result { +impl > Colorize for Opcode { + fn colorize(&self, colors: &Y, out: &mut T) -> fmt::Result { match self { Opcode::VHADDPS | Opcode::VHSUBPS | @@ -1831,7 +1820,7 @@ impl Colorize 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 Colorize for Instruction { - fn colorize(&self, colors: Option<&ColorSettings>, out: &mut T) -> std::fmt::Result { +impl > Colorize 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 > ShowContextual 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 ShowContextual], T> for Instruction { - fn contextualize(&self, colors: Option<&ColorSettings>, _address: u64, context: Option<&[Option]>, out: &mut T) -> std::fmt::Result { +#[cfg(feature="std")] +impl > ShowContextual], Color, T, Y> for Instruction { + fn contextualize(&self, colors: &Y, _address: u64, context: Option<&[Option]>, 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(&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), 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::(), 1); - assert_eq!(std::mem::size_of::(), 2); - // assert_eq!(std::mem::size_of::(), 4); - // assert_eq!(std::mem::size_of::(), 40); + assert_eq!(core::mem::size_of::(), 1); + assert_eq!(core::mem::size_of::(), 2); + // assert_eq!(core::mem::size_of::(), 4); + // assert_eq!(core::mem::size_of::(), 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::(), 4); + assert_eq!(core::mem::size_of::(), 4); } const OPCODES: [OpcodeRecord; 256] = [ @@ -4567,7 +4562,7 @@ fn width_to_gp_reg_bank(width: u8, rex: bool) -> RegisterBank { fn read_instr>(decoder: &InstDecoder, mut bytes_iter: T, instruction: &mut Instruction) -> Result<(), DecodeError> { let mut length = 0u8; let mut alternate_opcode_map: Option = 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) { -- cgit v1.1