summaryrefslogtreecommitdiff
path: root/rust/src/llvm.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src/llvm.rs')
-rw-r--r--rust/src/llvm.rs100
1 files changed, 97 insertions, 3 deletions
diff --git a/rust/src/llvm.rs b/rust/src/llvm.rs
index 1296db65..d2a0292a 100644
--- a/rust/src/llvm.rs
+++ b/rust/src/llvm.rs
@@ -1,8 +1,102 @@
-use binaryninjacore_sys::BNLlvmServicesDisasmInstruction;
+use binaryninjacore_sys::{
+ BNLlvmServicesAssemble, BNLlvmServicesAssembleFree, BNLlvmServicesDisasmInstruction,
+ BNLlvmServicesInit,
+};
use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_int};
-pub fn disas_instruction(triplet: &str, data: &[u8], address64: u64) -> Option<(usize, String)> {
+#[repr(i32)]
+pub enum LlvmServicesDialect {
+ Unspecified = 0,
+ Att = 1,
+ Intel = 2,
+}
+
+#[repr(i32)]
+pub enum LlvmServicesCodeModel {
+ Default = 0,
+ Small = 1,
+ Kernel = 2,
+ Medium = 3,
+ Large = 4,
+}
+
+#[repr(i32)]
+pub enum LlvmServicesRelocMode {
+ Static = 0,
+ PIC = 1,
+ DynamicNoPIC = 2,
+}
+
+pub fn llvm_assemble(
+ code: &str,
+ dialect: LlvmServicesDialect,
+ triplet: &str,
+ code_model: LlvmServicesCodeModel,
+ reloc_mode: LlvmServicesRelocMode,
+) -> Result<Vec<u8>, String> {
+ let code = CString::new(code).map_err(|_| "Invalid encoding in code string".to_string())?;
+ let arch_triple = CString::new(triplet)
+ .map_err(|_| "Invalid encoding in architecture triple string".to_string())?;
+ let mut out_bytes: *mut std::ffi::c_char = std::ptr::null_mut();
+ let mut out_bytes_len: std::ffi::c_int = 0;
+ let mut err_bytes: *mut std::ffi::c_char = std::ptr::null_mut();
+ let mut err_len: std::ffi::c_int = 0;
+
+ unsafe {
+ BNLlvmServicesInit();
+ }
+
+ let result = unsafe {
+ BNLlvmServicesAssemble(
+ code.as_ptr(),
+ dialect as i32,
+ arch_triple.as_ptr(),
+ code_model as i32,
+ reloc_mode as i32,
+ &mut out_bytes as *mut *mut std::ffi::c_char,
+ &mut out_bytes_len as *mut std::ffi::c_int,
+ &mut err_bytes as *mut *mut std::ffi::c_char,
+ &mut err_len as *mut std::ffi::c_int,
+ )
+ };
+
+ let out = if out_bytes_len == 0 {
+ Vec::new()
+ } else {
+ unsafe {
+ std::slice::from_raw_parts(
+ out_bytes as *const std::ffi::c_char as *const u8,
+ out_bytes_len as usize,
+ )
+ }
+ .to_vec()
+ };
+
+ let errors = if err_len == 0 {
+ "".into()
+ } else {
+ String::from_utf8_lossy(unsafe {
+ std::slice::from_raw_parts(
+ err_bytes as *const std::ffi::c_char as *const u8,
+ err_len as usize,
+ )
+ })
+ .into_owned()
+ };
+
+ unsafe {
+ BNLlvmServicesAssembleFree(out_bytes, err_bytes);
+ }
+
+ if result == 0 {
+ Ok(out)
+ } else {
+ Err(errors)
+ }
+}
+
+pub fn llvm_disassemble(triplet: &str, data: &[u8], address: u64) -> Option<(usize, String)> {
unsafe {
let triplet = CString::new(triplet).ok()?;
let mut src = data.to_vec();
@@ -11,7 +105,7 @@ pub fn disas_instruction(triplet: &str, data: &[u8], address64: u64) -> Option<(
triplet.as_ptr(),
src.as_mut_ptr(),
src.len() as c_int,
- address64,
+ address,
buf.as_mut_ptr() as *mut c_char,
buf.len(),
);