diff options
| author | KyleMiles <krm504@nyu.edu> | 2023-06-27 13:23:41 -0400 |
|---|---|---|
| committer | KyleMiles <krm504@nyu.edu> | 2023-07-10 12:58:35 -0400 |
| commit | 0c2634e6791af365acd37c47ca22e571ec1d847c (patch) | |
| tree | c8566563cc006fdeef1cfd55dc213e878ca3cdd8 /rust/examples | |
| parent | 0cf69ff7ba7001c0c9ef6754f2dc5f98377d9561 (diff) | |
DWARF Export : Improve Default Parameter Handling
Diffstat (limited to 'rust/examples')
| -rw-r--r-- | rust/examples/dwarf/dwarf_export/src/edit_distance.rs | 44 | ||||
| -rw-r--r-- | rust/examples/dwarf/dwarf_export/src/lib.rs | 112 |
2 files changed, 110 insertions, 46 deletions
diff --git a/rust/examples/dwarf/dwarf_export/src/edit_distance.rs b/rust/examples/dwarf/dwarf_export/src/edit_distance.rs new file mode 100644 index 00000000..9f135451 --- /dev/null +++ b/rust/examples/dwarf/dwarf_export/src/edit_distance.rs @@ -0,0 +1,44 @@ +pub(crate) fn distance(a: &str, b: &str) -> usize { + if a == b { + return 0; + } + match (a.chars().count(), b.chars().count()) { + (0, b) => return b, + (a, 0) => return a, + // (a_len, b_len) if a_len < b_len => return distance(b, a), + _ => (), + } + + let mut result = 0; + let mut cache: Vec<usize> = (1..a.chars().count() + 1).collect(); + + for (index_b, char_b) in b.chars().enumerate() { + result = index_b; + let mut distance_a = index_b; + + for (index_a, char_a) in a.chars().enumerate() { + let distance_b = if char_a == char_b { + distance_a + } else { + distance_a + 1 + }; + + distance_a = cache[index_a]; + + result = if distance_a > result { + if distance_b > result { + result + 1 + } else { + distance_b + } + } else if distance_b > distance_a { + distance_a + 1 + } else { + distance_b + }; + + cache[index_a] = result; + } + } + result +} diff --git a/rust/examples/dwarf/dwarf_export/src/lib.rs b/rust/examples/dwarf/dwarf_export/src/lib.rs index c47be66c..9157d94f 100644 --- a/rust/examples/dwarf/dwarf_export/src/lib.rs +++ b/rust/examples/dwarf/dwarf_export/src/lib.rs @@ -1,3 +1,5 @@ +mod edit_distance; + use gimli::{ constants, write::{ @@ -15,6 +17,7 @@ use binaryninja::{ interaction::{FormResponses, FormResponses::Index}, logger::init, rc::Ref, + string::BnString, symbol::SymbolType, types::{Conf, MemberAccess, StructureType, Type, TypeClass}, }; @@ -490,46 +493,60 @@ fn export_data_vars( } } -fn present_form() -> Vec<FormResponses> { +fn present_form(bv_arch: &str) -> Vec<FormResponses> { // TODO : Verify inputs (like save location) so that we can fail early // TODO : Add Language field // TODO : Choose to export types/functions/etc + let archs = [ + "Unknown", + "Aarch64", + "Aarch64_Ilp32", + "Arm", + "Avr", + "Bpf", + "I386", + "X86_64", + "X86_64_X32", + "Hexagon", + "LoongArch64", + "Mips", + "Mips64", + "Msp430", + "PowerPc", + "PowerPc64", + "Riscv32", + "Riscv64", + "S390x", + "Sbf", + "Sparc64", + "Wasm32", + "Xtensa", + ]; interaction::FormInputBuilder::new() - .save_file_field("Save Location", None, None, None) - .choice_field( - "Architecture", - &[ - "Unknown", - "Aarch64", - "Aarch64_Ilp32", - "Arm", - "Avr", - "Bpf", - "I386", - "X86_64", - "X86_64_X32", - "Hexagon", - "LoongArch64", - "Mips", - "Mips64", - "Msp430", - "PowerPc", - "PowerPc64", - "Riscv32", - "Riscv64", - "S390x", - "Sbf", - "Sparc64", - "Wasm32", - "Xtensa", - ], + .save_file_field( + "Save Location", + Some("Debug Files (*.dwo *.debug);;All Files (*)"), + None, None, ) .choice_field( - "Container Format", - &["Coff", "Elf", "MachO", "Pe", "Wasm", "Xcoff"], - None, + "Architecture", + &archs, + archs + .iter() + .enumerate() + .min_by(|&(_, arch_name_1), &(_, arch_name_2)| { + edit_distance::distance(bv_arch, arch_name_1) + .cmp(&edit_distance::distance(bv_arch, arch_name_2)) + }) + .map(|(index, _)| index), ) + // Add actual / better support for formats other than elf? + // .choice_field( + // "Container Format", + // &["Coff", "Elf", "MachO", "Pe", "Wasm", "Xcoff"], + // None, + // ) .get_form_input("Export as DWARF") } @@ -569,21 +586,19 @@ fn write_dwarf<T: gimli::Endianity>( _ => Architecture::Unknown, }; - let format = match responses[2] { - Index(0) => BinaryFormat::Coff, - Index(1) => BinaryFormat::Elf, - Index(2) => BinaryFormat::MachO, - Index(3) => BinaryFormat::Pe, - Index(4) => BinaryFormat::Wasm, - Index(5) => BinaryFormat::Xcoff, - _ => BinaryFormat::Elf, - }; + // let format = match responses[2] { + // Index(0) => BinaryFormat::Coff, + // Index(1) => BinaryFormat::Elf, + // Index(2) => BinaryFormat::MachO, + // Index(3) => BinaryFormat::Pe, + // Index(4) => BinaryFormat::Wasm, + // Index(5) => BinaryFormat::Xcoff, + // _ => BinaryFormat::Elf, + // }; - // TODO : Properly determine output format (without user input) - // TODO : Properly determine architecture (without user input) // TODO : Look in to other options (mangling, flags, etc (see Object::new)) let mut out_object = write::Object::new( - format, + BinaryFormat::Elf, arch, if endian.is_little_endian() { object::Endianness::Little @@ -634,7 +649,12 @@ fn write_dwarf<T: gimli::Endianity>( } fn export_dwarf(bv: &BinaryView) { - let responses = present_form(); + let arch_name = if let Some(arch) = bv.default_arch() { + arch.name() + } else { + BnString::new("Unknown") + }; + let responses = present_form(&arch_name); let encoding = gimli::Encoding { format: gimli::Format::Dwarf32, @@ -678,7 +698,7 @@ impl Command for MyCommand { #[no_mangle] pub extern "C" fn CorePluginInit() -> bool { - init(LevelFilter::Info).expect("Unable to initialize logger"); + init(LevelFilter::Debug).expect("Unable to initialize logger"); register( "Export as DWARF", |
