mirror of
https://github.com/bitdefender/bddisasm.git
synced 2025-01-03 11:50:55 +00:00
Updates Rust binding to the latest version.
Fixed build in disasmtool_lix.
This commit is contained in:
parent
fe6a937f51
commit
70db095765
7
bindings/rsbddisasm/bddisasm-sys/CHANGELOG.md
Normal file
7
bindings/rsbddisasm/bddisasm-sys/CHANGELOG.md
Normal file
@ -0,0 +1,7 @@
|
||||
# bddisasm-sys changelog
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Changed
|
||||
|
||||
- the crate is now a `no_std` crate (this adds a dependency on [cty](https://crates.io/crates/cty))
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bddisasm-sys"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
authors = ["Cristi Anichitei <ianichitei@bitdefender.com>"]
|
||||
edition = "2018"
|
||||
links = "bddisasm"
|
||||
@ -12,7 +12,7 @@ documentation = "https://docs.rs/bddisasm-sys"
|
||||
description = """
|
||||
Bindings to bddisasm instruction decoder library
|
||||
"""
|
||||
categories = ["external-ffi-bindings", "hardware-support"]
|
||||
categories = ["external-ffi-bindings", "hardware-support", "no_std"]
|
||||
keywords = ["disassembler", "decoder", "x86", "amd64", "x86_64"]
|
||||
|
||||
[lib]
|
||||
@ -20,6 +20,7 @@ name = "bddisasm_sys"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dependencies]
|
||||
cty = "0.2.2"
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = "0.59.1"
|
||||
|
@ -1,9 +1,13 @@
|
||||
# bddisasm-sys
|
||||
|
||||
Rust bindings for [bddisasm](https://github.com/bitdefender/bddisasm).
|
||||
`no_std` Rust bindings for [bddisasm](https://github.com/bitdefender/bddisasm).
|
||||
|
||||
See [bddisasm](https://crates.io/crates/bddisasm) if you're looking for a Rust wrapper for these bindings.
|
||||
|
||||
## Requirements
|
||||
|
||||
[bindgen](https://crates.io/crates/bindgen) is used to generate the bindings at build time. Because of this, users need to have `clang` installed. Check the [bindgen documentation](https://rust-lang.github.io/rust-bindgen/requirements.html) for more information.
|
||||
|
||||
## Notes
|
||||
|
||||
While this crate is `no_std`, the `bddisasm` library it links against depends on a C library because it needs `vsnprintf` and `memset`. It is possible to [work around this limitation](https://github.com/bitdefender/bddisasm#nd_vsnprintf_s-and-nd_memset), but this is not currently done for these bindings.
|
||||
|
@ -11,6 +11,7 @@ fn main() {
|
||||
cc::Build::new()
|
||||
.file("csrc/bddisasm/bddisasm.c")
|
||||
.file("csrc/bddisasm/bdformat.c")
|
||||
.file("csrc/bddisasm/bdhelpers.c")
|
||||
.file("csrc/bddisasm/crt.c")
|
||||
.include("csrc/bddisasm/include")
|
||||
.include("csrc/inc")
|
||||
@ -24,6 +25,8 @@ fn main() {
|
||||
.allowlist_type("ND.*")
|
||||
.allowlist_var("ND.*")
|
||||
.rustified_enum(".*")
|
||||
.ctypes_prefix("cty")
|
||||
.use_core()
|
||||
.impl_debug(true)
|
||||
.generate_comments(false)
|
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
|
||||
|
@ -11,6 +11,7 @@
|
||||
//! [bindgen](https://crates.io/crates/bindgen) is used to generate the bindings at build time. Because of this, users
|
||||
//! need to have `clang` installed.
|
||||
//! Check the [bindgen documentation](https://rust-lang.github.io/rust-bindgen/requirements.html) for more information.
|
||||
#![cfg_attr(not(test), no_std)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
17
bindings/rsbddisasm/bddisasm/CHANGELOG.md
Normal file
17
bindings/rsbddisasm/bddisasm/CHANGELOG.md
Normal file
@ -0,0 +1,17 @@
|
||||
# bddisasm changelog
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
- implement `Decoder::decode_next_with_offset`
|
||||
- implement ``Decoder::decode_next_with_ip`
|
||||
- `OperandLookup` struct which makes working with operands easier
|
||||
- re-export `bddisasm_sys` as `ffi`
|
||||
- re-export commonly used items
|
||||
- Implement `as_*` and `is_*` accessors for the `OpInfo` enum
|
||||
|
||||
### Changed
|
||||
|
||||
- the crate is now a `no_std` crate
|
||||
- public types no longer implement `From` and no longer `panic!` when an unexpected value is encountered
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "bddisasm"
|
||||
version = "0.1.0"
|
||||
version = "0.1.2"
|
||||
authors = ["Cristi Anichitei <ianichitei@bitdefender.com>"]
|
||||
edition = "2018"
|
||||
license = "Apache-2.0"
|
||||
@ -15,3 +15,13 @@ keywords = ["disassembler", "decoder", "x86", "amd64", "x86_64"]
|
||||
|
||||
[dependencies]
|
||||
bddisasm-sys = { version = "0.1.0", path = "../bddisasm-sys" }
|
||||
|
||||
[features]
|
||||
std = []
|
||||
|
||||
[package.metadata."docs.rs"]
|
||||
all-features = true
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow = "1.0"
|
||||
clap = "2.34.0"
|
||||
|
@ -1,11 +1,13 @@
|
||||
# bddisasm
|
||||
# bddisasm x86/x64 instruction decoder
|
||||
|
||||
Rust bindings for the [bddisasm](https://github.com/bitdefender/bddisasm) x86/x64 decoder library, built on top
|
||||
of [bddisasm-sys](https://crates.io/crates/bddisasm-sys).
|
||||
`no_std` Rust bindings for the [bddisasm](https://github.com/bitdefender/bddisasm) x86/x64 decoder library, built
|
||||
on top of [bddisasm-sys](https://crates.io/crates/bddisasm-sys).
|
||||
|
||||
It supports all existing x86 instruction, offering a wide range of information about each one, including:
|
||||
It supports all existing 16-bit, 32-bit and 64-bit instructions, offering a wide range of information about each one,
|
||||
including:
|
||||
|
||||
- operands (implicit and explicit)
|
||||
- implicit operands
|
||||
- explicit operands
|
||||
- access mode for each operand
|
||||
- CPUID feature flags
|
||||
- CPU modes in which an instruction is valid
|
||||
@ -23,8 +25,11 @@ bddisasm = "0.1.0"
|
||||
|
||||
### Decoding one instruction
|
||||
|
||||
```rust
|
||||
use bddisasm::decoded_instruction::{DecodedInstruction, DecodeMode, Mnemonic};
|
||||
Use [`DecodedInstruction::decode`](https://docs.rs/bddisasm/latest/bddisasm/decoded_instruction/struct.DecodedInstruction.html#method.decode)
|
||||
to decode an instruction from a chunk of code.
|
||||
|
||||
```Rust
|
||||
use bddisasm::{DecodedInstruction, DecodeMode, Mnemonic};
|
||||
|
||||
let code = vec![0x31, 0xc0];
|
||||
match DecodedInstruction::decode(&code, DecodeMode::Bits32) {
|
||||
@ -38,8 +43,11 @@ match DecodedInstruction::decode(&code, DecodeMode::Bits32) {
|
||||
|
||||
### Decoding multiple instructions
|
||||
|
||||
```rust
|
||||
use bddisasm::decoder::{Decoder, DecodeMode};
|
||||
Use [`Decoder`](https://docs.rs/bddisasm/latest/bddisasm/decoder/struct.Decoder.html) to decode multiple instructions
|
||||
from a chunk of code.
|
||||
|
||||
```Rust
|
||||
use bddisasm::{Decoder, DecodeMode};
|
||||
|
||||
let code = [
|
||||
// ENCLS
|
||||
@ -70,21 +78,58 @@ the provided input buffer is too small
|
||||
WRMSR
|
||||
```
|
||||
|
||||
Use [`Decoder::decode_next_with_info`](https://docs.rs/bddisasm/latest/bddisasm/decoder/struct.Decoder.html#method.decode_next_with_info)
|
||||
to get information about the offset inside the code chunk at which an instruction was decoded from.
|
||||
|
||||
```Rust
|
||||
use bddisasm::{Decoder, DecodeMode};
|
||||
|
||||
let code = [
|
||||
// ENCLS
|
||||
0x0f, 0x01, 0xcf,
|
||||
// MOV rax, qword ptr [rbx+rcx*4+0x1234]
|
||||
0x48, 0x8b, 0x84, 0x8b, 0x34, 0x12, 0x00, 0x00,
|
||||
// Not a valid instruction
|
||||
0x0f,
|
||||
// WRMSR
|
||||
0x0f, 0x30,
|
||||
];
|
||||
let mut decoder = Decoder::new(&code, DecodeMode::Bits64, 0x1234);
|
||||
|
||||
|
||||
// Keep decoding until there's nothing left to decode
|
||||
while let Some((result, offset, _)) = decoder.decode_next_with_info() {
|
||||
match result {
|
||||
Ok(ins) => println!("{:#x} {}", offset, ins),
|
||||
Err(e) => println!("Error: `{}` at offset {:#x}", e, offset),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This will print:
|
||||
|
||||
```text
|
||||
0x0 ENCLS
|
||||
0x3 MOV rax, qword ptr [rbx+rcx*4+0x1234]
|
||||
Error `the provided input buffer is too small` at offset 0xb
|
||||
0xc WRMSR
|
||||
```
|
||||
|
||||
### Working with instruction operands
|
||||
|
||||
Rich informaion is offered for each type of operand. Bellow is a minimal example that looks at a memory operand.
|
||||
Instruction operands can be analyzed using the [operand](https://docs.rs/bddisasm/latest/bddisasm/operand/index.html)
|
||||
module. Rich informaion is offered for each type of operand. Bellow is a minimal example that looks at a memory operand.
|
||||
|
||||
```rust
|
||||
# use bddisasm::decode_error::DecodeError;
|
||||
# fn test() -> Result<(), DecodeError> {
|
||||
use bddisasm::decoded_instruction::{DecodedInstruction, DecodeMode};
|
||||
use bddisasm::operand::OpInfo;
|
||||
```Rust
|
||||
use bddisasm::{DecodedInstruction, DecodeMode, OpInfo};
|
||||
|
||||
// ` MOV rax, qword ptr [rcx+r15*2]`
|
||||
let code = b"\x4a\x8b\x04\x79";
|
||||
let ins = DecodedInstruction::decode(code, DecodeMode::Bits64).unwrap();
|
||||
|
||||
// Get the operands
|
||||
let operands = ins.operands();
|
||||
|
||||
// Get the second operand which is the source (`[rcx+r15*2]`)
|
||||
let src = operands[1];
|
||||
|
||||
@ -117,8 +162,6 @@ match src.info {
|
||||
},
|
||||
_ => unreachable!(),
|
||||
}
|
||||
# Ok(())
|
||||
# }
|
||||
```
|
||||
|
||||
Will print:
|
||||
@ -131,6 +174,11 @@ Scale: 2
|
||||
No displacement
|
||||
```
|
||||
|
||||
## Requirements
|
||||
## Accessing the raw bindings
|
||||
|
||||
Because [bddisasm-sys](https://crates.io/crates/bddisasm-sys) uses [bindgen](https://crates.io/crates/bindgen) to generate the bindings at build time, users need to have `clang` installed. Check the [bindgen documentation](https://rust-lang.github.io/rust-bindgen/requirements.html) for more information.
|
||||
The raw `bddisasm_sys` bindings are available via the `ffi` re-export.
|
||||
|
||||
## Feature Flags
|
||||
|
||||
- `std` - adds a `std` dependency - the only visible difference when doing this is that [`DecodeError`] implements
|
||||
the `Error` trait
|
||||
|
159
bindings/rsbddisasm/bddisasm/examples/emulator.rs
Normal file
159
bindings/rsbddisasm/bddisasm/examples/emulator.rs
Normal file
@ -0,0 +1,159 @@
|
||||
extern crate bddisasm;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use bddisasm::{DecodeMode, DecodedInstruction, Decoder, Mnemonic, OpRegType, Operand};
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::{App, Arg};
|
||||
|
||||
static ABOUT: &str = "
|
||||
Simple emulator example.
|
||||
Supports only a few 64-bit instructions (MOV, INC, DEC) and operand types (register, and immediate).
|
||||
All registers are initially set to 0.
|
||||
";
|
||||
|
||||
/// Holds the reigster state.
|
||||
#[derive(Debug, Default)]
|
||||
struct Context {
|
||||
/// Registers are in the Intel documented order (RAX, RCX, RDX, etc).
|
||||
regs: [u64; 16],
|
||||
}
|
||||
|
||||
impl Context {
|
||||
/// Emulates a 64-bit instruction.
|
||||
pub fn emulate(&mut self, ins: &DecodedInstruction) -> Result<()> {
|
||||
let operands = ins.operands();
|
||||
|
||||
match ins.mnemonic() {
|
||||
Mnemonic::Mov => {
|
||||
self.set_operand_value(&operands[0], self.get_operand_value(&operands[1])?)?
|
||||
}
|
||||
Mnemonic::Inc => self.set_operand_value(
|
||||
&operands[0],
|
||||
self.get_operand_value(&operands[0])?.wrapping_add(1),
|
||||
)?,
|
||||
Mnemonic::Dec => self.set_operand_value(
|
||||
&operands[0],
|
||||
self.get_operand_value(&operands[0])?.wrapping_sub(1),
|
||||
)?,
|
||||
_ => anyhow::bail!("Unsupported instruction: {}", ins),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_operand_value(&self, op: &Operand) -> Result<u64> {
|
||||
if let Some(reg) = op.info.as_reg() {
|
||||
if reg.kind != OpRegType::Gpr {
|
||||
anyhow::bail!("Unsupported register type: {}", reg.kind)
|
||||
} else {
|
||||
match reg.size {
|
||||
1 => {
|
||||
if reg.is_high8 {
|
||||
// For `AH`, `BH`, etc.
|
||||
Ok((self.regs[reg.index] & 0xFF00) >> 8)
|
||||
} else {
|
||||
Ok(self.regs[reg.index] & 0xFF)
|
||||
}
|
||||
}
|
||||
2 => Ok(self.regs[reg.index] & 0xFFFF),
|
||||
4 => Ok(self.regs[reg.index] & 0xFFFFFFFF),
|
||||
8 => Ok(self.regs[reg.index]),
|
||||
_ => unreachable!("Unexpected GPR size: {}", reg.size),
|
||||
}
|
||||
}
|
||||
} else if let Some(imm) = op.info.as_imm() {
|
||||
Ok(imm)
|
||||
} else {
|
||||
anyhow::bail!("Unsupported operand type: {}", op.info)
|
||||
}
|
||||
}
|
||||
|
||||
fn set_operand_value(&mut self, op: &Operand, value: u64) -> Result<()> {
|
||||
if let Some(reg) = op.info.as_reg() {
|
||||
if reg.kind != OpRegType::Gpr {
|
||||
anyhow::bail!("Unsupported register type: {}", reg.kind)
|
||||
} else {
|
||||
let orig_value = self.regs[reg.index];
|
||||
|
||||
let value = match reg.size {
|
||||
1 => {
|
||||
if reg.is_high8 {
|
||||
let value = value << 8;
|
||||
value | (orig_value & 0xFFFFFFFFFFFF00FF)
|
||||
} else {
|
||||
value | (orig_value & 0xFFFFFFFFFFFFFF00)
|
||||
}
|
||||
}
|
||||
2 => value | (orig_value & 0xFFFFFFFFFFFF0000),
|
||||
4 => {
|
||||
// The upper 32-bits are always set to 0.
|
||||
value & 0xFFFFFFFF
|
||||
}
|
||||
8 => value,
|
||||
_ => unreachable!("Unexpected GPR size: {}", reg.size),
|
||||
};
|
||||
|
||||
self.regs[reg.index] = value;
|
||||
Ok(())
|
||||
}
|
||||
} else {
|
||||
anyhow::bail!("Unsupported operand type: {}", op.info)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Context {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let names = [
|
||||
"RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", " R8", " R9", "R10", "R11",
|
||||
"R12", "R13", "R14", "R15",
|
||||
];
|
||||
|
||||
for (i, name) in names.iter().enumerate() {
|
||||
if let Err(e) = write!(f, "{}: {:#018x} ", name, self.regs[i]) {
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
if (i + 1) % 4 == 0 {
|
||||
if let Err(e) = writeln!(f) {
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let matches = App::new("emulator")
|
||||
.about(ABOUT)
|
||||
.arg(
|
||||
Arg::with_name("INPUT")
|
||||
.short("f")
|
||||
.long("file")
|
||||
.value_name("PATH")
|
||||
.help("Path to the binary file from which to load code")
|
||||
.takes_value(true),
|
||||
)
|
||||
.get_matches();
|
||||
|
||||
let code = std::fs::read(matches.value_of("INPUT").unwrap())?;
|
||||
|
||||
let decoder = Decoder::new(&code, DecodeMode::Bits64, 0);
|
||||
let mut ctx = Context::default();
|
||||
|
||||
for ins in decoder {
|
||||
match ins {
|
||||
Ok(ins) => {
|
||||
ctx.emulate(&ins)?;
|
||||
println!("{}\n{}", ins, ctx);
|
||||
}
|
||||
Err(e) => anyhow::bail!("Failed to decode: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
@ -7,10 +7,10 @@
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```
|
||||
//! # use std::error::Error;
|
||||
//! # use bddisasm::DecodeError;
|
||||
//! #
|
||||
//! # fn main() -> Result<(), Box<dyn Error>> {
|
||||
//! use bddisasm::decoded_instruction::{DecodedInstruction, DecodeMode, Mnemonic, OperandSize};
|
||||
//! # fn main() -> Result<(), DecodeError> {
|
||||
//! use bddisasm::{DecodedInstruction, DecodeMode, Mnemonic};
|
||||
//!
|
||||
//! // `VMXON qword ptr [rax]`
|
||||
//! let ins = DecodedInstruction::decode(&[0xf3, 0x0f, 0xc7, 0x30], DecodeMode::Bits64)?;
|
||||
@ -26,16 +26,21 @@
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
|
||||
extern crate bddisasm_sys as ffi;
|
||||
|
||||
// TODO: maybe use something like the `bitflags` crate and have all these as flags?
|
||||
|
||||
/// Privilege levels (rings) in which an instruction is supported.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct PrivilegeLevel {
|
||||
/// Instruction is valid in ring 0.
|
||||
pub ring0: bool,
|
||||
|
||||
/// Instruction is valid in ring 1.
|
||||
pub ring1: bool,
|
||||
|
||||
/// Instruction is valid in ring 2.
|
||||
pub ring2: bool,
|
||||
|
||||
/// Instruction is valid in ring 3.
|
||||
pub ring3: bool,
|
||||
}
|
||||
|
||||
@ -109,11 +114,11 @@ pub struct CpuModes {
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
impl From<ffi::ND_VALID_MODES> for CpuModes {
|
||||
fn from(raw: ffi::ND_VALID_MODES) -> CpuModes {
|
||||
impl CpuModes {
|
||||
pub(crate) fn from_raw(raw: ffi::ND_VALID_MODES) -> Self {
|
||||
let raw = unsafe { raw.__bindgen_anon_1 };
|
||||
|
||||
CpuModes {
|
||||
Self {
|
||||
privilege_level: PrivilegeLevel {
|
||||
ring0: raw.Ring0() != 0,
|
||||
ring1: raw.Ring1() != 0,
|
||||
|
@ -7,10 +7,10 @@
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```
|
||||
//! # use std::error::Error;
|
||||
//! # use bddisasm::DecodeError;
|
||||
//! #
|
||||
//! # fn test() -> Option<()> {
|
||||
//! use bddisasm::decoded_instruction::{DecodedInstruction, DecodeMode};
|
||||
//! use bddisasm::{DecodedInstruction, DecodeMode};
|
||||
//!
|
||||
//! // `ENCLS`
|
||||
//! let ins = DecodedInstruction::decode(&[0x0f, 0x01, 0xcf], DecodeMode::Bits64).ok()?;
|
||||
@ -25,9 +25,7 @@
|
||||
//! # Some(())
|
||||
//! # }
|
||||
|
||||
extern crate bddisasm_sys as ffi;
|
||||
|
||||
use std::fmt;
|
||||
use core::fmt;
|
||||
|
||||
/// Describes the CPUID leaf, sub-leaf, register & bit that indicate whether an instruction is supported or not.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
|
@ -7,36 +7,20 @@
|
||||
//!
|
||||
//! # Notes
|
||||
//!
|
||||
//! All error codes that can be returned by `bddisasm-sys` are encapsulated in the [DecodeError](DecodeError) enum.
|
||||
//! All error codes that can be returned by `bddisasm-sys` are encapsulated in the [`DecodeError`](DecodeError) enum.
|
||||
//! However, some of these are unlikely to be encountered when using this crate (for example,
|
||||
//! [BufferOverflow](DecodeError::BufferOverflow)) which indicates that a buffer passed to the `bddisasm` C library is
|
||||
//! [`BufferOverflow`](DecodeError::BufferOverflow)) which indicates that a buffer passed to the `bddisasm` C library is
|
||||
//! not large enough.
|
||||
//!
|
||||
//! Other errors, such as [UnknownStatus](DecodeError::UnknownStatus) or
|
||||
//! [UnknownInstruction](DecodeError::UnknownInstruction) are used to indicate that this crate is out of sync with
|
||||
//! `bddisasm-sys`, which also should never happen.
|
||||
|
||||
extern crate bddisasm_sys as ffi;
|
||||
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use core::fmt;
|
||||
|
||||
/// Holds all the possible errors that can be encountered by the decoder.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// If the `std` feature is disabled, [`DecodeError`] does not implement the `Error` trait.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub enum DecodeError {
|
||||
/// The underlying bddisasm status is not known. The inner value holds the status as it was returned by bddisasm.
|
||||
///
|
||||
/// This usually means that this library is out of sync with bddisasm-sys and is not aware that a new error status
|
||||
/// was added.
|
||||
UnknownStatus(u32),
|
||||
|
||||
/// The instruction class returned by bddisasm is not known. The inner value holds the instruction class as it was
|
||||
/// returned by bddisasm.
|
||||
///
|
||||
/// This usually means that this library is out of sync with bddisasm-sys and is not aware that a new instruction
|
||||
/// class was added.
|
||||
UnknownInstruction(u32),
|
||||
|
||||
/// The provided input buffer is too small and does not contain a valid instruction.
|
||||
BufferTooSmall,
|
||||
|
||||
@ -134,16 +118,12 @@ pub enum DecodeError {
|
||||
BufferOverflow,
|
||||
|
||||
/// Internal library error.
|
||||
InternalError,
|
||||
InternalError(u64),
|
||||
}
|
||||
|
||||
impl fmt::Display for DecodeError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
DecodeError::UnknownStatus(value) => write!(f, "unknown status: {:#x}", value),
|
||||
DecodeError::UnknownInstruction(value) => {
|
||||
write!(f, "unknown instruction: {:#x}", value)
|
||||
}
|
||||
DecodeError::BufferTooSmall => write!(f, "the provided input buffer is too small"),
|
||||
DecodeError::InvalidEncoding => write!(f, "invalid encoding/instruction"),
|
||||
DecodeError::InstructionTooLong => {
|
||||
@ -156,7 +136,9 @@ impl fmt::Display for DecodeError {
|
||||
DecodeError::XopWithPrefix => write!(f, "XOP is present, but also a legacy prefix"),
|
||||
DecodeError::VexWithPrefix => write!(f, "VEX is present, but also a legacy prefix"),
|
||||
DecodeError::EvexWithPrefix => write!(f, "EVEX is present, but also a legacy prefix"),
|
||||
DecodeError::InvalidEncodingInMode => write!(f, "invalid encoding/instruction"),
|
||||
DecodeError::InvalidEncodingInMode => {
|
||||
write!(f, "invalid encoding/instruction in the given mode")
|
||||
}
|
||||
DecodeError::BadLockPrefix => write!(f, "invalid usage of LOCK"),
|
||||
DecodeError::CsLoad => write!(f, "an attempt to load the CS register"),
|
||||
DecodeError::Prefix66NotAccepted => write!(f, "0x66 prefix is not accepted"),
|
||||
@ -199,12 +181,13 @@ impl fmt::Display for DecodeError {
|
||||
DecodeError::BufferOverflow => {
|
||||
write!(f, "not enough space is available to format instruction")
|
||||
}
|
||||
DecodeError::InternalError => write!(f, "internal error"),
|
||||
DecodeError::InternalError(e) => write!(f, "internal error: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for DecodeError {}
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for DecodeError {}
|
||||
|
||||
pub(crate) fn status_to_error(status: ffi::NDSTATUS) -> Result<(), DecodeError> {
|
||||
if status == ffi::ND_STATUS_SUCCESS || status == ffi::ND_STATUS_HINT_OPERAND_NOT_USED {
|
||||
@ -249,8 +232,8 @@ pub(crate) fn status_to_error(status: ffi::NDSTATUS) -> Result<(), DecodeError>
|
||||
ffi::ND_STATUS_INVALID_PARAMETER => Err(DecodeError::InvalidParameter),
|
||||
ffi::ND_STATUS_INVALID_INSTRUX => Err(DecodeError::InvalidInstrux),
|
||||
ffi::ND_STATUS_BUFFER_OVERFLOW => Err(DecodeError::BufferOverflow),
|
||||
ffi::ND_STATUS_INTERNAL_ERROR => Err(DecodeError::InternalError),
|
||||
_ => Err(DecodeError::UnknownStatus(status)),
|
||||
ffi::ND_STATUS_INTERNAL_ERROR => Err(DecodeError::InternalError(0)),
|
||||
_ => panic!("Unexpected status: {:#x}", status),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,14 +4,10 @@
|
||||
*/
|
||||
//! Decodes instructions.
|
||||
|
||||
extern crate bddisasm_sys as ffi;
|
||||
|
||||
pub use crate::decode_error::DecodeError;
|
||||
pub use crate::decoded_instruction::{DecodeMode, DecodeResult, DecodedInstruction};
|
||||
pub use crate::mnemonic::Mnemonic;
|
||||
use crate::decoded_instruction::{DecodeMode, DecodeResult, DecodedInstruction};
|
||||
|
||||
/// Decodes instructions.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct Decoder<'a> {
|
||||
code: &'a [u8],
|
||||
ip: u64,
|
||||
@ -61,10 +57,10 @@ impl<'a> Decoder<'a> {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use std::error::Error;
|
||||
/// # use bddisasm::DecodeError;
|
||||
/// #
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// use bddisasm::decoder::{Decoder, DecodeMode};
|
||||
/// # fn main() -> Result<(), DecodeError> {
|
||||
/// use bddisasm::{Decoder, DecodeMode};
|
||||
///
|
||||
/// let mut decoder = Decoder::new(&[0x51, 0x53], DecodeMode::Bits32, 0);
|
||||
///
|
||||
@ -103,16 +99,16 @@ impl<'a> Decoder<'a> {
|
||||
|
||||
/// Attempts to decode the next instruction from the given code chunk.
|
||||
///
|
||||
/// Behaves like [decode_next](Decoder::decode_next), but in addition to the [DecodeResult](DecodeResult) it will
|
||||
/// also return the offset from which decoding was attempted, as well as the corresponding instruction pointer.
|
||||
/// Behaves like [`decode_next`](Decoder::decode_next), but in addition to the [`DecodeResult`](DecodeResult) it
|
||||
/// will also return the offset from which decoding was attempted, as well as the corresponding instruction pointer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use std::error::Error;
|
||||
/// # use bddisasm::DecodeError;
|
||||
/// #
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// use bddisasm::decoder::{Decoder, DecodeMode};
|
||||
/// # fn main() -> Result<(), DecodeError> {
|
||||
/// use bddisasm::{Decoder, DecodeMode};
|
||||
///
|
||||
/// let mut decoder = Decoder::new(&[0x51, 0x53], DecodeMode::Bits32, 0x1000);
|
||||
///
|
||||
@ -128,12 +124,81 @@ impl<'a> Decoder<'a> {
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn decode_next_with_info(&mut self) -> Option<(DecodeResult, usize, u64)> {
|
||||
let offset = self.offset;
|
||||
let ip = self.ip;
|
||||
|
||||
self.decode_next().map(|res| (res, offset, ip))
|
||||
}
|
||||
|
||||
/// Attempts to decode the next instruction from the given code chunk.
|
||||
///
|
||||
/// Behaves like [`decode_next`](Decoder::decode_next), but in addition to the [`DecodeResult`](DecodeResult) it
|
||||
/// will also return the offset from which decoding was attempted.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use bddisasm::DecodeError;
|
||||
/// #
|
||||
/// # fn main() -> Result<(), DecodeError> {
|
||||
/// use bddisasm::{Decoder, DecodeMode};
|
||||
///
|
||||
/// let mut decoder = Decoder::new(&[0x51, 0x53], DecodeMode::Bits32, 0x1000);
|
||||
///
|
||||
/// // As long as we have something to decode
|
||||
/// while let Some((result, offset)) = decoder.decode_next_with_offset() {
|
||||
/// // Check if the decoding succeeded
|
||||
/// match result {
|
||||
/// Ok(instruction) => println!("{} at offset {:#x}", instruction, offset),
|
||||
/// Err(e) => println!("Unable to decode at offset {:#x}: {}", offset, e),
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn decode_next_with_offset(&mut self) -> Option<(DecodeResult, usize)> {
|
||||
let offset = self.offset;
|
||||
|
||||
self.decode_next().map(|res| (res, offset))
|
||||
}
|
||||
|
||||
/// Attempts to decode the next instruction from the given code chunk.
|
||||
///
|
||||
/// Behaves like [`decode_next`](Decoder::decode_next), but in addition to the [`DecodeResult`](DecodeResult) it
|
||||
/// will also return the corresponding instruction pointer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use bddisasm::DecodeError;
|
||||
/// #
|
||||
/// # fn main() -> Result<(), DecodeError> {
|
||||
/// use bddisasm::{Decoder, DecodeMode};
|
||||
///
|
||||
/// let mut decoder = Decoder::new(&[0x51, 0x53], DecodeMode::Bits32, 0x1000);
|
||||
///
|
||||
/// // As long as we have something to decode
|
||||
/// while let Some((result, ip)) = decoder.decode_next_with_ip() {
|
||||
/// // Check if the decoding succeeded
|
||||
/// match result {
|
||||
/// Ok(instruction) => println!("{:#x} {}", ip, instruction),
|
||||
/// Err(e) => println!("Unable to decode: {}", e),
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn decode_next_with_ip(&mut self) -> Option<(DecodeResult, u64)> {
|
||||
let ip = self.ip;
|
||||
|
||||
self.decode_next().map(|res| (res, ip))
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Decoder<'_> {
|
||||
@ -145,11 +210,12 @@ impl Iterator for Decoder<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::iter::FusedIterator for Decoder<'_> {}
|
||||
impl core::iter::FusedIterator for Decoder<'_> {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::*;
|
||||
|
||||
#[test]
|
||||
fn decode_next() {
|
||||
|
@ -4,7 +4,7 @@
|
||||
*/
|
||||
//! Offers information about how an instructions accesses the FPU status registers.
|
||||
|
||||
extern crate bddisasm_sys as ffi;
|
||||
use super::decode_error::DecodeError;
|
||||
|
||||
/// The mode in which a FPU status flag is accessed.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
@ -19,15 +19,16 @@ pub enum FpuFlagsAccess {
|
||||
Undefined,
|
||||
}
|
||||
|
||||
impl From<u8> for FpuFlagsAccess {
|
||||
fn from(value: u8) -> FpuFlagsAccess {
|
||||
let value = value as u32;
|
||||
#[doc(hidden)]
|
||||
impl FpuFlagsAccess {
|
||||
pub(crate) fn from_raw(value: u8) -> Result<Self, DecodeError> {
|
||||
let value = u32::from(value);
|
||||
match value {
|
||||
ffi::ND_FPU_FLAG_SET_0 => FpuFlagsAccess::Cleared,
|
||||
ffi::ND_FPU_FLAG_SET_1 => FpuFlagsAccess::Set,
|
||||
ffi::ND_FPU_FLAG_MODIFIED => FpuFlagsAccess::Modified,
|
||||
ffi::ND_FPU_FLAG_UNDEFINED => FpuFlagsAccess::Undefined,
|
||||
_ => panic!("Unexpected FPU flag access: {}", value),
|
||||
ffi::ND_FPU_FLAG_SET_0 => Ok(FpuFlagsAccess::Cleared),
|
||||
ffi::ND_FPU_FLAG_SET_1 => Ok(FpuFlagsAccess::Set),
|
||||
ffi::ND_FPU_FLAG_MODIFIED => Ok(FpuFlagsAccess::Modified),
|
||||
ffi::ND_FPU_FLAG_UNDEFINED => Ok(FpuFlagsAccess::Undefined),
|
||||
_ => Err(DecodeError::InternalError(value.into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -46,13 +47,13 @@ pub struct FpuFlags {
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
impl From<ffi::ND_FPU_FLAGS> for FpuFlags {
|
||||
fn from(flags: ffi::ND_FPU_FLAGS) -> FpuFlags {
|
||||
FpuFlags {
|
||||
c0: FpuFlagsAccess::from(flags.C0()),
|
||||
c1: FpuFlagsAccess::from(flags.C1()),
|
||||
c2: FpuFlagsAccess::from(flags.C2()),
|
||||
c3: FpuFlagsAccess::from(flags.C3()),
|
||||
}
|
||||
impl FpuFlags {
|
||||
pub(crate) fn from_raw(flags: ffi::ND_FPU_FLAGS) -> Result<Self, DecodeError> {
|
||||
Ok(Self {
|
||||
c0: FpuFlagsAccess::from_raw(flags.C0())?,
|
||||
c1: FpuFlagsAccess::from_raw(flags.C1())?,
|
||||
c2: FpuFlagsAccess::from_raw(flags.C2())?,
|
||||
c3: FpuFlagsAccess::from_raw(flags.C3())?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,8 @@
|
||||
*/
|
||||
//! Instruction categories.
|
||||
|
||||
extern crate bddisasm_sys as ffi;
|
||||
|
||||
use super::decode_error;
|
||||
use std::convert::TryFrom;
|
||||
use super::decode_error::DecodeError;
|
||||
use core::convert::TryFrom;
|
||||
|
||||
/// Instruction category.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
@ -120,13 +118,11 @@ pub enum Category {
|
||||
|
||||
#[doc(hidden)]
|
||||
impl TryFrom<ffi::ND_INS_CATEGORY> for Category {
|
||||
type Error = decode_error::DecodeError;
|
||||
type Error = DecodeError;
|
||||
|
||||
fn try_from(value: ffi::ND_INS_CATEGORY) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
ffi::_ND_INS_TYPE::ND_CAT_INVALID => {
|
||||
Err(decode_error::DecodeError::UnknownInstruction(value as u32))
|
||||
}
|
||||
ffi::_ND_INS_TYPE::ND_CAT_INVALID => Err(DecodeError::InternalError(value as u64)),
|
||||
ffi::_ND_INS_TYPE::ND_CAT_3DNOW => Ok(Category::I3dnow),
|
||||
ffi::_ND_INS_TYPE::ND_CAT_AES => Ok(Category::Aes),
|
||||
ffi::_ND_INS_TYPE::ND_CAT_AESKL => Ok(Category::Aeskl),
|
||||
|
@ -4,10 +4,8 @@
|
||||
*/
|
||||
//! Instruction sets.
|
||||
|
||||
extern crate bddisasm_sys as ffi;
|
||||
|
||||
use super::decode_error;
|
||||
use std::convert::TryFrom;
|
||||
use super::decode_error::DecodeError;
|
||||
use core::convert::TryFrom;
|
||||
|
||||
/// ISA set.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
@ -133,13 +131,11 @@ pub enum IsaSet {
|
||||
|
||||
#[doc(hidden)]
|
||||
impl TryFrom<ffi::ND_INS_SET> for IsaSet {
|
||||
type Error = decode_error::DecodeError;
|
||||
type Error = DecodeError;
|
||||
|
||||
fn try_from(value: ffi::ND_INS_SET) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
ffi::_ND_INS_SET::ND_SET_INVALID => {
|
||||
Err(decode_error::DecodeError::UnknownInstruction(value as u32))
|
||||
}
|
||||
ffi::_ND_INS_SET::ND_SET_INVALID => Err(DecodeError::InternalError(value as u64)),
|
||||
ffi::_ND_INS_SET::ND_SET_3DNOW => Ok(IsaSet::I3dnow),
|
||||
ffi::_ND_INS_SET::ND_SET_ADX => Ok(IsaSet::Adx),
|
||||
ffi::_ND_INS_SET::ND_SET_AES => Ok(IsaSet::Aes),
|
||||
|
@ -4,12 +4,14 @@
|
||||
*/
|
||||
//! bddisasm x86/x64 instruction decoder
|
||||
//!
|
||||
//! Rust bindings for the [bddisasm](https://github.com/bitdefender/bddisasm) x86/x64 decoder library, built on top
|
||||
//! of [bddisasm-sys](https://crates.io/crates/bddisasm-sys).
|
||||
//! `no_std` Rust bindings for the [bddisasm](https://github.com/bitdefender/bddisasm) x86/x64 decoder library, built
|
||||
//! on top of [bddisasm-sys](https://crates.io/crates/bddisasm-sys).
|
||||
//!
|
||||
//! It supports all existing x86 instruction, offering a wide range of information about each one, including:
|
||||
//! It supports all existing 16-bit, 32-bit and 64-bit instruction, offering a wide range of information about each one,
|
||||
//! including:
|
||||
//!
|
||||
//! - operands (implicit and explicit)
|
||||
//! - implicit operands
|
||||
//! - explicit operands
|
||||
//! - access mode for each operand
|
||||
//! - CPUID feature flags
|
||||
//! - CPU modes in which an instruction is valid
|
||||
@ -27,11 +29,11 @@
|
||||
//!
|
||||
//! ## Decoding one instruction
|
||||
//!
|
||||
//! Use [DecodedInstruction::decode](crate::decoded_instruction::DecodedInstruction::decode) to decode an instruction
|
||||
//! Use [`DecodedInstruction::decode`](crate::decoded_instruction::DecodedInstruction::decode) to decode an instruction
|
||||
//! from a chunk of code.
|
||||
//!
|
||||
//! ```
|
||||
//! use bddisasm::decoded_instruction::{DecodedInstruction, DecodeMode, Mnemonic};
|
||||
//! use bddisasm::{DecodedInstruction, DecodeMode, Mnemonic};
|
||||
//!
|
||||
//! let code = vec![0x31, 0xc0];
|
||||
//! match DecodedInstruction::decode(&code, DecodeMode::Bits32) {
|
||||
@ -45,10 +47,10 @@
|
||||
//!
|
||||
//! ## Decoding multiple instructions
|
||||
//!
|
||||
//! Use [Decoder](crate::decoder::Decoder) to decode multiple instructions from a chunk of code.
|
||||
//! Use [`Decoder`](crate::decoder::Decoder) to decode multiple instructions from a chunk of code.
|
||||
//!
|
||||
//! ```
|
||||
//! use bddisasm::decoder::{Decoder, DecodeMode};
|
||||
//! use bddisasm::{Decoder, DecodeMode};
|
||||
//!
|
||||
//! let code = [
|
||||
//! // ENCLS
|
||||
@ -79,11 +81,11 @@
|
||||
//! WRMSR
|
||||
//! ```
|
||||
//!
|
||||
//! Use [Decoder::decode_next_with_info](crate::decoder::Decoder::decode_next_with_info) to get information about the
|
||||
//! Use [`Decoder::decode_next_with_info`](crate::decoder::Decoder::decode_next_with_info) to get information about the
|
||||
//! offset inside the code chunk at which an instruction was decoded from.
|
||||
//!
|
||||
//! ```
|
||||
//! use bddisasm::decoder::{Decoder, DecodeMode};
|
||||
//! use bddisasm::{Decoder, DecodeMode};
|
||||
//!
|
||||
//! let code = [
|
||||
//! // ENCLS
|
||||
@ -122,10 +124,9 @@
|
||||
//! each type of operand. Bellow is a minimal example that looks at a memory operand.
|
||||
//!
|
||||
//! ```
|
||||
//! # use bddisasm::decode_error::DecodeError;
|
||||
//! # use bddisasm::DecodeError;
|
||||
//! # fn test() -> Result<(), DecodeError> {
|
||||
//! use bddisasm::decoded_instruction::{DecodedInstruction, DecodeMode};
|
||||
//! use bddisasm::operand::OpInfo;
|
||||
//! use bddisasm::{DecodedInstruction, DecodeMode, OpInfo};
|
||||
//!
|
||||
//! // ` MOV rax, qword ptr [rcx+r15*2]`
|
||||
//! let code = b"\x4a\x8b\x04\x79";
|
||||
@ -177,6 +178,21 @@
|
||||
//! Scale: 2
|
||||
//! No displacement
|
||||
//! ```
|
||||
//!
|
||||
//! ## Accessing the raw bindings
|
||||
//!
|
||||
//! The raw `bddisasm_sys` bindings are available via the `ffi` re-export.
|
||||
//!
|
||||
//! # Feature Flags
|
||||
//!
|
||||
//! - `std` - adds a `std` dependency - the only visible difference when doing this is that [`DecodeError`] implements
|
||||
//! the `Error` trait
|
||||
//!
|
||||
|
||||
#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
|
||||
|
||||
pub extern crate bddisasm_sys as ffi;
|
||||
|
||||
pub mod cpu_modes;
|
||||
pub mod cpuid;
|
||||
pub mod decode_error;
|
||||
@ -189,3 +205,13 @@ pub mod mnemonic;
|
||||
pub mod operand;
|
||||
pub mod rflags;
|
||||
pub mod tuple;
|
||||
|
||||
pub use crate::decode_error::DecodeError;
|
||||
pub use crate::decoded_instruction::{DecodeMode, DecodeResult, DecodedInstruction, OperandSize};
|
||||
pub use crate::decoder::Decoder;
|
||||
pub use crate::instruction_category::Category;
|
||||
pub use crate::isa_set::IsaSet;
|
||||
pub use crate::mnemonic::Mnemonic;
|
||||
pub use crate::operand::{
|
||||
OpAddr, OpInfo, OpMem, OpReg, OpRegType, OpSize, Operand, OperandsLookup,
|
||||
};
|
||||
|
@ -4,10 +4,8 @@
|
||||
*/
|
||||
//! Mnemonics.
|
||||
|
||||
extern crate bddisasm_sys as ffi;
|
||||
|
||||
use super::decode_error;
|
||||
use std::convert::TryFrom;
|
||||
use super::decode_error::DecodeError;
|
||||
use core::convert::TryFrom;
|
||||
|
||||
/// Uniquely identifies an instruction.
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
@ -1601,13 +1599,11 @@ pub enum Mnemonic {
|
||||
|
||||
#[doc(hidden)]
|
||||
impl TryFrom<ffi::ND_INS_CLASS> for Mnemonic {
|
||||
type Error = decode_error::DecodeError;
|
||||
type Error = DecodeError;
|
||||
|
||||
fn try_from(value: ffi::ND_INS_CLASS) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
ffi::_ND_INS_CLASS::ND_INS_INVALID => {
|
||||
Err(decode_error::DecodeError::UnknownInstruction(value as u32))
|
||||
}
|
||||
ffi::_ND_INS_CLASS::ND_INS_INVALID => Err(DecodeError::InternalError(value as u64)),
|
||||
ffi::_ND_INS_CLASS::ND_INS_AAA => Ok(Mnemonic::Aaa),
|
||||
ffi::_ND_INS_CLASS::ND_INS_AAD => Ok(Mnemonic::Aad),
|
||||
ffi::_ND_INS_CLASS::ND_INS_AAM => Ok(Mnemonic::Aam),
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -4,8 +4,6 @@
|
||||
*/
|
||||
//! Describes the bits in the FLAGS register.
|
||||
|
||||
extern crate bddisasm_sys as ffi;
|
||||
|
||||
/// Carry flag.
|
||||
pub const CF: u32 = ffi::NDR_RFLAG_CF;
|
||||
/// Parity flag.
|
||||
|
@ -4,7 +4,7 @@
|
||||
*/
|
||||
//! Instruction tuple type.
|
||||
|
||||
extern crate bddisasm_sys as ffi;
|
||||
use super::decode_error::DecodeError;
|
||||
|
||||
/// Instruction tuple type.
|
||||
///
|
||||
@ -50,73 +50,76 @@ pub enum Tuple {
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
impl From<ffi::ND_TUPLE> for Tuple {
|
||||
fn from(value: ffi::ND_TUPLE) -> Tuple {
|
||||
match value {
|
||||
ffi::_ND_TUPLE::ND_TUPLE_None => Tuple::None,
|
||||
ffi::_ND_TUPLE::ND_TUPLE_FV => Tuple::Fv,
|
||||
ffi::_ND_TUPLE::ND_TUPLE_HV => Tuple::Hv,
|
||||
ffi::_ND_TUPLE::ND_TUPLE_QV => Tuple::Qv,
|
||||
ffi::_ND_TUPLE::ND_TUPLE_T1S8 => Tuple::T1S8,
|
||||
ffi::_ND_TUPLE::ND_TUPLE_T1S16 => Tuple::T1S16,
|
||||
ffi::_ND_TUPLE::ND_TUPLE_T1S => Tuple::T1S,
|
||||
ffi::_ND_TUPLE::ND_TUPLE_T1F => Tuple::T1F,
|
||||
ffi::_ND_TUPLE::ND_TUPLE_T2 => Tuple::T2,
|
||||
ffi::_ND_TUPLE::ND_TUPLE_T4 => Tuple::T4,
|
||||
ffi::_ND_TUPLE::ND_TUPLE_T8 => Tuple::T8,
|
||||
ffi::_ND_TUPLE::ND_TUPLE_FVM => Tuple::Fvm,
|
||||
ffi::_ND_TUPLE::ND_TUPLE_HVM => Tuple::Hvm,
|
||||
ffi::_ND_TUPLE::ND_TUPLE_QVM => Tuple::Qvm,
|
||||
ffi::_ND_TUPLE::ND_TUPLE_OVM => Tuple::OVm,
|
||||
ffi::_ND_TUPLE::ND_TUPLE_M128 => Tuple::M128,
|
||||
ffi::_ND_TUPLE::ND_TUPLE_DUP => Tuple::Dup,
|
||||
ffi::_ND_TUPLE::ND_TUPLE_T1_4X => Tuple::T14X,
|
||||
// NOTE: when updating this take care to also update the `From<u32>` implementation!
|
||||
// TODO: any way of keeping these in sync automagically?
|
||||
impl Tuple {
|
||||
pub(crate) fn from_raw(value: u32) -> Result<Self, DecodeError> {
|
||||
if value == ffi::_ND_TUPLE::ND_TUPLE_None as u32 {
|
||||
Ok(Tuple::None)
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_FV as u32 {
|
||||
Ok(Tuple::Fv)
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_HV as u32 {
|
||||
Ok(Tuple::Hv)
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_QV as u32 {
|
||||
Ok(Tuple::Qv)
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_T1S8 as u32 {
|
||||
Ok(Tuple::T1S8)
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_T1S16 as u32 {
|
||||
Ok(Tuple::T1S16)
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_T1S as u32 {
|
||||
Ok(Tuple::T1S)
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_T1F as u32 {
|
||||
Ok(Tuple::T1F)
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_T2 as u32 {
|
||||
Ok(Tuple::T2)
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_T4 as u32 {
|
||||
Ok(Tuple::T4)
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_T8 as u32 {
|
||||
Ok(Tuple::T8)
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_FVM as u32 {
|
||||
Ok(Tuple::Fvm)
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_HVM as u32 {
|
||||
Ok(Tuple::Hvm)
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_QVM as u32 {
|
||||
Ok(Tuple::Qvm)
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_OVM as u32 {
|
||||
Ok(Tuple::OVm)
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_M128 as u32 {
|
||||
Ok(Tuple::M128)
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_DUP as u32 {
|
||||
Ok(Tuple::Dup)
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_T1_4X as u32 {
|
||||
Ok(Tuple::T14X)
|
||||
} else {
|
||||
Err(DecodeError::InternalError(value.into()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Tuple {
|
||||
fn from(value: u32) -> Tuple {
|
||||
if value == ffi::_ND_TUPLE::ND_TUPLE_None as u32 {
|
||||
Tuple::None
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_FV as u32 {
|
||||
Tuple::Fv
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_HV as u32 {
|
||||
Tuple::Hv
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_QV as u32 {
|
||||
Tuple::Qv
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_T1S8 as u32 {
|
||||
Tuple::T1S8
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_T1S16 as u32 {
|
||||
Tuple::T1S16
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_T1S as u32 {
|
||||
Tuple::T1S
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_T1F as u32 {
|
||||
Tuple::T1F
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_T2 as u32 {
|
||||
Tuple::T2
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_T4 as u32 {
|
||||
Tuple::T4
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_T8 as u32 {
|
||||
Tuple::T8
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_FVM as u32 {
|
||||
Tuple::Fvm
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_HVM as u32 {
|
||||
Tuple::Hvm
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_QVM as u32 {
|
||||
Tuple::Qvm
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_OVM as u32 {
|
||||
Tuple::OVm
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_M128 as u32 {
|
||||
Tuple::M128
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_DUP as u32 {
|
||||
Tuple::Dup
|
||||
} else if value == ffi::_ND_TUPLE::ND_TUPLE_T1_4X as u32 {
|
||||
Tuple::T14X
|
||||
} else {
|
||||
panic!("Unknown tuple: {}", value)
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn check_all_tuples() {
|
||||
// This is a really contrieved way of making sure that we check all variants of `ffi::_ND_TUPLE`. If a new
|
||||
// one is added, this will fail to build. We do this because `Tuple::from_raw` takes an `u32`.
|
||||
// NOTE: When a new variant is added, `Tuple::from_raw` must be updated.
|
||||
match ffi::_ND_TUPLE::ND_TUPLE_None {
|
||||
ffi::_ND_TUPLE::ND_TUPLE_None => {}
|
||||
ffi::_ND_TUPLE::ND_TUPLE_FV => {}
|
||||
ffi::_ND_TUPLE::ND_TUPLE_HV => {}
|
||||
ffi::_ND_TUPLE::ND_TUPLE_QV => {}
|
||||
ffi::_ND_TUPLE::ND_TUPLE_T1S8 => {}
|
||||
ffi::_ND_TUPLE::ND_TUPLE_T1S16 => {}
|
||||
ffi::_ND_TUPLE::ND_TUPLE_T1S => {}
|
||||
ffi::_ND_TUPLE::ND_TUPLE_T1F => {}
|
||||
ffi::_ND_TUPLE::ND_TUPLE_T2 => {}
|
||||
ffi::_ND_TUPLE::ND_TUPLE_T4 => {}
|
||||
ffi::_ND_TUPLE::ND_TUPLE_T8 => {}
|
||||
ffi::_ND_TUPLE::ND_TUPLE_FVM => {}
|
||||
ffi::_ND_TUPLE::ND_TUPLE_HVM => {}
|
||||
ffi::_ND_TUPLE::ND_TUPLE_QVM => {}
|
||||
ffi::_ND_TUPLE::ND_TUPLE_OVM => {}
|
||||
ffi::_ND_TUPLE::ND_TUPLE_M128 => {}
|
||||
ffi::_ND_TUPLE::ND_TUPLE_DUP => {}
|
||||
ffi::_ND_TUPLE::ND_TUPLE_T1_4X => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
12
bindings/rsbddisasm/fix_symlinks.sh
Normal file
12
bindings/rsbddisasm/fix_symlinks.sh
Normal file
@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
cd bddisasm-sys
|
||||
rm -rf LICENSE
|
||||
ln -s ../../../LICENSE .
|
||||
|
||||
cd csrc
|
||||
rm -rf bddisasm
|
||||
ln -s ../../../../bddisasm/ .
|
||||
rm -rf inc
|
||||
ln -s ../../../../inc/ .
|
@ -1,6 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
@ -9,6 +13,10 @@
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
@ -43,11 +51,22 @@
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
@ -60,9 +79,15 @@
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>14.0.23107.0</_ProjectFileVersion>
|
||||
@ -77,6 +102,11 @@
|
||||
<IntDir>$(SolutionDir)_intdir\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)_intdir\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)_intdir\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
@ -89,6 +119,13 @@
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)_intdir\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
|
||||
<IgnoreImportLibrary>false</IgnoreImportLibrary>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<LibraryPath>$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
@ -141,6 +178,33 @@
|
||||
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
|
||||
</ProjectReference>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<Midl />
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/D "AMD64" %(AdditionalOptions)</AdditionalOptions>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>..\inc;..\bdshemu;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MinimalRebuild>true</MinimalRebuild>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<ProgramDataBaseFileName>$(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>bddisasm.lib;bdshemu.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)disasmtool.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<IgnoreSpecificDefaultLibraries>LIBCMTD;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
<ProjectReference>
|
||||
<UseLibraryDependencyInputs>false</UseLibraryDependencyInputs>
|
||||
</ProjectReference>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
@ -200,6 +264,38 @@
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<Midl />
|
||||
<ClCompile>
|
||||
<AdditionalOptions>/D "AMD64" %(AdditionalOptions)</AdditionalOptions>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
|
||||
<AdditionalIncludeDirectories>..\inc;..\bdshemu;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<FunctionLevelLinking>false</FunctionLevelLinking>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<ProgramDataBaseFileName>$(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<ProjectReference>
|
||||
<UseLibraryDependencyInputs>true</UseLibraryDependencyInputs>
|
||||
</ProjectReference>
|
||||
<Link>
|
||||
<AdditionalDependencies>bddisasm.lib;bdshemu.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<OutputFile>$(OutDir)disasmtool.exe</OutputFile>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)bin\$(Platform)\$(Configuration)\;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<IgnoreSpecificDefaultLibraries>LIBCMT;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="disasmtool.c" />
|
||||
</ItemGroup>
|
||||
|
@ -12,7 +12,7 @@ if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release")
|
||||
endif ()
|
||||
|
||||
add_executable(disasmtool disasmtool.cpp dumpers.cpp)
|
||||
add_executable(disasmtool disasmtool.cpp dumpers.cpp rapidjson.cpp)
|
||||
|
||||
target_compile_options(
|
||||
disasmtool
|
||||
@ -43,15 +43,11 @@ if (NOT TARGET bddisasm)
|
||||
find_package(bddisasm REQUIRED)
|
||||
endif ()
|
||||
|
||||
find_package(RapidJSON QUIET)
|
||||
find_package(RapidJSON QUIET REQUIRED)
|
||||
|
||||
target_link_libraries(disasmtool PRIVATE bddisasm::bddisasm bddisasm::bdshemu)
|
||||
if (RapidJSON_FOUND)
|
||||
# :( https://github.com/satishbabariya/modern-cmake#good-boys-export-their-targets
|
||||
target_include_directories(disasmtool PRIVATE ${RapidJSON_INCLUDE_DIRS})
|
||||
target_sources(disasmtool PRIVATE rapidjson.cpp)
|
||||
target_compile_definitions(disasmtool PRIVATE HAS_RAPIDJSON)
|
||||
endif ()
|
||||
|
||||
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
|
||||
include(CheckIPOSupported)
|
||||
|
@ -7,13 +7,8 @@
|
||||
#include <ctime>
|
||||
#include <cstdint>
|
||||
|
||||
#ifdef HAS_RAPIDJSON
|
||||
#include <rapidjson/stringbuffer.h>
|
||||
using StringBuffer = rapidjson::StringBuffer;
|
||||
#else
|
||||
#include "external/json.hpp"
|
||||
using json = nlohmann::json;
|
||||
#endif
|
||||
|
||||
|
||||
extern "C"
|
||||
|
@ -496,14 +496,14 @@ void shemu_log(PCHAR msg)
|
||||
printf("%s", msg);
|
||||
}
|
||||
|
||||
bool shemu_access_mem(void * /* Ctx */, uint64_t /* Gla */, size_t Size, uint8_t *Buffer, bool Store)
|
||||
ND_BOOL shemu_access_mem(void * /* Ctx */, uint64_t /* Gla */, size_t Size, uint8_t *Buffer, ND_BOOL Store)
|
||||
{
|
||||
if (!Store)
|
||||
{
|
||||
memset(Buffer, 0, Size);
|
||||
}
|
||||
|
||||
return true;
|
||||
return ND_TRUE;
|
||||
}
|
||||
|
||||
void shemu(options &opts)
|
||||
|
Loading…
Reference in New Issue
Block a user