Skip to content

Commit 161a57c

Browse files
committed
add idb_import plugin til dependencies prompts
1 parent 7612a20 commit 161a57c

File tree

2 files changed

+310
-219
lines changed

2 files changed

+310
-219
lines changed

plugins/idb_import/src/lib.rs

Lines changed: 82 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
mod types;
2-
use std::path::Path;
2+
use std::fs::File;
3+
use std::io::BufReader;
34

45
use binaryninja::command::Command;
6+
use binaryninja::string::BnStrCompatible;
57
use binaryninja::type_library::TypeLibrary;
68
use binaryninja::types::QualifiedName;
79
use types::*;
@@ -41,7 +43,7 @@ impl CustomDebugInfoParser for IDBDebugInfoParser {
4143
debug_file: &BinaryView,
4244
progress: Box<dyn Fn(usize, usize) -> Result<(), ()>>,
4345
) -> bool {
44-
match parse_idb_info(debug_info, bv, debug_file, progress) {
46+
match import_idb_info(debug_info, bv, debug_file, progress) {
4547
Ok(()) => true,
4648
Err(error) => {
4749
error!("Unable to parse IDB file: {error}");
@@ -68,7 +70,7 @@ impl CustomDebugInfoParser for TILDebugInfoParser {
6870
debug_file: &BinaryView,
6971
progress: Box<dyn Fn(usize, usize) -> Result<(), ()>>,
7072
) -> bool {
71-
match parse_til_info(debug_info, bv, debug_file, progress) {
73+
match import_til_info_from_debug_file(debug_info, bv, debug_file, progress) {
7274
Ok(()) => true,
7375
Err(error) => {
7476
error!("Unable to parse TIL file: {error}");
@@ -124,79 +126,59 @@ impl std::io::Seek for BinaryViewReader<'_> {
124126
}
125127
}
126128

127-
fn parse_idb_info(
129+
fn dummy_progress(_: usize, _: usize) -> Result<(), ()> {
130+
Ok(())
131+
}
132+
133+
fn import_idb_info<P: Fn(usize, usize) -> Result<(), ()>>(
128134
debug_info: &mut DebugInfo,
129135
bv: &BinaryView,
130136
debug_file: &BinaryView,
131-
progress: Box<dyn Fn(usize, usize) -> Result<(), ()>>,
137+
progress: P,
132138
) -> Result<()> {
133139
trace!("Opening a IDB file");
134-
let file = BinaryViewReader {
140+
let file = BufReader::new(BinaryViewReader {
135141
bv: debug_file,
136142
offset: 0,
137-
};
143+
});
138144
trace!("Parsing a IDB file");
139-
let file = std::io::BufReader::new(file);
140145
let mut parser = idb_rs::IDBParser::new(file)?;
141146

142-
let default_arch = bv
143-
.default_arch()
144-
.ok_or_else(|| anyhow!("Unable to get the default arch"))?;
145-
let filename = debug_file.file().filename();
146-
let mut type_lib = TypeLibrary::new(default_arch, filename);
147-
148147
if let Some(til_section) = parser.til_section_offset() {
149148
// TODO handle dependency, create a function for that with closures
150149
trace!("Parsing the TIL section");
151150
let til = parser.read_til_section(til_section)?;
152-
// progress 0%-50%
153-
import_til_section(&mut type_lib, debug_file, &til, progress)?;
151+
let filename = debug_file.file().filename();
152+
// TODO progress 0%-50%
153+
import_til_to_type_library(til, filename, bv, progress)?;
154154
}
155155

156-
if !type_lib.finalize() {
157-
return Err(anyhow!("Unable to finalize TypeLibrary"));
158-
};
159-
bv.add_type_library(&type_lib);
160-
161156
if let Some(id0_section) = parser.id0_section_offset() {
162157
trace!("Parsing the ID0 section");
163158
let id0 = parser.read_id0_section(id0_section)?;
164-
// progress 50%-100%
159+
// TODO progress 50%-100%
165160
parse_id0_section_info(debug_info, bv, debug_file, &id0)?;
166161
}
167162

168163
Ok(())
169164
}
170165

171-
fn parse_til_info(
166+
fn import_til_info_from_debug_file<P: Fn(usize, usize) -> Result<(), ()>>(
172167
_debug_info: &mut DebugInfo,
173168
bv: &BinaryView,
174169
debug_file: &BinaryView,
175-
progress: Box<dyn Fn(usize, usize) -> Result<(), ()>>,
170+
progress: P,
176171
) -> Result<()> {
177172
trace!("Opening a TIL file");
178173
let file = BinaryViewReader {
179174
bv: debug_file,
180175
offset: 0,
181176
};
182-
let mut file = std::io::BufReader::new(file);
183-
184-
let default_arch = bv
185-
.default_arch()
186-
.ok_or_else(|| anyhow!("Unable to get the default arch"))?;
187177
let filename = debug_file.file().filename();
188-
let mut type_lib = TypeLibrary::new(default_arch, filename);
189-
190-
trace!("Parsing the TIL section");
178+
let mut file = std::io::BufReader::new(file);
191179
let til = TILSection::read(&mut file, idb_rs::IDBSectionCompression::None)?;
192-
// TODO handle dependency, create a function for that with closures
193-
import_til_section(&mut type_lib, debug_file, &til, progress)?;
194180

195-
if !type_lib.finalize() {
196-
return Err(anyhow!("Unable to finalize TypeLibrary"));
197-
};
198-
bv.add_type_library(&type_lib);
199-
Ok(())
181+
import_til_to_type_library(til, filename, bv, progress)
200182
}
201183

202184
fn interactive_import_til(view: &BinaryView) -> Result<()> {
@@ -206,83 +188,115 @@ fn interactive_import_til(view: &BinaryView) -> Result<()> {
206188
return Ok(());
207189
};
208190

191+
let filename = file.file_name().unwrap().to_string_lossy();
192+
let mut file = BufReader::new(File::open(&file)?);
193+
let til = TILSection::read(&mut file, idb_rs::IDBSectionCompression::None)?;
194+
195+
// TODO remove the extension?
196+
import_til_to_type_library(til, filename, view, dummy_progress)
197+
}
198+
199+
fn import_til_to_type_library<S, P>(
200+
til: TILSection,
201+
type_lib_name: S,
202+
view: &BinaryView,
203+
progress: P,
204+
) -> Result<()>
205+
where
206+
S: BnStrCompatible,
207+
P: Fn(usize, usize) -> Result<(), ()>,
208+
{
209209
let default_arch = view
210210
.default_arch()
211211
.ok_or_else(|| anyhow!("Unable to get the default arch"))?;
212-
let filename = file.file_name().unwrap().to_string_lossy();
213-
let mut type_lib = TypeLibrary::new(default_arch, filename);
212+
let mut type_lib = TypeLibrary::new(default_arch, type_lib_name);
214213

215-
interactive_import_til_file(file.as_path(), view, &mut type_lib)?;
214+
// TODO create a background task to not freeze bn, also create a progress
215+
// user interface feedback
216+
import_til_file(til, view, &mut type_lib, progress)?;
216217
if !type_lib.finalize() {
217218
return Err(anyhow!("Unable to finalize TypeLibrary"));
218219
};
219220
view.add_type_library(&type_lib);
220221
Ok(())
221222
}
222223

223-
fn interactive_import_til_file(
224-
file: &Path,
224+
fn import_til_file<P: Fn(usize, usize) -> Result<(), ()>>(
225+
til: TILSection,
225226
view: &BinaryView,
226227
type_library: &mut TypeLibrary,
228+
progress: P,
227229
) -> Result<()> {
228-
// TODO create a background task to not freeze bn, also create a progress
229-
// user interface feedback
230-
let file = std::fs::File::open(file)?;
231-
let mut file = std::io::BufReader::new(file);
232-
let til = TILSection::read(&mut file, idb_rs::IDBSectionCompression::None)?;
233-
for dep in &til.header.dependencies {
234-
let name = dep.as_utf8_lossy();
230+
trace!("Parsing the TIL section");
231+
// TODO
232+
let mut tils = vec![til];
233+
import_til_dependency(&mut tils, 0, &progress)?;
234+
import_til_section(type_library, view, &tils, progress)
235+
}
236+
237+
fn import_til_dependency<P: Fn(usize, usize) -> Result<(), ()>>(
238+
tils: &mut Vec<TILSection>,
239+
til_idx: usize,
240+
_progress: &P,
241+
) -> Result<()> {
242+
let names: Vec<_> = tils[til_idx].header.dependencies.to_vec();
243+
for name in names {
244+
let name = name.as_utf8_lossy();
235245
let message = format!("Select the dependency \"{name}.til\"",);
236246
let Some(dep_file) = binaryninja::interaction::get_open_filename_input(&message, "*.til")
237247
else {
238248
return Err(anyhow!("Unable to get the dependency {name}"));
239249
};
240250

241-
interactive_import_til_file(dep_file.as_path(), view, type_library)
242-
.context("While importing dependency {name}")?;
251+
let mut dep_file = BufReader::new(File::open(&dep_file)?);
252+
let dep_til = TILSection::read(&mut dep_file, idb_rs::IDBSectionCompression::None)?;
253+
tils.push(dep_til);
243254
}
244-
245-
fn dummy_progress(_: usize, _: usize) -> Result<(), ()> {
246-
Ok(())
255+
if tils.len() > til_idx + 1 {
256+
// add dependencies of dependencies
257+
// TODO handle progress
258+
// TODO identify ciclycal dependencies
259+
import_til_dependency(tils, til_idx + 1, _progress)
260+
.context("While importing dependency {name}")?;
247261
}
248-
import_til_section(type_library, view, &til, dummy_progress)
262+
Ok(())
249263
}
250264

251-
fn import_til_section(
265+
fn import_til_section<P: Fn(usize, usize) -> Result<(), ()>>(
252266
type_library: &mut TypeLibrary,
253267
view: &BinaryView,
254-
til: &TILSection,
255-
progress: impl Fn(usize, usize) -> Result<(), ()>,
268+
tils: &[TILSection],
269+
progress: P,
256270
) -> Result<()> {
257271
let default_arch = view
258272
.default_arch()
259273
.ok_or_else(|| anyhow!("Unable to get the default arch"))?;
260-
let types = types::translate_til_types(default_arch, til, progress)?;
274+
let types = types::translate_tils_types(default_arch, tils, progress)?;
261275

262276
// print any errors
263-
print_til_convertsion_errors(&types);
277+
print_til_convertsion_errors(&types)?;
264278

265279
// add all type to the type library
266280
for ty in &types {
267281
if let TranslateTypeResult::Translated(bn_ty)
268282
| TranslateTypeResult::PartiallyTranslated(bn_ty, _) = &ty.ty
269283
{
270284
let name = QualifiedName::new(vec![ty.name.as_utf8_lossy().to_string()]);
271-
type_library.add_named_type(name, &bn_ty);
285+
type_library.add_named_type(name, bn_ty);
272286
}
273287
}
274288

275289
Ok(())
276290
}
277291

278-
fn print_til_convertsion_errors(types: &[TranslatesIDBType]) {
292+
fn print_til_convertsion_errors(types: &[TranslatesIDBType]) -> Result<()> {
279293
for ty in types {
280294
match &ty.ty {
281295
TranslateTypeResult::NotYet => {
282-
panic!(
283-
"type could not be processed `{}`: {:#?}",
296+
// NOTE this should be unreachable
297+
error!(
298+
"Unable to finish parsing type `{}`",
284299
ty.name.as_utf8_lossy(),
285-
&ty.og_ty
286300
);
287301
}
288302
TranslateTypeResult::Error(error) => {
@@ -307,6 +321,7 @@ fn print_til_convertsion_errors(types: &[TranslatesIDBType]) {
307321
TranslateTypeResult::Translated(_) => {}
308322
};
309323
}
324+
Ok(())
310325
}
311326

312327
fn parse_id0_section_info(

0 commit comments

Comments
 (0)