diff options
| author | iximeow <me@iximeow.net> | 2021-08-13 23:44:28 -0700 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2021-08-21 19:08:40 -0700 | 
| commit | a07098315bea8b880688831f931bc5213ebb6a5f (patch) | |
| tree | 67b134241aefde7919091c51e97bbc6b0f6c62b1 | |
| parent | 9cb6967f484553d78f75113ad534a34960184db8 (diff) | |
extend annotation reporting to 32- and 16-bit modes, kinda
| -rw-r--r-- | src/long_mode/mod.rs | 9 | ||||
| -rw-r--r-- | src/long_mode/vex.rs | 12 | ||||
| -rw-r--r-- | src/protected_mode/mod.rs | 118 | ||||
| -rw-r--r-- | src/protected_mode/vex.rs | 12 | ||||
| -rw-r--r-- | src/real_mode/mod.rs | 118 | ||||
| -rw-r--r-- | src/real_mode/vex.rs | 12 | ||||
| -rw-r--r-- | src/shared/evex.in | 8 | 
7 files changed, 245 insertions, 44 deletions
| diff --git a/src/long_mode/mod.rs b/src/long_mode/mod.rs index 25a1735..54d83e8 100644 --- a/src/long_mode/mod.rs +++ b/src/long_mode/mod.rs @@ -7462,6 +7462,9 @@ impl yaxpeax_arch::FieldDescription for FieldDescription {      fn id(&self) -> u32 {          self.id      } +    fn is_separator(&self) -> bool { +        false +    }  }  impl fmt::Display for FieldDescription { @@ -7547,7 +7550,7 @@ fn read_with_annotations<                      return Err(DecodeError::InvalidPrefixes);                  } else {                      instruction.prefixes = prefixes; -                    vex::two_byte_vex(words, instruction)?; +                    vex::two_byte_vex(words, instruction, sink)?;                      return Ok(());                  }              } else if b == 0xc4 { @@ -7556,7 +7559,7 @@ fn read_with_annotations<                      return Err(DecodeError::InvalidPrefixes);                  } else {                      instruction.prefixes = prefixes; -                    vex::three_byte_vex(words, instruction)?; +                    vex::three_byte_vex(words, instruction, sink)?;                      return Ok(());                  }              } else if b == 0x62 { @@ -7565,7 +7568,7 @@ fn read_with_annotations<                      return Err(DecodeError::InvalidPrefixes);                  } else {                      instruction.prefixes = prefixes; -                    evex::read_evex(words, instruction, None)?; +                    evex::read_evex(words, instruction, None, sink)?;                      return Ok(());                  }              } diff --git a/src/long_mode/vex.rs b/src/long_mode/vex.rs index 9649e72..893d624 100644 --- a/src/long_mode/vex.rs +++ b/src/long_mode/vex.rs @@ -1,8 +1,10 @@  use yaxpeax_arch::Reader; +use yaxpeax_arch::DescriptionSink;  use crate::long_mode::Arch;  use crate::long_mode::OperandSpec;  use crate::long_mode::DecodeError; +use crate::long_mode::FieldDescription;  use crate::long_mode::RegSpec;  use crate::long_mode::RegisterBank;  use crate::long_mode::Instruction; @@ -100,7 +102,10 @@ enum VEXOperandCode {  }  #[inline(never)] -pub(crate) fn three_byte_vex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, instruction: &mut Instruction) -> Result<(), DecodeError> { +pub(crate) fn three_byte_vex< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription>, +>(words: &mut T, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> {      let vex_byte_one = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;      let vex_byte_two = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;      let p = vex_byte_two & 0x03; @@ -130,7 +135,10 @@ pub(crate) fn three_byte_vex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <A      read_vex_instruction(m, words, instruction, p)  } -pub(crate) fn two_byte_vex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, instruction: &mut Instruction) -> Result<(), DecodeError> { +pub(crate) fn two_byte_vex< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription>, +>(words: &mut T, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> {      let vex_byte = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;      let p = vex_byte & 0x03;      let p = match p { diff --git a/src/protected_mode/mod.rs b/src/protected_mode/mod.rs index 2d37bc6..ab55460 100644 --- a/src/protected_mode/mod.rs +++ b/src/protected_mode/mod.rs @@ -13,6 +13,7 @@ use core::cmp::PartialEq;  use core::hint::unreachable_unchecked;  use yaxpeax_arch::{AddressDiff, Decoder, Reader, LengthedInstruction}; +use yaxpeax_arch::{AnnotatingDecoder, DescriptionSink, NullSink};  use yaxpeax_arch::{DecodeError as ArchDecodeError};  use core::fmt; @@ -4090,7 +4091,7 @@ impl Default for InstDecoder {  impl Decoder<Arch> for InstDecoder {      fn decode<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(&self, words: &mut T) -> Result<Instruction, <Arch as yaxpeax_arch::Arch>::DecodeError> {          let mut instr = Instruction::invalid(); -        read_instr(self, words, &mut instr)?; +        read_with_annotations(self, words, &mut instr, &mut NullSink)?;          instr.length = words.offset() as u8;          if words.offset() > 15 { @@ -4104,7 +4105,7 @@ impl Decoder<Arch> for InstDecoder {          Ok(instr)      }      fn decode_into<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(&self, instr: &mut Instruction, words: &mut T) -> Result<(), <Arch as yaxpeax_arch::Arch>::DecodeError> { -        read_instr(self, words, instr)?; +        read_with_annotations(self, words, instr, &mut NullSink)?;          instr.length = words.offset() as u8;          if words.offset() > 15 { @@ -4822,7 +4823,7 @@ impl OperandCodeBuilder {  //   |  //   ---------------------------> read modr/m?  #[repr(u16)] -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)]  enum OperandCode {      Ivs = OperandCodeBuilder::new().special_case(25).bits(),      I_3 = OperandCodeBuilder::new().special_case(27).bits(), @@ -7086,7 +7087,84 @@ fn read_0f3a_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord {      };  } -fn read_instr<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction) -> Result<(), DecodeError> { +#[derive(Clone, Debug, PartialEq, Eq)] +enum InnerDescription { +    RexPrefix(u8), +    SegmentPrefix(Segment), +    Opcode(Opcode), +    OperandCode(OperandCode), +    RegisterNumber(&'static str, u8, RegSpec), +    Misc(&'static str), +    Number(&'static str, i64), +} + +impl InnerDescription { +    fn with_id(self, id: u32) -> FieldDescription { +        FieldDescription { +            desc: self, +            id, +        } +    } +} + +impl fmt::Display for InnerDescription { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        match self { +            InnerDescription::RexPrefix(bits) => { +                write!(f, "rex prefix: {}{}{}{}", +                    if bits & 0x8 != 0 { "w" } else { "-" }, +                    if bits & 0x4 != 0 { "r" } else { "-" }, +                    if bits & 0x2 != 0 { "x" } else { "-" }, +                    if bits & 0x1 != 0 { "b" } else { "-" }, +                ) +            } +            InnerDescription::SegmentPrefix(segment) => { +                write!(f, "segment override: {}", segment) +            } +            InnerDescription::Misc(text) => { +                f.write_str(text) +            } +            InnerDescription::Number(text, num) => { +                write!(f, "{}: {:#x}", text, num) +            } +            InnerDescription::Opcode(opc) => { +                write!(f, "opcode `{}`", opc) +            } +            InnerDescription::OperandCode(code) => { +                write!(f, "operand code `{:?}`", code) +            } +            InnerDescription::RegisterNumber(name, num, reg) => { +                write!(f, "`{}` (`{}` selects register number {})", reg, name, num) +            } +        } +    } +} + +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct FieldDescription { +    desc: InnerDescription, +    id: u32, +} + +impl yaxpeax_arch::FieldDescription for FieldDescription { +    fn id(&self) -> u32 { +        self.id +    } +    fn is_separator(&self) -> bool { +        false +    } +} + +impl fmt::Display for FieldDescription { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        fmt::Display::fmt(&self.desc, f) +    } +} + +fn read_with_annotations< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription>, +>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> {      words.mark();      let mut nextb = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;      let mut next_rec = OPCODES[nextb as usize]; @@ -7173,7 +7251,7 @@ fn read_instr<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          unsafe { unreachable_unchecked(); }      }      instruction.prefixes = prefixes; -    read_operands(decoder, words, instruction, record.1)?; +    read_operands(decoder, words, instruction, record.1, sink)?;      instruction.length = words.offset() as u8;      if instruction.length > 15 {          return Err(DecodeError::TooLong); @@ -7225,7 +7303,10 @@ fn read_instr<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          OperandCode::ModRM_0x8f_Ev => 30   */ -fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, operand_code: OperandCode) -> Result<(), DecodeError> { +fn read_operands< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription> +>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, operand_code: OperandCode, sink: &mut S) -> Result<(), DecodeError> {      instruction.operands[0] = OperandSpec::RegRRR;      instruction.operand_count = 2;      let operand_code = OperandCodeBuilder::from_bits(operand_code as u16); @@ -7725,14 +7806,17 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe          },          _ => {          let operand_code: OperandCode = unsafe { core::mem::transmute(operand_code.bits()) }; -            unlikely_operands(decoder, words, instruction, operand_code, mem_oper)?; +            unlikely_operands(decoder, words, instruction, operand_code, mem_oper, sink)?;          }      };      }      Ok(())  } -fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, operand_code: OperandCode, mem_oper: OperandSpec) -> Result<(), DecodeError> { +fn unlikely_operands< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription> +>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, operand_code: OperandCode, mem_oper: OperandSpec, sink: &mut S) -> Result<(), DecodeError> {      match operand_code {          OperandCode::G_E_mm_Ib => {              let modrm = read_modrm(words)?; @@ -7840,7 +7924,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      // prefixes and then vex is invalid! reject it.                      return Err(DecodeError::InvalidPrefixes);                  } else { -                    vex::three_byte_vex(words, modrm, instruction)?; +                    vex::three_byte_vex(words, modrm, instruction, sink)?;                      if decoder != &InstDecoder::default() {                          decoder.revise_instruction(instruction)?; @@ -7867,7 +7951,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      // prefixes and then vex is invalid! reject it.                      return Err(DecodeError::InvalidPrefixes);                  } else { -                    vex::two_byte_vex(words, modrm, instruction)?; +                    vex::two_byte_vex(words, modrm, instruction, sink)?;                      if decoder != &InstDecoder::default() {                          decoder.revise_instruction(instruction)?; @@ -8725,7 +8809,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }          }          OperandCode::ModRM_0xf30f38dc => { -            read_operands(decoder, words, instruction, OperandCode::G_E_xmm)?; +            read_operands(decoder, words, instruction, OperandCode::G_E_xmm, sink)?;              if let OperandSpec::RegMMM = instruction.operands[1] {                  instruction.opcode = Opcode::LOADIWKEY;              } else { @@ -8734,7 +8818,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }          }          OperandCode::ModRM_0xf30f38dd => { -            read_operands(decoder, words, instruction, OperandCode::G_E_xmm)?; +            read_operands(decoder, words, instruction, OperandCode::G_E_xmm, sink)?;              if let OperandSpec::RegMMM = instruction.operands[1] {                  return Err(DecodeError::InvalidOperand);              } else { @@ -8743,7 +8827,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }          }          OperandCode::ModRM_0xf30f38de => { -            read_operands(decoder, words, instruction, OperandCode::G_E_xmm)?; +            read_operands(decoder, words, instruction, OperandCode::G_E_xmm, sink)?;              if let OperandSpec::RegMMM = instruction.operands[1] {                  return Err(DecodeError::InvalidOperand);              } else { @@ -8752,7 +8836,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }          }          OperandCode::ModRM_0xf30f38df => { -            read_operands(decoder, words, instruction, OperandCode::G_E_xmm)?; +            read_operands(decoder, words, instruction, OperandCode::G_E_xmm, sink)?;              if let OperandSpec::RegMMM = instruction.operands[1] {                  return Err(DecodeError::InvalidOperand);              } else { @@ -8762,13 +8846,13 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          OperandCode::ModRM_0xf30f38fa => {              instruction.opcode = Opcode::ENCODEKEY128; -            read_operands(decoder, words, instruction, OperandCode::G_U_xmm)?; +            read_operands(decoder, words, instruction, OperandCode::G_U_xmm, sink)?;              instruction.regs[0].bank = RegisterBank::D;              instruction.regs[1].bank = RegisterBank::D;          }          OperandCode::ModRM_0xf30f38fb => {              instruction.opcode = Opcode::ENCODEKEY256; -            read_operands(decoder, words, instruction, OperandCode::G_U_xmm)?; +            read_operands(decoder, words, instruction, OperandCode::G_U_xmm, sink)?;              instruction.regs[0].bank = RegisterBank::D;              instruction.regs[1].bank = RegisterBank::D;          } @@ -10072,7 +10156,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  if prefixes.lock() || prefixes.operand_size() || prefixes.rep_any() {                      return Err(DecodeError::InvalidPrefixes);                  } else { -                    evex::read_evex(words, instruction, Some(modrm))?; +                    evex::read_evex(words, instruction, Some(modrm), sink)?;                  }              }          } diff --git a/src/protected_mode/vex.rs b/src/protected_mode/vex.rs index 54c9d23..202aeb3 100644 --- a/src/protected_mode/vex.rs +++ b/src/protected_mode/vex.rs @@ -1,8 +1,10 @@  use yaxpeax_arch::Reader; +use yaxpeax_arch::DescriptionSink;  use crate::protected_mode::Arch;  use crate::protected_mode::OperandSpec;  use crate::protected_mode::DecodeError; +use crate::protected_mode::FieldDescription;  use crate::protected_mode::RegSpec;  use crate::protected_mode::RegisterBank;  use crate::protected_mode::Instruction; @@ -97,7 +99,10 @@ enum VEXOperandCode {  }  #[inline(never)] -pub(crate) fn three_byte_vex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, vex_byte_one: u8, instruction: &mut Instruction) -> Result<(), DecodeError> { +pub(crate) fn three_byte_vex< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription>, +>(words: &mut T, vex_byte_one: u8, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> {      let vex_byte_two = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;      let p = vex_byte_two & 0x03;      let p = match p { @@ -129,7 +134,10 @@ pub(crate) fn three_byte_vex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <A      Ok(())  } -pub(crate) fn two_byte_vex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, vex_byte: u8, instruction: &mut Instruction) -> Result<(), DecodeError> { +pub(crate) fn two_byte_vex< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription>, +>(words: &mut T, vex_byte: u8, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> {      let p = vex_byte & 0x03;      let p = match p {          0x00 => VEXOpcodePrefix::None, diff --git a/src/real_mode/mod.rs b/src/real_mode/mod.rs index 7f3ad42..0af0b0b 100644 --- a/src/real_mode/mod.rs +++ b/src/real_mode/mod.rs @@ -13,6 +13,7 @@ use core::cmp::PartialEq;  use core::hint::unreachable_unchecked;  use yaxpeax_arch::{AddressDiff, Decoder, Reader, LengthedInstruction}; +use yaxpeax_arch::{AnnotatingDecoder, DescriptionSink, NullSink};  use yaxpeax_arch::{DecodeError as ArchDecodeError};  use core::fmt; @@ -4090,7 +4091,7 @@ impl Default for InstDecoder {  impl Decoder<Arch> for InstDecoder {      fn decode<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(&self, words: &mut T) -> Result<Instruction, <Arch as yaxpeax_arch::Arch>::DecodeError> {          let mut instr = Instruction::invalid(); -        read_instr(self, words, &mut instr)?; +        read_with_annotations(self, words, &mut instr, &mut NullSink)?;          instr.length = words.offset() as u8;          if words.offset() > 15 { @@ -4104,7 +4105,7 @@ impl Decoder<Arch> for InstDecoder {          Ok(instr)      }      fn decode_into<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(&self, instr: &mut Instruction, words: &mut T) -> Result<(), <Arch as yaxpeax_arch::Arch>::DecodeError> { -        read_instr(self, words, instr)?; +        read_with_annotations(self, words, instr, &mut NullSink)?;          instr.length = words.offset() as u8;          if words.offset() > 15 { @@ -4822,7 +4823,7 @@ impl OperandCodeBuilder {  //   |  //   ---------------------------> read modr/m?  #[repr(u16)] -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)]  enum OperandCode {      Ivs = OperandCodeBuilder::new().special_case(25).bits(),      I_3 = OperandCodeBuilder::new().special_case(27).bits(), @@ -7087,7 +7088,84 @@ fn read_0f3a_opcode(opcode: u8, prefixes: &mut Prefixes) -> OpcodeRecord {      };  } -fn read_instr<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction) -> Result<(), DecodeError> { +#[derive(Clone, Debug, PartialEq, Eq)] +enum InnerDescription { +    RexPrefix(u8), +    SegmentPrefix(Segment), +    Opcode(Opcode), +    OperandCode(OperandCode), +    RegisterNumber(&'static str, u8, RegSpec), +    Misc(&'static str), +    Number(&'static str, i64), +} + +impl InnerDescription { +    fn with_id(self, id: u32) -> FieldDescription { +        FieldDescription { +            desc: self, +            id, +        } +    } +} + +impl fmt::Display for InnerDescription { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        match self { +            InnerDescription::RexPrefix(bits) => { +                write!(f, "rex prefix: {}{}{}{}", +                    if bits & 0x8 != 0 { "w" } else { "-" }, +                    if bits & 0x4 != 0 { "r" } else { "-" }, +                    if bits & 0x2 != 0 { "x" } else { "-" }, +                    if bits & 0x1 != 0 { "b" } else { "-" }, +                ) +            } +            InnerDescription::SegmentPrefix(segment) => { +                write!(f, "segment override: {}", segment) +            } +            InnerDescription::Misc(text) => { +                f.write_str(text) +            } +            InnerDescription::Number(text, num) => { +                write!(f, "{}: {:#x}", text, num) +            } +            InnerDescription::Opcode(opc) => { +                write!(f, "opcode `{}`", opc) +            } +            InnerDescription::OperandCode(code) => { +                write!(f, "operand code `{:?}`", code) +            } +            InnerDescription::RegisterNumber(name, num, reg) => { +                write!(f, "`{}` (`{}` selects register number {})", reg, name, num) +            } +        } +    } +} + +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct FieldDescription { +    desc: InnerDescription, +    id: u32, +} + +impl yaxpeax_arch::FieldDescription for FieldDescription { +    fn id(&self) -> u32 { +        self.id +    } +    fn is_separator(&self) -> bool { +        false +    } +} + +impl fmt::Display for FieldDescription { +    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +        fmt::Display::fmt(&self.desc, f) +    } +} + +fn read_with_annotations< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription>, +>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> {      words.mark();      let mut nextb = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;      let mut next_rec = OPCODES[nextb as usize]; @@ -7174,7 +7252,7 @@ fn read_instr<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          unsafe { unreachable_unchecked(); }      }      instruction.prefixes = prefixes; -    read_operands(decoder, words, instruction, record.1)?; +    read_operands(decoder, words, instruction, record.1, sink)?;      instruction.length = words.offset() as u8;      if instruction.length > 15 {          return Err(DecodeError::TooLong); @@ -7226,7 +7304,10 @@ fn read_instr<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_          OperandCode::ModRM_0x8f_Ev => 30   */ -fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, operand_code: OperandCode) -> Result<(), DecodeError> { +fn read_operands< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription> +>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, operand_code: OperandCode, sink: &mut S) -> Result<(), DecodeError> {      instruction.operands[0] = OperandSpec::RegRRR;      instruction.operand_count = 2;      let operand_code = OperandCodeBuilder::from_bits(operand_code as u16); @@ -7725,14 +7806,17 @@ fn read_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpe          },          _ => {          let operand_code: OperandCode = unsafe { core::mem::transmute(operand_code.bits()) }; -            unlikely_operands(decoder, words, instruction, operand_code, mem_oper)?; +            unlikely_operands(decoder, words, instruction, operand_code, mem_oper, sink)?;          }      };      }      Ok(())  } -fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, operand_code: OperandCode, mem_oper: OperandSpec) -> Result<(), DecodeError> { +fn unlikely_operands< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription> +>(decoder: &InstDecoder, words: &mut T, instruction: &mut Instruction, operand_code: OperandCode, mem_oper: OperandSpec, sink: &mut S) -> Result<(), DecodeError> {      match operand_code {          OperandCode::G_E_mm_Ib => {              let modrm = read_modrm(words)?; @@ -7841,7 +7925,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      // prefixes and then vex is invalid! reject it.                      return Err(DecodeError::InvalidPrefixes);                  } else { -                    vex::three_byte_vex(words, modrm, instruction)?; +                    vex::three_byte_vex(words, modrm, instruction, sink)?;                      if decoder != &InstDecoder::default() {                          decoder.revise_instruction(instruction)?; @@ -7868,7 +7952,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                      // prefixes and then vex is invalid! reject it.                      return Err(DecodeError::InvalidPrefixes);                  } else { -                    vex::two_byte_vex(words, modrm, instruction)?; +                    vex::two_byte_vex(words, modrm, instruction, sink)?;                      if decoder != &InstDecoder::default() {                          decoder.revise_instruction(instruction)?; @@ -8729,7 +8813,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }          }          OperandCode::ModRM_0xf30f38dc => { -            read_operands(decoder, words, instruction, OperandCode::G_E_xmm)?; +            read_operands(decoder, words, instruction, OperandCode::G_E_xmm, sink)?;              if let OperandSpec::RegMMM = instruction.operands[1] {                  instruction.opcode = Opcode::LOADIWKEY;              } else { @@ -8738,7 +8822,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }          }          OperandCode::ModRM_0xf30f38dd => { -            read_operands(decoder, words, instruction, OperandCode::G_E_xmm)?; +            read_operands(decoder, words, instruction, OperandCode::G_E_xmm, sink)?;              if let OperandSpec::RegMMM = instruction.operands[1] {                  return Err(DecodeError::InvalidOperand);              } else { @@ -8747,7 +8831,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }          }          OperandCode::ModRM_0xf30f38de => { -            read_operands(decoder, words, instruction, OperandCode::G_E_xmm)?; +            read_operands(decoder, words, instruction, OperandCode::G_E_xmm, sink)?;              if let OperandSpec::RegMMM = instruction.operands[1] {                  return Err(DecodeError::InvalidOperand);              } else { @@ -8756,7 +8840,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y              }          }          OperandCode::ModRM_0xf30f38df => { -            read_operands(decoder, words, instruction, OperandCode::G_E_xmm)?; +            read_operands(decoder, words, instruction, OperandCode::G_E_xmm, sink)?;              if let OperandSpec::RegMMM = instruction.operands[1] {                  return Err(DecodeError::InvalidOperand);              } else { @@ -8766,13 +8850,13 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y          }          OperandCode::ModRM_0xf30f38fa => {              instruction.opcode = Opcode::ENCODEKEY128; -            read_operands(decoder, words, instruction, OperandCode::G_U_xmm)?; +            read_operands(decoder, words, instruction, OperandCode::G_U_xmm, sink)?;              instruction.regs[0].bank = RegisterBank::D;              instruction.regs[1].bank = RegisterBank::D;          }          OperandCode::ModRM_0xf30f38fb => {              instruction.opcode = Opcode::ENCODEKEY256; -            read_operands(decoder, words, instruction, OperandCode::G_U_xmm)?; +            read_operands(decoder, words, instruction, OperandCode::G_U_xmm, sink)?;              instruction.regs[0].bank = RegisterBank::D;              instruction.regs[1].bank = RegisterBank::D;          } @@ -10075,7 +10159,7 @@ fn unlikely_operands<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as y                  if prefixes.lock() || prefixes.operand_size() || prefixes.rep_any() {                      return Err(DecodeError::InvalidPrefixes);                  } else { -                    evex::read_evex(words, instruction, Some(modrm))?; +                    evex::read_evex(words, instruction, Some(modrm), sink)?;                  }              }          } diff --git a/src/real_mode/vex.rs b/src/real_mode/vex.rs index 56eb48f..41102d9 100644 --- a/src/real_mode/vex.rs +++ b/src/real_mode/vex.rs @@ -1,8 +1,10 @@  use yaxpeax_arch::Reader; +use yaxpeax_arch::DescriptionSink;  use crate::real_mode::Arch;  use crate::real_mode::OperandSpec;  use crate::real_mode::DecodeError; +use crate::real_mode::FieldDescription;  use crate::real_mode::RegSpec;  use crate::real_mode::RegisterBank;  use crate::real_mode::Instruction; @@ -97,7 +99,10 @@ enum VEXOperandCode {  }  #[inline(never)] -pub(crate) fn three_byte_vex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, vex_byte_one: u8, instruction: &mut Instruction) -> Result<(), DecodeError> { +pub(crate) fn three_byte_vex< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription>, +>(words: &mut T, vex_byte_one: u8, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> {      let vex_byte_two = words.next().ok().ok_or(DecodeError::ExhaustedInput)?;      let p = vex_byte_two & 0x03;      let p = match p { @@ -129,7 +134,10 @@ pub(crate) fn three_byte_vex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <A      Ok(())  } -pub(crate) fn two_byte_vex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, vex_byte: u8, instruction: &mut Instruction) -> Result<(), DecodeError> { +pub(crate) fn two_byte_vex< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription>, +>(words: &mut T, vex_byte: u8, instruction: &mut Instruction, sink: &mut S) -> Result<(), DecodeError> {      let p = vex_byte & 0x03;      let p = match p {          0x00 => VEXOpcodePrefix::None, diff --git a/src/shared/evex.in b/src/shared/evex.in index 8a1e4eb..2f1cbe5 100644 --- a/src/shared/evex.in +++ b/src/shared/evex.in @@ -1,11 +1,17 @@  use super::OperandSpec; +use super::FieldDescription; + +use yaxpeax_arch::DescriptionSink;  // `evex_byte_one` is an option because the caller *may* have already read it,  // but may have not. `long_mode` can decide immediately that `0x62` should be read  // as an `EVEX` instruction, but for other modes we can only make this  // determination when reading a `bound`'s `modrm` byte.  #[inline(never)] -pub(crate) fn read_evex<T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>>(words: &mut T, instruction: &mut Instruction, evex_byte_one: Option<u8>) -> Result<(), DecodeError> { +pub(crate) fn read_evex< +    T: Reader<<Arch as yaxpeax_arch::Arch>::Address, <Arch as yaxpeax_arch::Arch>::Word>, +    S: DescriptionSink<FieldDescription>, +>(words: &mut T, instruction: &mut Instruction, evex_byte_one: Option<u8>, sink: &mut S) -> Result<(), DecodeError> {      let evex_byte_one = if let Some(b) = evex_byte_one {        b      } else { | 
