aboutsummaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs444
1 files changed, 3 insertions, 441 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 6c406ac..cead4df 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,13 +1,15 @@
extern crate yaxpeax_arch;
extern crate termion;
+mod display;
+
use termion::color;
use std::fmt;
use std::hint::unreachable_unchecked;
-use yaxpeax_arch::{Arch, Colorize, ColorSettings, Decodable, LengthedInstruction};
+use yaxpeax_arch::{Arch, ColorSettings, Decodable, LengthedInstruction};
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct RegSpec {
@@ -51,32 +53,6 @@ impl RegSpec {
}
}
-impl fmt::Display for RegSpec {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let name = match self.bank {
- RegisterBank::Q => {
- ["rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"][self.num as usize]
- },
- RegisterBank::D => {
- ["eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"][self.num as usize]
- },
- RegisterBank::W => {
- ["ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w"][self.num as usize]
- },
- RegisterBank::B => {
- ["al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"][self.num as usize]
- },
- RegisterBank::rB => {
- ["al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b"][self.num as usize]
- },
- RegisterBank::EIP => { "eip" },
- RegisterBank::RIP => { "rip" },
- _ => panic!("unnamable register")
- };
- write!(f, "{}", name)
- }
-}
-
#[allow(non_camel_case_types)]
enum SizeCode {
b,
@@ -85,64 +61,6 @@ enum SizeCode {
vqp
}
-impl fmt::Display for Operand {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- self.colorize(None, fmt)
- }
-}
-
-impl <T: std::fmt::Write> Colorize<T> for Operand {
- fn colorize(&self, colors: Option<&ColorSettings>, f: &mut T) -> std::fmt::Result {
- match self {
- &Operand::ImmediateI16(imm) => write!(f, "0x{:x}", imm),
- &Operand::ImmediateU16(imm) => write!(f, "0x{:x}", imm),
- &Operand::ImmediateU32(imm) => write!(f, "0x{:x}", imm),
- &Operand::ImmediateI32(imm) => write!(f, "0x{:x}", imm),
- &Operand::ImmediateU64(imm) => write!(f, "0x{:x}", imm),
- &Operand::ImmediateI64(imm) => write!(f, "0x{:x}", imm),
- &Operand::Register(ref spec) => write!(f, "{}", spec),
- &Operand::ImmediateI8(imm) => write!(f, "0x{:x}", imm),
- &Operand::ImmediateU8(imm) => write!(f, "0x{:x}", imm),
- &Operand::DisplacementU32(imm) => write!(f, "[0x{:x}]", imm),
- &Operand::DisplacementU64(imm) => write!(f, "[0x{:x}]", imm),
- &Operand::RegDisp(ref spec, ref disp) => {
- if *disp < 0 {
- write!(f, "[{} - 0x{:x}]", spec, -disp)
- } else {
- write!(f, "[{} + 0x{:x}]", spec, disp)
- }
- },
- &Operand::RegDeref(ref spec) => write!(f, "[{}]", spec),
- &Operand::RegScale(ref spec, scale) => write!(f, "[{} * {}]", spec, scale),
- &Operand::RegScaleDisp(ref spec, scale, disp) => {
- write!(f, "[{} * {} + 0x{:x}]", spec, scale, disp)
- },
- &Operand::RegIndexBase(ref base, ref index) => {
- write!(f, "[{} + {}]", base, index)
- }
- &Operand::RegIndexBaseDisp(ref base, ref index, disp) => {
- write!(f, "[{} + {} + 0x{:x}]", base, index, disp)
- },
- &Operand::RegIndexBaseScale(ref base, ref index, scale) => {
- if scale == 1 {
- write!(f, "[{} + {}]", base, index)
- } else {
- write!(f, "[{} + {} * {}]", base, index, scale)
- }
- }
- &Operand::RegIndexBaseScaleDisp(ref base, ref index, scale, disp) => {
- if scale == 1 {
- write!(f, "[{} + {} + {:#x}]", base, index, disp)
- } else {
- write!(f, "[{} + {} * {} + {:#x}]", base, index, scale, disp)
- }
- },
- &Operand::Nothing => { Ok(()) },
- &Operand::Many(_) => { panic!("many not covered"); }
- }
- }
-}
-
#[derive(Clone, Debug)]
pub enum Operand {
ImmediateI8(i8),
@@ -181,123 +99,6 @@ pub enum Segment {
CS, DS, ES, FS, GS, SS
}
-impl fmt::Display for Opcode {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self {
- &Opcode::INC => write!(f, "{}", "inc"),
- &Opcode::DEC => write!(f, "{}", "dec"),
- &Opcode::HLT => write!(f, "{}", "hlt"),
- &Opcode::SBB => write!(f, "{}", "sbb"),
- &Opcode::AND => write!(f, "{}", "and"),
- &Opcode::XOR => write!(f, "{}", "xor"),
- &Opcode::OR => write!(f, "{}", "or"),
- &Opcode::PUSH => write!(f, "{}", "push"),
- &Opcode::POP => write!(f, "{}", "pop"),
- &Opcode::LEA => write!(f, "{}", "lea"),
- &Opcode::NOP => write!(f, "{}", "nop"),
- &Opcode::XCHG => write!(f, "{}", "xchg"),
- &Opcode::POPF => write!(f, "{}", "popf"),
- &Opcode::ADD => write!(f, "{}", "add"),
- &Opcode::ADC => write!(f, "{}", "adc"),
- &Opcode::SUB => write!(f, "{}", "sub"),
- &Opcode::INT => write!(f, "{}", "int"),
- &Opcode::INTO => write!(f, "{}", "into"),
- &Opcode::IRET => write!(f, "{}", "iret"),
- &Opcode::RETF => write!(f, "{}", "retf"),
- &Opcode::ENTER => write!(f, "{}", "enter"),
- &Opcode::LEAVE => write!(f, "{}", "leave"),
- &Opcode::MOV => write!(f, "{}", "mov"),
- &Opcode::RETURN => write!(f, "{}", "ret"),
- &Opcode::PUSHF => write!(f, "{}", "pushf"),
- &Opcode::WAIT => write!(f, "{}", "wait"),
- &Opcode::CBW => write!(f, "{}", "cbw"),
- &Opcode::CDW => write!(f, "{}", "cdw"),
- &Opcode::LODS => write!(f, "{}", "lods"),
- &Opcode::STOS => write!(f, "{}", "stos"),
- &Opcode::LAHF => write!(f, "{}", "lahf"),
- &Opcode::SAHF => write!(f, "{}", "sahf"),
- &Opcode::CMPS => write!(f, "{}", "cmps"),
- &Opcode::SCAS => write!(f, "{}", "scas"),
- &Opcode::MOVS => write!(f, "{}", "movs"),
- &Opcode::TEST => write!(f, "{}", "test"),
- &Opcode::CMP => write!(f, "{}", "cmp"),
- &Opcode::INS => write!(f, "{}", "ins"),
- &Opcode::OUTS => write!(f, "{}", "outs"),
- &Opcode::IMUL => write!(f, "{}", "imul"),
- &Opcode::JO => write!(f, "{}", "jo"),
- &Opcode::JNO => write!(f, "{}", "jno"),
- &Opcode::JB => write!(f, "{}", "jb"),
- &Opcode::JNB => write!(f, "{}", "jnb"),
- &Opcode::JZ => write!(f, "{}", "jz"),
- &Opcode::JNZ => write!(f, "{}", "jnz"),
- &Opcode::JA => write!(f, "{}", "ja"),
- &Opcode::JNA => write!(f, "{}", "jna"),
- &Opcode::JS => write!(f, "{}", "js"),
- &Opcode::JNS => write!(f, "{}", "jns"),
- &Opcode::JP => write!(f, "{}", "jp"),
- &Opcode::JNP => write!(f, "{}", "jnp"),
- &Opcode::JL => write!(f, "{}", "jl"),
- &Opcode::JGE => write!(f, "{}", "jge"),
- &Opcode::JLE => write!(f, "{}", "jle"),
- &Opcode::JG => write!(f, "{}", "jg"),
- &Opcode::CALL => write!(f, "{}", "call"),
- &Opcode::JMP => write!(f, "{}", "jmp"),
- &Opcode::CALLF => write!(f, "{}", "callf"),
- &Opcode::JMPF => write!(f, "{}", "jmpf"),
- &Opcode::SAR => write!(f, "{}", "sar"),
- &Opcode::SAL => write!(f, "{}", "sal"),
- &Opcode::SHR => write!(f, "{}", "shr"),
- &Opcode::SHL => write!(f, "{}", "shl"),
- &Opcode::RCR => write!(f, "{}", "rcr"),
- &Opcode::RCL => write!(f, "{}", "rcl"),
- &Opcode::ROR => write!(f, "{}", "ror"),
- &Opcode::ROL => write!(f, "{}", "rol"),
- &Opcode::CMOVA => write!(f, "{}", "cmova"),
- &Opcode::CMOVB => write!(f, "{}", "cmovb"),
- &Opcode::CMOVG => write!(f, "{}", "cmovg"),
- &Opcode::CMOVGE => write!(f, "{}", "cmovge"),
- &Opcode::CMOVL => write!(f, "{}", "cmovl"),
- &Opcode::CMOVLE => write!(f, "{}", "cmovle"),
- &Opcode::CMOVNA => write!(f, "{}", "cmovna"),
- &Opcode::CMOVNB => write!(f, "{}", "cmovnb"),
- &Opcode::CMOVNO => write!(f, "{}", "cmovno"),
- &Opcode::CMOVNP => write!(f, "{}", "cmovnp"),
- &Opcode::CMOVNS => write!(f, "{}", "cmovns"),
- &Opcode::CMOVNZ => write!(f, "{}", "cmovnz"),
- &Opcode::CMOVO => write!(f, "{}", "cmovo"),
- &Opcode::CMOVP => write!(f, "{}", "cmovp"),
- &Opcode::CMOVS => write!(f, "{}", "cmovs"),
- &Opcode::CMOVZ => write!(f, "{}", "cmovz"),
- &Opcode::NEG => write!(f, "{}", "neg"),
- &Opcode::NOT => write!(f, "{}", "not"),
- &Opcode::MUL => write!(f, "{}", "mul"),
- &Opcode::DIV => write!(f, "{}", "div"),
- &Opcode::IDIV => write!(f, "{}", "idiv"),
- &Opcode::CMPXCHG => write!(f, "{}", "cmpxchg"),
- &Opcode::MOVZX_b => write!(f, "{}", "movzx"),
- &Opcode::MOVZX_w => write!(f, "{}", "movzx"),
- &Opcode::MOVSX => write!(f, "{}", "movsx"),
- &Opcode::SETO => write!(f, "{}", "seto"),
- &Opcode::SETNO => write!(f, "{}", "setno"),
- &Opcode::SETB => write!(f, "{}", "setb"),
- &Opcode::SETAE => write!(f, "{}", "setae"),
- &Opcode::SETZ => write!(f, "{}", "setz"),
- &Opcode::SETNZ => write!(f, "{}", "setnz"),
- &Opcode::SETBE => write!(f, "{}", "setbe"),
- &Opcode::SETA => write!(f, "{}", "seta"),
- &Opcode::SETS => write!(f, "{}", "sets"),
- &Opcode::SETNS => write!(f, "{}", "setns"),
- &Opcode::SETP => write!(f, "{}", "setp"),
- &Opcode::SETNP => write!(f, "{}", "setnp"),
- &Opcode::SETL => write!(f, "{}", "setl"),
- &Opcode::SETGE => write!(f, "{}", "setge"),
- &Opcode::SETLE => write!(f, "{}", "setle"),
- &Opcode::SETG => write!(f, "{}", "setg"),
- &Opcode::Invalid => write!(f, "{}", "invalid")
- }
- }
-}
-
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Opcode {
@@ -566,245 +367,6 @@ impl PrefixRex {
}
}
-fn color_for(opcode: Opcode, colors: &ColorSettings) -> &'static color::Fg<&'static color::Color> {
- match opcode {
- Opcode::DIV |
- Opcode::IDIV |
- Opcode::MUL |
- Opcode::NEG |
- Opcode::NOT |
- Opcode::SAR |
- Opcode::SAL |
- Opcode::SHR |
- Opcode::SHL |
- Opcode::RCR |
- Opcode::RCL |
- Opcode::ROR |
- Opcode::ROL |
- Opcode::INC |
- Opcode::DEC |
- Opcode::SBB |
- Opcode::AND |
- Opcode::XOR |
- Opcode::OR |
- Opcode::LEA |
- Opcode::ADD |
- Opcode::ADC |
- Opcode::SUB |
- Opcode::IMUL |
- Opcode::PUSH |
- Opcode::POP |
- Opcode::NOP |
- Opcode::XCHG |
- Opcode::POPF |
- Opcode::ENTER |
- Opcode::LEAVE |
- Opcode::PUSHF |
- Opcode::WAIT |
- Opcode::CMPS |
- Opcode::SCAS |
- Opcode::TEST |
- Opcode::CMP |
-
- /* Control flow */
- Opcode::HLT |
- Opcode::CALL |
- Opcode::CALLF |
- Opcode::JMP |
- Opcode::JMPF |
- Opcode::INT |
- Opcode::INTO |
- Opcode::IRET |
- Opcode::RETF |
- Opcode::RETURN |
- Opcode::JO |
- Opcode::JNO |
- Opcode::JB |
- Opcode::JNB |
- Opcode::JZ |
- Opcode::JNZ |
- Opcode::JA |
- Opcode::JNA |
- Opcode::JS |
- Opcode::JNS |
- Opcode::JP |
- Opcode::JNP |
- Opcode::JL |
- Opcode::JGE |
- Opcode::JLE |
- Opcode::JG |
-
- /* Data transfer */
- Opcode::MOV |
- Opcode::CBW |
- Opcode::CDW |
- Opcode::LODS |
- Opcode::STOS |
- Opcode::LAHF |
- Opcode::SAHF |
- Opcode::MOVS |
- Opcode::INS |
- Opcode::OUTS |
- Opcode::MOVZX_b |
- Opcode::MOVZX_w |
- Opcode::MOVSX |
- Opcode::CMOVA |
- Opcode::CMOVB |
- Opcode::CMOVG |
- Opcode::CMOVGE |
- Opcode::CMOVL |
- Opcode::CMOVLE |
- Opcode::CMOVNA |
- Opcode::CMOVNB |
- Opcode::CMOVNO |
- Opcode::CMOVNP |
- Opcode::CMOVNS |
- Opcode::CMOVNZ |
- Opcode::CMOVO |
- Opcode::CMOVP |
- Opcode::CMOVS |
- Opcode::CMOVZ |
-
- Opcode::CMPXCHG |
- Opcode::SETO |
- Opcode::SETNO |
- Opcode::SETB |
- Opcode::SETAE |
- Opcode::SETZ |
- Opcode::SETNZ |
- Opcode::SETBE |
- Opcode::SETA |
- Opcode::SETS |
- Opcode::SETNS |
- Opcode::SETP |
- Opcode::SETNP |
- Opcode::SETL |
- Opcode::SETGE |
- Opcode::SETLE |
- Opcode::SETG |
-
- Opcode::Invalid => {
- &color::Fg(&color::Red)
- }
- }
-}
-
-impl fmt::Display for Instruction {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- self.colorize(None, fmt)
- }
-}
-
-/*
- * Can't implement this as accepting a formatter because rust
- * doesn't let me build one outside println! or write! or whatever.
- *
- * can't write this as an intermediate struct because i refuse to copy
- * all data into the struct, and having a function producing a struct with
- * some lifetimes gets really hairy if it's from a trait - same GAT kind
- * of nonsense as i saw with ContextRead, because someone could hold onto
- * the dang intermediate struct forever.
- *
- * 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>, f: &mut T) -> std::fmt::Result {
- if self.prefixes.lock {
- write!(f, "lock ")?;
- }
- colors.map(|c| { write!(f, "{}{}{}", color_for(self.opcode, c), self.opcode, color::Fg(&color::Reset as &color::Color)) })
- .unwrap_or_else(|| { write!(f, "{}", self.opcode) })?;
- /* For when contextualization is a thing we can do?
- match self.0.opers.as_ref().and_then(|xs| xs[0].as_ref()) {
- Some(s) => { write!(f, " {}", s)?; },
- None => {
- */
- match self.operands[0] {
- Operand::Nothing => {
- return Ok(());
- },
- ref x @ _ => {
- write!(f, " ")?;
- x.colorize(colors, f)?;
- }
- }
- /*
- }
- }*/;
- match self.opcode {
- Opcode::MOVZX_b => {
- /*
- match self.0.opers.as_ref().and_then(|xs| xs[1].as_ref()) {
- Some(s) => { write!(f, ", {}", s) }
- None => {
- */
- match &self.operands[1] {
- &Operand::Nothing => {
- return Ok(());
- },
- x @ &Operand::Register(_) => {
- write!(f, ", ")?;
- x.colorize(colors, f)
- }
- x @ _ => {
- write!(f, ", byte ")?;
- x.colorize(colors, f)
- }
- }
- /*
- }
- }
- */
- },
- Opcode::MOVZX_w => {
- /*
- match self.0.opers.as_ref().and_then(|xs| xs[1].as_ref()) {
- Some(s) => { write!(f, ", {}", s) }
- None => {
- */
- match &self.operands[1] {
- &Operand::Nothing => {
- return Ok(());
- },
- x @ &Operand::Register(_) => {
- write!(f, ", ")?;
- x.colorize(colors, f)
- }
- x @ _ => {
- write!(f, ", word ")?;
- x.colorize(colors, f)
- }
- }
- /*
- }
- }
- */
- },
- _ => {
- /*
- match self.0.opers.as_ref().and_then(|xs| xs[1].as_ref()) {
- Some(s) => { write!(f, ", {}", s) }
- None => {
- */
- match &self.operands[1] {
- &Operand::Nothing => {
- return Ok(());
- },
- x @ _ => {
- write!(f, ", ")?;
- x.colorize(colors, f)
- }
- }
- /*
- }
- }
- */
- }
- }
- }
-}
-
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug)]
pub enum OperandCode {