diff options
| author | Mason Reed <mason@vector35.com> | 2026-03-25 21:02:02 -0700 |
|---|---|---|
| committer | Mason Reed <35282038+emesare@users.noreply.github.com> | 2026-03-25 21:04:29 -0700 |
| commit | 33dd97f352ad452129427d945c2d71730e5bbdb7 (patch) | |
| tree | 6c64605ca2cf654ea4f78e89a6fc82db65ca1211 /plugins/idb_import/src/parse.rs | |
| parent | 5461d6d9abd30df3d4ad5007040f45bf5fac7c56 (diff) | |
[IDB Import] Fix some misc bugs
- In certain IDBs the loading base is zeroed but the info is not relative, in this case we now fallback to rebasing based off the lowest section address specified by `min_ea`.
- In certain IDBs the info is relative, we ignore both the loading base and `min_ea` and compute the absolute address using the base address in the binary view
- Fixed data exports being recognized as functions
- Retrieve post, pre comments from dirtree
- Fix mapping in extern section (which is tool specific in how it is setup)
- Properly mark exported data as global binding
Diffstat (limited to 'plugins/idb_import/src/parse.rs')
| -rw-r--r-- | plugins/idb_import/src/parse.rs | 117 |
1 files changed, 102 insertions, 15 deletions
diff --git a/plugins/idb_import/src/parse.rs b/plugins/idb_import/src/parse.rs index 72ac1baa..95a2fdd0 100644 --- a/plugins/idb_import/src/parse.rs +++ b/plugins/idb_import/src/parse.rs @@ -1,6 +1,6 @@ //! Parse the provided IDB / TIL file and extract information into a struct for further processing. -use idb_rs::addr_info::AddressInfo; +use idb_rs::addr_info::{all_address_info, AddressInfo}; use idb_rs::id0::function::{FuncIdx, FuncordsIdx, IDBFunctionType}; use idb_rs::id0::{ID0Section, Netdelta, SegmentType}; use idb_rs::id1::ID1Section; @@ -27,7 +27,13 @@ pub struct FunctionInfo { pub address: u64, pub is_library: bool, pub is_no_return: bool, - pub is_entry: bool, +} + +#[derive(Debug, Clone, Serialize)] +pub struct ExportInfo { + pub name: String, + pub address: u64, + pub ty: Option<idb_rs::til::Type>, } #[derive(Debug, Clone, Serialize)] @@ -35,6 +41,7 @@ pub struct NameInfo { pub address: u64, pub ty: Option<idb_rs::til::Type>, pub label: Option<String>, + pub exported: bool, } #[derive(Debug, Clone, Serialize)] @@ -57,12 +64,27 @@ pub struct FunctionCordInfo { } #[derive(Debug, Clone, Serialize)] +pub enum BaseAddressInfo { + /// The base address is not specified in the IDB. + None, + /// The base address is the absolute address of the first byte of the executable. + /// + /// To get a delta, calculate the difference between the base address and the address of the lowest segment. + BaseSegment(u64), + /// The base address is the address of the first byte of the lowest section. + /// + /// To get a delta, calculate the difference between the base address and the address of the lowest section. + BaseSection(u64), +} + +#[derive(Debug, Clone, Serialize)] pub struct ID0Info { - pub base_address: Option<u64>, + pub base_address: BaseAddressInfo, pub segments: Vec<SegmentInfo>, pub functions: Vec<FunctionInfo>, pub comments: Vec<CommentInfo>, pub labels: Vec<LabelInfo>, + pub exports: Vec<ExportInfo>, } #[derive(Debug, Clone, Serialize)] @@ -71,6 +93,7 @@ pub struct DirTreeInfo { pub types: Vec<TILTypeInfo>, /// Contains both function and data names (along with their types). pub names: Vec<NameInfo>, + pub comments: Vec<CommentInfo>, } #[derive(Debug, Clone, Serialize, Default)] @@ -124,6 +147,7 @@ impl IDBInfo { address: label.address, ty: None, label: Some(label.label.clone()), + exported: false, }); } @@ -132,6 +156,7 @@ impl IDBInfo { address: func.address, ty: func.ty.clone(), label: func.name.clone(), + exported: false, }); } } @@ -172,6 +197,24 @@ impl IDBInfo { }); types } + + pub fn merged_comments(&self) -> Vec<CommentInfo> { + let mut comments = Vec::new(); + if let Some(id0) = &self.id0 { + comments.extend(id0.comments.clone()); + } + if let Some(dir_tree) = &self.dir_tree { + comments.extend(dir_tree.comments.clone()); + } + comments.sort_by_key(|c| c.address); + comments.dedup_by(|a, b| { + if a.address != b.address { + return false; + } + a.is_repeatable == b.is_repeatable + }); + comments + } } /// Parsed the IDB data into [`IDBInfo`]. @@ -314,32 +357,32 @@ impl IDBFileParser { address: func_start, is_library: func.flags.is_lib(), is_no_return: func.flags.is_no_return(), - is_entry: false, }); } } } } + let mut exports = Vec::new(); if let Ok(entry_points) = id0.entry_points(&root_info) { for entry in entry_points { - // TODO: What to do with entry.forwarded? - functions.push(FunctionInfo { - name: Some(entry.name), - ty: entry.entry_type, + exports.push(ExportInfo { + name: entry.name, address: entry.address.into_u64(), - is_library: false, - is_no_return: false, - is_entry: true, + ty: entry.entry_type, }); } } - let base_address = match root_info.addresses.loading_base.into_u64() { + let min_ea = root_info.addresses.min_ea.into_raw().into_u64(); + let loading_base = root_info.addresses.loading_base.into_u64(); + let base_address = match (loading_base, min_ea) { + (0, 0) => BaseAddressInfo::None, // An IDB with zero loading base is possibly not loaded there. // For example, see the FlawedGrace.idb in the idb-rs resources directory. - 0 => None, - loading_base => Some(loading_base.into_u64()), + // Instead, we will want to use the lowest section address. + (0, min_ea) => BaseAddressInfo::BaseSection(min_ea), + (loading_base, _) => BaseAddressInfo::BaseSegment(loading_base.into_u64()), }; Ok(ID0Info { @@ -348,6 +391,7 @@ impl IDBFileParser { functions, comments, labels, + exports, }) } @@ -421,10 +465,51 @@ impl IDBFileParser { address: func_addr, is_library: false, is_no_return: false, - is_entry: false, })) }; + let comment_info_from_addr = |addr_info: &AddressInfo<K>| -> Vec<CommentInfo> { + let mut comments = Vec::new(); + if let Some(comment) = addr_info.comment() { + comments.push(CommentInfo { + address: addr_info.address().into_raw().into_u64(), + comment: comment.to_string(), + is_repeatable: false, + }); + } + if let Some(comment) = addr_info.comment_repeatable() { + comments.push(CommentInfo { + address: addr_info.address().into_raw().into_u64(), + comment: comment.to_string(), + is_repeatable: true, + }) + } + if let Some(pre_comments) = addr_info.comment_pre() { + for comment in pre_comments { + comments.push(CommentInfo { + address: addr_info.address().into_raw().into_u64(), + comment: comment.to_string(), + is_repeatable: false, + }) + } + } + if let Some(post_comments) = addr_info.comment_post() { + for comment in post_comments { + comments.push(CommentInfo { + address: addr_info.address().into_raw().into_u64(), + comment: comment.to_string(), + is_repeatable: false, + }) + } + } + comments + }; + + let mut comments = Vec::new(); + for (addr_info, _) in all_address_info(id0, id1, id2, netdelta) { + comments.extend(comment_info_from_addr(&addr_info)); + } + let mut functions = Vec::new(); if let Some(func_dir_tree) = id0.dirtree_function_address()? { func_dir_tree.visit_leafs(|addr_raw| { @@ -446,6 +531,7 @@ impl IDBFileParser { address: info.address().into_raw().into_u64(), ty: info.tinfo(&root_info).ok().flatten().map(|t| t.clone()), label: info.label().ok().flatten().map(|s| s.to_string()), + exported: false, }); } }); @@ -466,6 +552,7 @@ impl IDBFileParser { functions, types, names, + comments, }) } } |
