diff options
| author | iximeow <me@iximeow.net> | 2020-01-15 01:17:42 -0800 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2020-01-15 01:17:42 -0800 | 
| commit | c03917812aa6ce5a731d743298cb2ab46627189a (patch) | |
| tree | 698d38f653a44fb3cf4dfba688db67c36ba3fe61 | |
| parent | b7ac0d56035dda259d9c666c03bc70ace5e58f41 (diff) | |
no_std!!
this makes yaxpeax-x86 no_std. no externally-visible changes!
| -rw-r--r-- | Cargo.toml | 13 | ||||
| -rw-r--r-- | src/display.rs | 179 | ||||
| -rw-r--r-- | src/lib.rs | 33 | 
3 files changed, 156 insertions, 69 deletions
@@ -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 ")?;          } @@ -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>) {  | 
