summaryrefslogtreecommitdiff
path: root/rust/examples
diff options
context:
space:
mode:
authorKyleMiles <krm504@nyu.edu>2023-06-27 13:23:41 -0400
committerKyleMiles <krm504@nyu.edu>2023-07-10 12:58:35 -0400
commit0c2634e6791af365acd37c47ca22e571ec1d847c (patch)
treec8566563cc006fdeef1cfd55dc213e878ca3cdd8 /rust/examples
parent0cf69ff7ba7001c0c9ef6754f2dc5f98377d9561 (diff)
DWARF Export : Improve Default Parameter Handling
Diffstat (limited to 'rust/examples')
-rw-r--r--rust/examples/dwarf/dwarf_export/src/edit_distance.rs44
-rw-r--r--rust/examples/dwarf/dwarf_export/src/lib.rs112
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",