aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2019-03-10 17:40:38 -0700
committeriximeow <me@iximeow.net>2020-01-12 16:10:13 -0800
commitfc87dfea6408d378cd5a417f4a5a4dd448df5358 (patch)
treee7351097baecbb4ab532e5e05b4b4356f6eceb90
parent5697c17af9ba0854f37edc5970ec862c446002d2 (diff)
add build configs and tweak lifetimes to match yaxpeax-arch adjustments
-rw-r--r--Cargo.toml8
-rw-r--r--build.rs4
-rw-r--r--src/lib.rs64
-rw-r--r--test/bench.rs163
4 files changed, 207 insertions, 32 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 51c590e..27c7f43 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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");
+}
diff --git a/src/lib.rs b/src/lib.rs
index 5a5f34d..20b77e9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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]");
+//}