diff options
| author | iximeow <me@iximeow.net> | 2019-03-10 17:40:38 -0700 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2020-01-12 16:10:13 -0800 | 
| commit | fc87dfea6408d378cd5a417f4a5a4dd448df5358 (patch) | |
| tree | e7351097baecbb4ab532e5e05b4b4356f6eceb90 | |
| parent | 5697c17af9ba0854f37edc5970ec862c446002d2 (diff) | |
add build configs and tweak lifetimes to match yaxpeax-arch adjustments
| -rw-r--r-- | Cargo.toml | 8 | ||||
| -rw-r--r-- | build.rs | 4 | ||||
| -rw-r--r-- | src/lib.rs | 64 | ||||
| -rw-r--r-- | test/bench.rs | 163 | 
4 files changed, 207 insertions, 32 deletions
| @@ -24,6 +24,14 @@ path = "test/test.rs"  name = "bench"  path = "test/bench.rs" +[profile.bench] +opt-level = 3 +lto = true + +[profile.release] +opt-level = 3 +lto = true +  [features]  default = [] diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..c6bc953 --- /dev/null +++ b/build.rs @@ -0,0 +1,4 @@ +fn main() { +    println!("cargo:rustc-link-search=/usr/lib/"); +    println!("cargo:rustc-link-lib=capstone"); +} @@ -636,10 +636,10 @@ const BITWISE_OPCODE_MAP: [Opcode; 8] = [      Opcode::SAR  ]; -fn read_opcode_0f_map<'a, T: Iterator<Item=&'a u8>>(bytes_iter: &mut T, instruction: &mut Instruction, prefixes: Prefixes) -> Result<OperandCode, String> { +fn read_opcode_0f_map<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mut Instruction, prefixes: Prefixes) -> Result<OperandCode, String> {      match bytes_iter.next() {          Some(b) => { -            match *b { +            match b {                  0x1f => {                      instruction.prefixes = prefixes;                      instruction.opcode = Opcode::NOP; @@ -836,7 +836,7 @@ fn read_opcode_0f_map<'a, T: Iterator<Item=&'a u8>>(bytes_iter: &mut T, instruct      }  } -fn read_opcode<'a, T: Iterator<Item=&'a u8>>(bytes_iter: &mut T, instruction: &mut Instruction) -> Result<OperandCode, String> { +fn read_opcode<T: Iterator<Item=u8>>(bytes_iter: &mut T, instruction: &mut Instruction) -> Result<OperandCode, String> {      use std::hint::unreachable_unchecked;  //    use std::intrinsics::unlikely;      let mut reading = true; @@ -845,7 +845,7 @@ fn read_opcode<'a, T: Iterator<Item=&'a u8>>(bytes_iter: &mut T, instruction: &m      loop {          match bytes_iter.next() {              Some(b) => { -                match *b { +                match b {                      x if x < 0x40 => {                          if x % 8 > 5 { // unsafe { unlikely(x % 8 > 5) } {                              // for x86_32 this is push/pop prefixes and 0x0f escape @@ -1346,7 +1346,7 @@ fn read_opcode<'a, T: Iterator<Item=&'a u8>>(bytes_iter: &mut T, instruction: &m      }  } -fn read_E<'a, T: Iterator<Item=&'a u8>>(bytes_iter: &mut T, prefixes: &Prefixes, m: u8, modbits: u8, width: u8, result: &mut Operand) -> Result<(), String> { +fn read_E<T: Iterator<Item=u8>>(bytes_iter: &mut T, prefixes: &Prefixes, m: u8, modbits: u8, width: u8, result: &mut Operand) -> Result<(), String> {      let addr_width = if prefixes.address_size() { 4 } else { 8 };      if modbits == 0b11 {          *result = Operand::Register(RegSpec::gp_from_parts(m, prefixes.rex().b(), width, prefixes.rex().present())) @@ -1357,7 +1357,7 @@ fn read_E<'a, T: Iterator<Item=&'a u8>>(bytes_iter: &mut T, prefixes: &Prefixes,              disp as i32          );      } else if m == 4 { -        let sibbyte = *bytes_iter.next().unwrap(); +        let sibbyte = bytes_iter.next().unwrap();          let (ss, index, base) = octets_of(sibbyte);  //            println!("scale: {:b}, index: {:b}, base: {:b}", ss, index, base); @@ -1456,7 +1456,7 @@ fn read_E<'a, T: Iterator<Item=&'a u8>>(bytes_iter: &mut T, prefixes: &Prefixes,  }  #[inline] -fn read_operands<'a, T: Iterator<Item=&'a u8>>( +fn read_operands<T: Iterator<Item=u8>>(      bytes_iter: &mut T,      instruction: &mut Instruction,      operand_code: OperandCode @@ -1512,7 +1512,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(              let opwidth = 1;              // TODO: ...              let modrm = bytes_iter.next().unwrap(); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0]) {                  Ok(()) => { @@ -1529,7 +1529,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(              let opwidth = 1;              // TODO: ...              let modrm = bytes_iter.next().unwrap(); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0]) {                  Ok(()) => { @@ -1546,7 +1546,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              // TODO: ...              let modrm = bytes_iter.next().unwrap(); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0]) {                  Ok(()) => { @@ -1563,7 +1563,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(              let opwidth = 1;              // TODO: ...              let modrm = bytes_iter.next().unwrap(); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0]) {                  Ok(()) => { @@ -1582,7 +1582,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              // TODO: ...              let modrm = bytes_iter.next().unwrap(); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0]) {                  Ok(e_op) => { @@ -1602,7 +1602,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(              let opwidth = 1;              // TODO: ...              let modrm = bytes_iter.next().unwrap(); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0]) {                  Ok(()) => { @@ -1618,7 +1618,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              // TODO: ...              let modrm = bytes_iter.next().unwrap(); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0]) {                  Ok(()) => { @@ -1633,7 +1633,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(          OperandCode::ModRM_0xf6 => {              let opwidth = 1;              let modrm = bytes_iter.next().unwrap(); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0]) {                  Ok(()) => { },                  Err(reason) => { return Err(reason); } @@ -1675,7 +1675,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(          OperandCode::ModRM_0xf7 => {              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              let modrm = bytes_iter.next().unwrap(); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0]) {                  Ok(()) => { },                  Err(reason) => { return Err(reason); } @@ -1719,7 +1719,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(              let opwidth = 1;              // TODO: ...              let modrm = bytes_iter.next().unwrap(); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0]) {                  Ok(()) => { @@ -1744,7 +1744,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              // TODO: ...              let modrm = bytes_iter.next().unwrap(); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0]) {                  Ok(()) => { @@ -1769,7 +1769,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              // TODO: ...              let modrm = bytes_iter.next().unwrap(); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0]) {                  Ok(()) => { @@ -1783,7 +1783,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(              let opwidth = 1;              // TODO: ...              let modrm = bytes_iter.next().unwrap(); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0]) {                  Ok(()) => { @@ -1798,7 +1798,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              // TODO: ...              let modrm = bytes_iter.next().unwrap(); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0]) {                  Ok(()) => { @@ -1813,7 +1813,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(              let opwidth = 1;              // TODO: ...              let modrm = bytes_iter.next().unwrap(); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[1]) {                  Ok(()) => { @@ -1828,7 +1828,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              // TODO: ...              let modrm = bytes_iter.next().unwrap(); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[1]) {                  Ok(()) => { @@ -1843,7 +1843,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              // TODO: ...              let modrm = bytes_iter.next().unwrap(); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, 2, &mut instruction.operands[1]) {                  Ok(()) => { @@ -1859,7 +1859,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes);              // TODO: ...              let modrm = bytes_iter.next().unwrap(); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);  //                println!("mod_bits: {:2b}, r: {:3b}, m: {:3b}", mod_bits, r, m);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[1]) { @@ -1934,7 +1934,7 @@ fn read_operands<'a, T: Iterator<Item=&'a u8>>(              let modrm = bytes_iter.next().unwrap();              let opwidth = imm_width_from_prefixes_64(SizeCode::vqp, &instruction.prefixes); -            let (mod_bits, r, m) = octets_of(*modrm); +            let (mod_bits, r, m) = octets_of(modrm);              match read_E(bytes_iter, &instruction.prefixes, m, mod_bits, opwidth, &mut instruction.operands[0]) {                  Ok(()) => { @@ -1996,7 +1996,7 @@ fn width_to_gp_reg_bank(width: u8, rex: bool) -> RegisterBank {      }  } -pub fn decode_one<'a, 'b, T: IntoIterator<Item=&'a u8>>(bytes: T, instr: &'b mut Instruction) -> Option<()> { +pub fn decode_one<'b, T: IntoIterator<Item=u8>>(bytes: T, instr: &'b mut Instruction) -> Option<()> {      let mut bytes_iter = bytes.into_iter();      match read_opcode(&mut bytes_iter, instr) {          Ok(operand_code) => { @@ -2022,21 +2022,21 @@ pub fn decode_one<'a, 'b, T: IntoIterator<Item=&'a u8>>(bytes: T, instr: &'b mut  }  #[inline] -fn read_num<'a, T: Iterator<Item=&'a u8>>(bytes: &mut T, width: u8) -> u64 { +fn read_num<T: Iterator<Item=u8>>(bytes: &mut T, width: u8) -> u64 {      let mut result = 0u64;      let mut idx = 0;      loop {          if idx == width {              return result;          } -        let byte = *bytes.next().unwrap(); +        let byte = bytes.next().unwrap();          result |= (byte as u64) << (idx * 8);          idx += 1;      }  }  #[inline] -fn read_imm_ivq<'a, T: Iterator<Item=&'a u8>>(bytes: &mut T, width: u8) -> Result<Operand, String> { +fn read_imm_ivq<T: Iterator<Item=u8>>(bytes: &mut T, width: u8) -> Result<Operand, String> {      match width {          2 => {              Ok(Operand::ImmediateU16(read_num(bytes, 2) as u16)) @@ -2054,7 +2054,7 @@ fn read_imm_ivq<'a, T: Iterator<Item=&'a u8>>(bytes: &mut T, width: u8) -> Resul  }  #[inline] -fn read_imm_signed<'a, T: Iterator<Item=&'a u8>>(bytes: &mut T, num_width: u8, extend_to: u8) -> Result<Operand, String> { +fn read_imm_signed<T: Iterator<Item=u8>>(bytes: &mut T, num_width: u8, extend_to: u8) -> Result<Operand, String> {      let num = match num_width {          1 => read_num(bytes, 1) as i8 as i64,          2 => read_num(bytes, 2) as i16 as i64, @@ -2073,7 +2073,7 @@ fn read_imm_signed<'a, T: Iterator<Item=&'a u8>>(bytes: &mut T, num_width: u8, e  }  #[inline] -fn read_imm_unsigned<'a, T: Iterator<Item=&'a u8>>(bytes: &mut T, width: u8) -> Result<Operand, String> { +fn read_imm_unsigned<T: Iterator<Item=u8>>(bytes: &mut T, width: u8) -> Result<Operand, String> {      match width {          1 => {              Ok(Operand::ImmediateU8(read_num(bytes, 1) as u8)) diff --git a/test/bench.rs b/test/bench.rs new file mode 100644 index 0000000..1d7414d --- /dev/null +++ b/test/bench.rs @@ -0,0 +1,163 @@ +#![feature(test)] + +extern crate test; +extern crate yaxpeax_x86; + +use std::ffi::c_void; + +use std::io::Write; + +use test::Bencher; + +use yaxpeax_x86::{Instruction, Opcode, decode_one}; + +fn decode(bytes: &[u8]) -> Option<Instruction> { +    let mut instr = Instruction::invalid(); +    match decode_one(bytes, &mut instr) { +        Some(()) => Some(instr), +        None => None +    } +} + +#[bench] +fn bench_102000_instrs(b: &mut Bencher) { +    b.iter(|| { +        for i in (0..3000) { +            test::black_box(do_decode_swathe()); +        } +    }) +} + +#[cfg(feature = "capstone_bench")] +#[bench] +fn bench_102000_intrs_capstone(b: &mut Bencher) { +    let handle = get_cs_handle(); +//    panic!("Allocating.."); +    let mut instr: *mut c_void = unsafe { cs_malloc(handle) }; +//    panic!("Allocated..."); +    b.iter(|| { +        for i in (0..3000) { +            test::black_box(do_capstone_decode_swathe(handle, instr)); +        } +    }) +} + +const decode_data: [u8; 130] = [ +    0x48, 0xc7, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00, +    0x48, 0x89, 0x44, 0x24, 0x08, +    0x48, 0x89, 0x43, 0x18, +    0x48, 0xc7, 0x43, 0x10, 0x00, 0x00, 0x00, 0x00, +    0x49, 0x89, 0x4e, 0x08, +    0x48, 0x8b, 0x32, +    0x49, 0x89, 0x46, 0x10, +    0x4d, 0x0f, 0x43, 0xec, 0x49, +    0x0f, 0xb6, 0x06, +    0x0f, 0xb7, 0x06, +    0x66, 0x41, 0x50, +    0x66, 0x41, 0x31, 0xc0, +    0x66, 0x41, 0x32, 0xc0, +    0x40, 0x32, 0xc5, +    0x73, 0x31, +    0x72, 0x5a, +    0x0f, 0x86, 0x8b, 0x01, 0x00, 0x00, +    0x74, 0x47, +    0xff, 0x15, 0x7e, 0x72, 0x24, 0x00, +    0xc3, +    0x48, 0x3d, 0x01, 0xf0, 0xff, 0xff, +    0x3d, 0x01, 0xf0, 0xff, 0xff, +    0x48, 0x83, 0xf8, 0xff, +    0x48, 0x39, 0xc6, +    0x48, 0x8d, 0xa4, 0xc7, 0x20, 0x00, 0x00, 0x12, +    0x33, 0xc0, +    0x48, 0x8d, 0x53, 0x08, +    0x31, 0xc9, +    0x48, 0x29, 0xc8, +    0x48, 0x03, 0x0b, +    0x5b, +    0x41, 0x5e, +    0x48, 0x8d, 0x0c, 0x12, +    0xf6, 0xc2, 0x18 +]; + +fn do_decode_swathe() { +    let mut buf = [0u8; 128]; +    let mut iter = decode_data.iter(); +    let mut result = yaxpeax_x86::Instruction::invalid(); +    loop { +        match yaxpeax_x86::decode_one(&mut iter, &mut result) { +            Some(_) => { +                #[cfg(feature = "capstone_bench")] +                test::black_box(write!(&mut buf[..], "{}", result)); +                test::black_box(&result); +            }, +            None => { +                println!("done."); +                break; +            } +        } +    } +} + +#[cfg(feature = "capstone_bench")] +extern "C" { +    pub fn cs_open(arch: u32, mode: u32, handle: *mut usize) -> usize; +} + +#[cfg(feature = "capstone_bench")] +extern "C" { +    pub fn cs_malloc(handle: usize) -> *mut c_void; +} + +#[cfg(feature = "capstone_bench")] +extern "C" { +    pub fn cs_disasm_iter( +        arch: usize, +        code: *mut *const u8, +        size: *mut usize, +        address: *mut u64, +        insn: *mut c_void +    ) -> bool; +} + +#[cfg(feature = "capstone_bench")] +fn get_cs_handle() -> usize { +    let mut handle: usize = 0; +    let res = unsafe { cs_open(3, 4, &mut handle as *mut usize) }; +    handle +} + +#[cfg(feature = "capstone_bench")] +fn get_instr(handle: usize) -> *mut c_void { +    unsafe { cs_malloc(handle) as *mut c_void } +} + +#[cfg(feature = "capstone_bench")] +fn do_capstone_decode_swathe(cs: usize, instr: *mut c_void) { +    unsafe { +        let mut code = &decode_data as *const u8; +        let mut len = decode_data.len(); +        let mut addr = 0u64; +        loop { +            let result = cs_disasm_iter( +                cs, +                &mut code as *mut *const u8, +                &mut len as *mut usize, +                &mut addr as *mut u64, +                instr +            ); +            //panic!("at least one succeeded"); +            if result == false { +                return; +            } +        } +    } +} + +//#[bench] +//#[ignore] +// VEX prefixes are not supported at the moment, in any form +//fn test_avx() { +//    assert_eq!(&format!("{}", decode( +//        &[0xc5, 0xf8, 0x10, 0x00] +//    ).unwrap()), "vmovups xmm0, xmmword [rax]"); +//} | 
