diff options
Diffstat (limited to 'rust/examples/idb_import/src/lib.rs')
| -rw-r--r-- | rust/examples/idb_import/src/lib.rs | 344 |
1 files changed, 0 insertions, 344 deletions
diff --git a/rust/examples/idb_import/src/lib.rs b/rust/examples/idb_import/src/lib.rs deleted file mode 100644 index 48d1b8fd..00000000 --- a/rust/examples/idb_import/src/lib.rs +++ /dev/null @@ -1,344 +0,0 @@ -mod types; -use types::*; -mod addr_info; -use addr_info::*; - -use binaryninja::binaryview::{BinaryView, BinaryViewBase, BinaryViewExt}; -use binaryninja::debuginfo::{ - CustomDebugInfoParser, DebugFunctionInfo, DebugInfo, DebugInfoParser, -}; - -use idb_rs::id0::{ID0Section, IDBParam1, IDBParam2}; -use idb_rs::til::section::TILSection; -use idb_rs::til::Type as TILType; - -use log::{error, trace, warn, LevelFilter}; - -use anyhow::Result; -use binaryninja::logger::Logger; - -struct IDBDebugInfoParser; -impl CustomDebugInfoParser for IDBDebugInfoParser { - fn is_valid(&self, view: &BinaryView) -> bool { - if let Some(project_file) = view.file().get_project_file() { - project_file.name().as_str().ends_with(".i64") - || project_file.name().as_str().ends_with(".idb") - } else { - view.file().filename().as_str().ends_with(".i64") - || view.file().filename().as_str().ends_with(".idb") - } - } - - fn parse_info( - &self, - debug_info: &mut DebugInfo, - bv: &BinaryView, - debug_file: &BinaryView, - progress: Box<dyn Fn(usize, usize) -> Result<(), ()>>, - ) -> bool { - match parse_idb_info(debug_info, bv, debug_file, progress) { - Ok(()) => true, - Err(error) => { - error!("Unable to parse IDB file: {error}"); - false - } - } - } -} - -struct TILDebugInfoParser; -impl CustomDebugInfoParser for TILDebugInfoParser { - fn is_valid(&self, view: &BinaryView) -> bool { - if let Some(project_file) = view.file().get_project_file() { - project_file.name().as_str().ends_with(".til") - } else { - view.file().filename().as_str().ends_with(".til") - } - } - - fn parse_info( - &self, - debug_info: &mut DebugInfo, - _bv: &BinaryView, - debug_file: &BinaryView, - progress: Box<dyn Fn(usize, usize) -> Result<(), ()>>, - ) -> bool { - match parse_til_info(debug_info, debug_file, progress) { - Ok(()) => true, - Err(error) => { - error!("Unable to parse TIL file: {error}"); - false - } - } - } -} - -struct BinaryViewReader<'a> { - bv: &'a BinaryView, - offset: u64, -} -impl std::io::Read for BinaryViewReader<'_> { - fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> { - if !self.bv.offset_valid(self.offset) { - return Err(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "")); - } - let len = self.bv.read(buf, self.offset); - self.offset += u64::try_from(len).unwrap(); - Ok(len) - } -} - -impl std::io::Seek for BinaryViewReader<'_> { - fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> { - let new_offset = match pos { - std::io::SeekFrom::Start(offset) => Some(offset), - std::io::SeekFrom::End(end) => u64::try_from(self.bv.len()) - .unwrap() - .checked_add_signed(end), - std::io::SeekFrom::Current(next) => self.offset.checked_add_signed(next), - }; - let new_offset = - new_offset.ok_or_else(|| std::io::Error::new(std::io::ErrorKind::UnexpectedEof, ""))?; - if !self.bv.offset_valid(new_offset) { - return Err(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "")); - } - self.offset = new_offset; - Ok(new_offset) - } -} - -fn parse_idb_info( - debug_info: &mut DebugInfo, - bv: &BinaryView, - debug_file: &BinaryView, - progress: Box<dyn Fn(usize, usize) -> Result<(), ()>>, -) -> Result<()> { - trace!("Opening a IDB file"); - let file = BinaryViewReader { - bv: debug_file, - offset: 0, - }; - trace!("Parsing a IDB file"); - let file = std::io::BufReader::new(file); - let mut parser = idb_rs::IDBParser::new(file)?; - if let Some(til_section) = parser.til_section_offset() { - trace!("Parsing the TIL section"); - let til = parser.read_til_section(til_section)?; - // progress 0%-50% - import_til_section(debug_info, debug_file, &til, progress)?; - } - - if let Some(id0_section) = parser.id0_section_offset() { - trace!("Parsing the ID0 section"); - let id0 = parser.read_id0_section(id0_section)?; - // progress 50%-100% - parse_id0_section_info(debug_info, bv, debug_file, &id0)?; - } - - Ok(()) -} - -fn parse_til_info( - debug_info: &mut DebugInfo, - debug_file: &BinaryView, - progress: Box<dyn Fn(usize, usize) -> Result<(), ()>>, -) -> Result<()> { - trace!("Opening a TIL file"); - let file = BinaryViewReader { - bv: debug_file, - offset: 0, - }; - let file = std::io::BufReader::new(file); - trace!("Parsing the TIL section"); - let til = TILSection::parse(file)?; - import_til_section(debug_info, debug_file, &til, progress) -} - -pub fn import_til_section( - debug_info: &mut DebugInfo, - debug_file: &BinaryView, - til: &TILSection, - progress: impl Fn(usize, usize) -> Result<(), ()>, -) -> Result<()> { - let types = types::translate_til_types(debug_file.default_arch().unwrap(), til, progress)?; - - // print any errors - for ty in &types { - match &ty.ty { - TranslateTypeResult::NotYet => { - panic!( - "type could not be processed `{}`: {:#?}", - &String::from_utf8_lossy(&ty.name), - &ty.og_ty - ); - } - TranslateTypeResult::Error(error) => { - error!( - "Unable to parse type `{}`: {error}", - &String::from_utf8_lossy(&ty.name) - ); - } - TranslateTypeResult::PartiallyTranslated(_, error) => { - if let Some(error) = error { - error!( - "Unable to parse type `{}` correctly: {error}", - &String::from_utf8_lossy(&ty.name) - ); - } else { - warn!( - "Type `{}` maybe not be fully translated", - &String::from_utf8_lossy(&ty.name) - ); - } - } - TranslateTypeResult::Translated(_) => {} - }; - } - - // add all type to binary ninja - for ty in &types { - if let TranslateTypeResult::Translated(bn_ty) - | TranslateTypeResult::PartiallyTranslated(bn_ty, _) = &ty.ty - { - if !debug_info.add_type(&String::from_utf8_lossy(&ty.name), bn_ty, &[/* TODO */]) { - error!( - "Unable to add type `{}`", - &String::from_utf8_lossy(&ty.name) - ) - } - } - } - - // add a second time to fix the references LOL - for ty in &types { - if let TranslateTypeResult::Translated(bn_ty) - | TranslateTypeResult::PartiallyTranslated(bn_ty, _) = &ty.ty - { - if !debug_info.add_type(&String::from_utf8_lossy(&ty.name), bn_ty, &[/* TODO */]) { - error!( - "Unable to fix type `{}`", - &String::from_utf8_lossy(&ty.name) - ) - } - } - } - - Ok(()) -} - -fn parse_id0_section_info( - debug_info: &mut DebugInfo, - bv: &BinaryView, - debug_file: &BinaryView, - id0: &ID0Section, -) -> Result<()> { - let version = match id0.ida_info()? { - idb_rs::id0::IDBParam::V1(IDBParam1 { version, .. }) - | idb_rs::id0::IDBParam::V2(IDBParam2 { version, .. }) => version, - }; - - for (addr, info) in get_info(id0, version)? { - // just in case we change this struct in the future, this line will for us to review this code - // TODO merge this data with folder locations - let AddrInfo { - comments, - label, - ty, - } = info; - // TODO set comments to address here - for function in &bv.functions_containing(addr) { - function.set_comment_at( - addr, - String::from_utf8_lossy(&comments.join(&b"\n"[..])).to_string(), - ); - } - - let bnty = ty - .as_ref() - .and_then(|ty| match translate_ephemeral_type(debug_file, ty) { - TranslateTypeResult::Translated(result) => Some(result), - TranslateTypeResult::PartiallyTranslated(result, None) => { - warn!("Unable to fully translate the type at {addr:#x}"); - Some(result) - } - TranslateTypeResult::NotYet => { - error!("Unable to translate the type at {addr:#x}"); - None - } - TranslateTypeResult::PartiallyTranslated(_, Some(bn_type_error)) - | TranslateTypeResult::Error(bn_type_error) => { - error!("Unable to translate the type at {addr:#x}: {bn_type_error}",); - None - } - }); - - match (label, &ty, bnty) { - (_, Some(TILType::Function(_)), bnty) => { - if bnty.is_none() { - error!("Unable to convert the function type at {addr:#x}",) - } - if !debug_info.add_function(DebugFunctionInfo::new( - None, - None, - label.map(str::to_string), - bnty, - Some(addr), - None, - vec![], - vec![], - )) { - error!("Unable to add the function at {addr:#x}") - } - } - (_, Some(_ty), Some(bnty)) => { - if !debug_info.add_data_variable(addr, &bnty, label, &[]) { - error!("Unable to add the type at {addr:#x}") - } - } - (_, Some(_ty), None) => { - // TODO types come from the TIL sections, can we make all types be just NamedTypes? - error!("Unable to convert type {addr:#x}"); - // TODO how to add a label without a type associacted with it? - if let Some(name) = label { - if !debug_info.add_data_variable( - addr, - &binaryninja::types::Type::void(), - Some(name), - &[], - ) { - error!("Unable to add the label at {addr:#x}") - } - } - } - (Some(name), None, None) => { - // TODO how to add a label without a type associacted with it? - if !debug_info.add_data_variable( - addr, - &binaryninja::types::Type::void(), - Some(name), - &[], - ) { - error!("Unable to add the label at {addr:#x}") - } - } - - // just comments at this address - (None, None, None) => {} - - (_, None, Some(_)) => unreachable!(), - } - } - - Ok(()) -} - -#[allow(non_snake_case)] -#[no_mangle] -pub extern "C" fn CorePluginInit() -> bool { - Logger::new("IDB Import") - .with_level(LevelFilter::Error) - .init(); - DebugInfoParser::register("IDB Parser", IDBDebugInfoParser); - DebugInfoParser::register("TIL Parser", TILDebugInfoParser); - true -} |
