diff options
author | iximeow <me@iximeow.net> | 2019-03-20 14:55:53 -0700 |
---|---|---|
committer | iximeow <me@iximeow.net> | 2020-01-12 16:10:13 -0800 |
commit | 0adc1ba0b88e4afd55bb080bb8134a56f302ead7 (patch) | |
tree | 387e6e9d3a0df3acd84c2a8cc5cf4a3dbed9528f /src/lib.rs | |
parent | 9e5fd6103b8213376b83b2bc427fc15a1213ba5a (diff) |
factor out display for x86, implement colorization... a bit
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 444 |
1 files changed, 3 insertions, 441 deletions
@@ -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 { |