Skip to content

Commit 5239db6

Browse files
rbranemesare
authored andcommitted
Implement rust TypeParser
1 parent 8c098d2 commit 5239db6

File tree

4 files changed

+1684
-76
lines changed

4 files changed

+1684
-76
lines changed

rust/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ pub mod fileaccessor;
148148
pub mod filemetadata;
149149
pub mod flowgraph;
150150
pub mod function;
151+
pub mod typeparser;
151152
pub mod functionrecognizer;
152153
pub mod headless;
153154
pub mod hlil;

rust/src/platform.rs

Lines changed: 100 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
//! Contains all information related to the execution environment of the binary, mainly the calling conventions used
1616
17-
use std::{borrow::Borrow, collections::HashMap, os::raw, path::Path, ptr, slice};
17+
use std::{borrow::Borrow, ffi, ptr};
1818

1919
use binaryninjacore_sys::*;
2020

@@ -26,6 +26,7 @@ use crate::{
2626
typelibrary::TypeLibrary,
2727
types::{QualifiedName, QualifiedNameAndType, Type},
2828
};
29+
use crate::typeparser::{TypeParserError, TypeParserErrorSeverity, TypeParserResult};
2930

3031
#[derive(PartialEq, Eq, Hash)]
3132
pub struct Platform {
@@ -260,95 +261,118 @@ impl Platform {
260261
Array::new(handles, count, ())
261262
}
262263
}
263-
}
264264

265-
pub trait TypeParser {
266-
fn parse_types_from_source<S: BnStrCompatible, P: AsRef<Path>>(
265+
pub fn preprocess_source(
267266
&self,
268-
_source: S,
269-
_filename: S,
270-
_include_directories: &[P],
271-
_auto_type_source: S,
272-
) -> Result<TypeParserResult, String> {
273-
Err(String::new())
267+
source: &str,
268+
file_name: &str,
269+
include_dirs: &[BnString],
270+
) -> Result<BnString, Vec<TypeParserError>> {
271+
let source_cstr = BnString::new(source);
272+
let file_name_cstr = BnString::new(file_name);
273+
274+
let mut result = ptr::null_mut();
275+
let mut error_string = ptr::null_mut();
276+
let success = unsafe {
277+
BNPreprocessSource(
278+
source_cstr.as_ptr(),
279+
file_name_cstr.as_ptr(),
280+
&mut result,
281+
&mut error_string,
282+
include_dirs.as_ptr() as *mut *const ffi::c_char,
283+
include_dirs.len(),
284+
)
285+
};
286+
287+
if success {
288+
assert!(!result.is_null());
289+
Ok(unsafe { BnString::from_raw(result) })
290+
} else {
291+
assert!(!error_string.is_null());
292+
Err(vec![TypeParserError::new(
293+
TypeParserErrorSeverity::FatalSeverity,
294+
unsafe { BnString::from_raw(error_string) },
295+
file_name,
296+
0,
297+
0,
298+
)])
299+
}
274300
}
275-
}
276-
277-
#[derive(Clone, Default)]
278-
pub struct TypeParserResult {
279-
pub types: HashMap<QualifiedName, Ref<Type>>,
280-
pub variables: HashMap<QualifiedName, Ref<Type>>,
281-
pub functions: HashMap<QualifiedName, Ref<Type>>,
282-
}
283-
284-
impl TypeParser for Platform {
285-
fn parse_types_from_source<S: BnStrCompatible, P: AsRef<Path>>(
301+
pub fn parse_types_from_source(
286302
&self,
287-
source: S,
288-
filename: S,
289-
include_directories: &[P],
290-
auto_type_source: S,
291-
) -> Result<TypeParserResult, String> {
292-
let mut result = BNTypeParserResult::default();
293-
let mut type_parser_result = TypeParserResult::default();
294-
let mut error_string: *mut raw::c_char = ptr::null_mut();
295-
296-
let src = source.into_bytes_with_nul();
297-
let filename = filename.into_bytes_with_nul();
298-
let auto_type_source = auto_type_source.into_bytes_with_nul();
299-
300-
let mut include_dirs = vec![];
301-
302-
for dir in include_directories.iter() {
303-
let d = dir
304-
.as_ref()
305-
.to_string_lossy()
306-
.to_string()
307-
.into_bytes_with_nul();
308-
include_dirs.push(d.as_ptr() as _);
309-
}
303+
src: &str,
304+
filename: &str,
305+
include_dirs: &[BnString],
306+
auto_type_source: &str,
307+
) -> Result<TypeParserResult, Vec<TypeParserError>> {
308+
let source_cstr = BnString::new(src);
309+
let file_name_cstr = BnString::new(filename);
310+
let auto_type_source = BnString::new(auto_type_source);
310311

311-
unsafe {
312-
let success = BNParseTypesFromSource(
312+
let mut result = BNTypeParserResult::default();
313+
let mut error_string = ptr::null_mut();
314+
let success = unsafe {
315+
BNParseTypesFromSource(
313316
self.handle,
314-
src.as_ref().as_ptr() as _,
315-
filename.as_ref().as_ptr() as _,
317+
source_cstr.as_ptr(),
318+
file_name_cstr.as_ptr(),
316319
&mut result,
317320
&mut error_string,
318-
include_dirs.as_mut_ptr(),
321+
include_dirs.as_ptr() as *mut *const ffi::c_char,
319322
include_dirs.len(),
320-
auto_type_source.as_ref().as_ptr() as _,
321-
);
322-
323-
let error_msg = BnString::from_raw(error_string);
323+
auto_type_source.as_ptr(),
324+
)
325+
};
324326

325-
if !success {
326-
return Err(error_msg.to_string());
327-
}
327+
if success {
328+
Ok(unsafe { TypeParserResult::from_raw(result) })
329+
} else {
330+
assert!(!error_string.is_null());
331+
Err(vec![TypeParserError::new(
332+
TypeParserErrorSeverity::FatalSeverity,
333+
unsafe { BnString::from_raw(error_string) },
334+
filename,
335+
0,
336+
0,
337+
)])
338+
}
339+
}
328340

329-
for i in slice::from_raw_parts(result.types, result.typeCount) {
330-
let name = QualifiedName::from(i.name);
331-
type_parser_result
332-
.types
333-
.insert(name, Type::ref_from_raw(i.type_));
334-
}
341+
pub fn parse_types_from_source_file(
342+
&self,
343+
filename: &str,
344+
include_dirs: &[BnString],
345+
auto_type_source: &str,
346+
) -> Result<TypeParserResult, Vec<TypeParserError>> {
347+
let file_name_cstr = BnString::new(filename);
348+
let auto_type_source = BnString::new(auto_type_source);
335349

336-
for i in slice::from_raw_parts(result.functions, result.functionCount) {
337-
let name = QualifiedName::from(i.name);
338-
type_parser_result
339-
.functions
340-
.insert(name, Type::ref_from_raw(i.type_));
341-
}
350+
let mut result = BNTypeParserResult::default();
351+
let mut error_string = ptr::null_mut();
352+
let success = unsafe {
353+
BNParseTypesFromSourceFile(
354+
self.handle,
355+
file_name_cstr.as_ptr(),
356+
&mut result,
357+
&mut error_string,
358+
include_dirs.as_ptr() as *mut *const ffi::c_char,
359+
include_dirs.len(),
360+
auto_type_source.as_ptr(),
361+
)
362+
};
342363

343-
for i in slice::from_raw_parts(result.variables, result.variableCount) {
344-
let name = QualifiedName::from(i.name);
345-
type_parser_result
346-
.variables
347-
.insert(name, Type::ref_from_raw(i.type_));
348-
}
364+
if success {
365+
Ok(unsafe { TypeParserResult::from_raw(result) })
366+
} else {
367+
assert!(!error_string.is_null());
368+
Err(vec![TypeParserError::new(
369+
TypeParserErrorSeverity::FatalSeverity,
370+
unsafe { BnString::from_raw(error_string) },
371+
filename,
372+
0,
373+
0,
374+
)])
349375
}
350-
351-
Ok(type_parser_result)
352376
}
353377
}
354378

rust/src/settings.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ impl Settings {
5050
}
5151
}
5252

53+
pub fn default() -> Ref<Self> {
54+
Self::new("default")
55+
}
56+
5357
pub fn set_resource_id<S: BnStrCompatible>(&self, resource_id: S) {
5458
let resource_id = resource_id.into_bytes_with_nul();
5559
unsafe { BNSettingsSetResourceId(self.handle, resource_id.as_ref().as_ptr() as *mut _) };

0 commit comments

Comments
 (0)