You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bddisasm/bindings/rsbddisasm/bddisasm-sys/src/lib.rs

103 lines
3.4 KiB

/*
* Copyright (c) 2021 Bitdefender
* SPDX-License-Identifier: Apache-2.0
*/
//! 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.
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(deref_nullptr)] // See https://github.com/rust-lang/rust-bindgen/issues/1651
#![allow(clippy::all)]
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
#[cfg(test)]
mod tests {
use super::*;
use ::std::os::raw::c_char;
use std::mem;
#[test]
fn get_version() {
let mut major: u32 = 0;
let mut minor: u32 = 0;
let mut revision: u32 = 0;
let mut build_date: *mut c_char = std::ptr::null_mut();
let mut build_time: *mut c_char = std::ptr::null_mut();
unsafe {
NdGetVersion(
&mut major,
&mut minor,
&mut revision,
&mut build_date,
&mut build_time,
);
}
println!("major: {} minor: {} rev: {}", major, minor, revision);
let build_date = unsafe { std::ffi::CStr::from_ptr(build_date) };
let build_date = build_date.to_str().unwrap().to_string();
let build_time = unsafe { std::ffi::CStr::from_ptr(build_time) };
let build_time = build_time.to_str().unwrap().to_string();
println!("Build date: {} build time: {}", build_date, build_time);
// There are no other asserts in this test. Enforcing a known minor version is not worth it, we mainly want to
// see that `NdGetVersion` works.
assert_eq!(major, 1);
}
fn do_decode(code: &[u8]) -> (INSTRUX, NDSTATUS) {
let mut instrux: mem::MaybeUninit<INSTRUX> = mem::MaybeUninit::uninit();
let instrux = instrux.as_mut_ptr();
let status = unsafe {
NdDecodeEx(
instrux,
code.as_ptr(),
code.len() as u64,
ND_CODE_32 as u8,
ND_DATA_32 as u8,
)
};
(unsafe { *instrux }, status)
}
#[test]
fn decode() {
let code = vec![0x90];
let (instrux, status) = do_decode(&code);
assert_eq!(status, 0, "Failed to decode instruction {:#x?}", code);
assert_eq!(
unsafe { instrux.__bindgen_anon_2.Instruction },
_ND_INS_CLASS::ND_INS_NOP
);
}
#[test]
fn format() {
let code = vec![0x89, 0x29];
let (instrux, status) = do_decode(&code);
assert_eq!(status, 0, "Failed to decode instruction {:#x?}", code);
let mut buffer: [i8; ND_MIN_BUF_SIZE as usize] = [0; ND_MIN_BUF_SIZE as usize];
let status = unsafe { NdToText(&instrux, 0, ND_MIN_BUF_SIZE, buffer.as_mut_ptr()) };
assert_eq!(status, 0, "Failed to decode format {:#x?}", code);
let text = String::from_utf8(buffer.iter().map(|&c| c as u8).collect()).unwrap();
let text = text.trim_matches(char::from(0));
assert_eq!(text, "MOV dword ptr [ecx], ebp");
}
}