From fb0fcd199680032932784b07b074738999779d58 Mon Sep 17 00:00:00 2001 From: KyleMiles Date: Tue, 16 Jan 2024 15:07:23 -0500 Subject: Add support for components in debug info --- rust/src/debuginfo.rs | 88 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 21 deletions(-) (limited to 'rust/src') diff --git a/rust/src/debuginfo.rs b/rust/src/debuginfo.rs index 640819dd..ab4f8f6b 100644 --- a/rust/src/debuginfo.rs +++ b/rust/src/debuginfo.rs @@ -285,17 +285,23 @@ unsafe impl CoreOwnedArrayProvider for DebugInfoParser { /// When contributing function info, provide only what you know - BinaryNinja will figure out everything else that it can, as it usually does. /// /// Functions will not be created if an address is not provided, but will be able to be queried from debug info for later user analysis. -pub struct DebugFunctionInfo { - short_name: Option, - full_name: Option, - raw_name: Option, +pub struct DebugFunctionInfo { + short_name: Option, + full_name: Option, + raw_name: Option, type_: Option>, address: u64, platform: Option>, + components: Vec, } -impl From<&BNDebugFunctionInfo> for DebugFunctionInfo { +impl From<&BNDebugFunctionInfo> for DebugFunctionInfo { fn from(raw: &BNDebugFunctionInfo) -> Self { + let components = unsafe { slice::from_raw_parts(raw.components, raw.componentN) } + .iter() + .map(|component| raw_to_string(*component as *const _).unwrap()) + .collect(); + Self { short_name: raw_to_string(raw.shortName), full_name: raw_to_string(raw.fullName), @@ -311,18 +317,20 @@ impl From<&BNDebugFunctionInfo> for DebugFunctionInfo { } else { Some(unsafe { Platform::ref_from_raw(raw.platform) }) }, + components, } } } -impl DebugFunctionInfo { +impl DebugFunctionInfo { pub fn new( - short_name: Option, - full_name: Option, - raw_name: Option, + short_name: Option, + full_name: Option, + raw_name: Option, type_: Option>, address: Option, platform: Option>, + components: Vec, ) -> Self { Self { short_name, @@ -334,6 +342,7 @@ impl DebugFunctionInfo { _ => 0, }, platform, + components, } } } @@ -408,7 +417,7 @@ impl DebugInfo { pub fn functions_by_name( &self, parser_name: S, - ) -> Vec> { + ) -> Vec { let parser_name = parser_name.into_bytes_with_nul(); let mut count: usize = 0; @@ -420,10 +429,10 @@ impl DebugInfo { ) }; - let result: Vec> = unsafe { + let result: Vec = unsafe { slice::from_raw_parts_mut(functions_ptr, count) .iter() - .map(DebugFunctionInfo::::from) + .map(DebugFunctionInfo::from) .collect() }; @@ -432,15 +441,15 @@ impl DebugInfo { } /// A generator of all functions provided by DebugInfoParsers - pub fn functions(&self) -> Vec> { + pub fn functions(&self) -> Vec { let mut count: usize = 0; let functions_ptr = unsafe { BNGetDebugFunctions(self.handle, ptr::null_mut(), &mut count) }; - let result: Vec> = unsafe { + let result: Vec = unsafe { slice::from_raw_parts_mut(functions_ptr, count) .iter() - .map(DebugFunctionInfo::::from) + .map(DebugFunctionInfo::from) .collect() }; @@ -720,38 +729,57 @@ impl DebugInfo { } /// Adds a type scoped under the current parser's name to the debug info - pub fn add_type(&self, name: S, new_type: &Type) -> bool { + pub fn add_type( + &self, + name: S, + new_type: &Type, + components: &[&str], + ) -> bool { + let mut components_array: Vec<*const ::std::os::raw::c_char> = + Vec::with_capacity(components.len()); + for component in components { + components_array.push(component.as_ptr() as _); + } + let name = name.into_bytes_with_nul(); unsafe { BNAddDebugType( self.handle, name.as_ref().as_ptr() as *mut _, new_type.handle, + components_array.as_ptr() as _, + components.len(), ) } } /// Adds a function scoped under the current parser's name to the debug info - pub fn add_function(&self, new_func: DebugFunctionInfo) -> bool { + pub fn add_function(&self, new_func: DebugFunctionInfo) -> bool { let short_name_bytes = new_func.short_name.map(|name| name.into_bytes_with_nul()); let short_name = short_name_bytes .as_ref() .map_or(ptr::null_mut() as *mut _, |name| { - name.as_ref().as_ptr() as *mut _ + name.as_ptr() as _ }); let full_name_bytes = new_func.full_name.map(|name| name.into_bytes_with_nul()); let full_name = full_name_bytes .as_ref() .map_or(ptr::null_mut() as *mut _, |name| { - name.as_ref().as_ptr() as *mut _ + name.as_ptr() as _ }); let raw_name_bytes = new_func.raw_name.map(|name| name.into_bytes_with_nul()); let raw_name = raw_name_bytes .as_ref() .map_or(ptr::null_mut() as *mut _, |name| { - name.as_ref().as_ptr() as *mut _ + name.as_ptr() as _ }); + let mut components_array: Vec<*const ::std::os::raw::c_char> = + Vec::with_capacity(new_func.components.len()); + for component in &new_func.components { + components_array.push(component.as_ptr() as _); + } + unsafe { BNAddDebugFunction( self.handle, @@ -768,6 +796,8 @@ impl DebugInfo { Some(platform) => platform.handle, _ => ptr::null_mut(), }, + components: components_array.as_ptr() as _, + componentN: new_func.components.len(), }, ) } @@ -779,7 +809,14 @@ impl DebugInfo { address: u64, t: &Type, name: Option, + components: &[&str], ) -> bool { + let mut components_array: Vec<*const ::std::os::raw::c_char> = + Vec::with_capacity(components.len()); + for component in components { + components_array.push(component.as_ptr() as _); + } + match name { Some(name) => { let name = name.into_bytes_with_nul(); @@ -789,11 +826,20 @@ impl DebugInfo { address, t.handle, name.as_ref().as_ptr() as *mut _, + components.as_ptr() as _, + components.len(), ) } } None => unsafe { - BNAddDebugDataVariable(self.handle, address, t.handle, ptr::null_mut()) + BNAddDebugDataVariable( + self.handle, + address, + t.handle, + ptr::null_mut(), + components.as_ptr() as _, + components.len(), + ) }, } } -- cgit v1.3.1