Skip to content

Commit 2c37899

Browse files
committed
More rust cleanup
- Fixed the issue with PDB types, this has caused me an insane amount of grief - Fixed LLIL visit_tree missing LLIL_LOAD expressions - Added LLIL visitor test - Made all WARP file pickers use the rfd crate
1 parent b1693fd commit 2c37899

File tree

9 files changed

+99
-33
lines changed

9 files changed

+99
-33
lines changed

plugins/pdb-ng/src/struct_grouper.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ pub fn group_structure(
360360
warn!("{} Could not resolve structure groups: {}", name, e);
361361
for member in members {
362362
structure.insert(
363-
&member.ty.clone(),
363+
&member.ty,
364364
member.name.clone(),
365365
member.offset,
366366
false,
@@ -389,7 +389,7 @@ fn apply_groups(
389389

390390
if offset > member.offset {
391391
structure.insert(
392-
&member.ty.clone(),
392+
&member.ty,
393393
member.name.clone(),
394394
0,
395395
false,
@@ -398,7 +398,7 @@ fn apply_groups(
398398
);
399399
} else {
400400
structure.insert(
401-
&member.ty.clone(),
401+
&member.ty,
402402
member.name.clone(),
403403
member.offset - offset,
404404
false,
@@ -449,6 +449,7 @@ fn resolve_struct_groups(members: Vec<MemberSize>) -> Result<Vec<ResolvedGroup>>
449449
max_width = max_width.max(member.offset + member.width);
450450
}
451451

452+
// TODO: has overlapping is probably failing.
452453
if !has_overlapping {
453454
// Nothing overlaps, just add em directly
454455
return Ok(members

plugins/pdb-ng/src/type_parser.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2075,7 +2075,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> {
20752075
fn is_name_anonymous(name: &QualifiedName) -> bool {
20762076
match name.items.last() {
20772077
Some(item) if item == "<anonymous-tag>" => true,
2078-
Some(item) if item.starts_with("<unnamed-") => true,
2078+
Some(item) if item.contains("<unnamed-") => true,
20792079
_ => false,
20802080
}
20812081
}
@@ -2210,6 +2210,7 @@ impl<'a, S: Source<'a> + 'a> PDBParserInstance<'a, S> {
22102210
// No? We're just going to do something close and leave it to the users to figure out the rest
22112211
// There's no way I'm digging through all nonsense
22122212

2213+
// Glenn: "Never mind this got deleted... MS has done it again"
22132214
// After a quick GitHub discussion (https://github.com/MicrosoftDocs/cpp-docs/issues/4152)
22142215
// I've determined this is unknowable.
22152216
// Microsoft does it again!!!!

plugins/warp/benches/convert.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub fn type_conversion_benchmark(c: &mut Criterion) {
2525
c.bench_function("type conversion all types", |b| {
2626
b.iter(|| {
2727
for ty in &types {
28-
from_bn_type(&bv, &ty.type_object(), u8::MAX);
28+
from_bn_type(&bv, &ty.ty, u8::MAX);
2929
}
3030
})
3131
});

plugins/warp/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ pub fn basic_block_guid<A: Architecture, M: FunctionMutability>(
128128

129129
let is_variant_instr = |instr: &LowLevelILInstruction<A, M, NonSSA<RegularNonSSA>>| {
130130
let is_variant_expr = |expr: &LowLevelILExpressionKind<A, M, NonSSA<RegularNonSSA>>| {
131+
// TODO: Checking the section here is slow, we should gather all section ranges outside of this.
131132
match expr {
132133
LowLevelILExpressionKind::ConstPtr(op)
133134
if !view.sections_at(op.value()).is_empty() =>

plugins/warp/src/plugin/load.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@ impl Command for LoadSignatureFile {
1010
return;
1111
};
1212

13-
let Some(file) =
14-
binaryninja::interaction::get_open_filename_input("Load Signature File", "*.sbin")
13+
// NOTE: Because we only can consume signatures from a specific directory, we don't need to use the interaction API.
14+
// If we did need to load signature files from a project than this would need to change.
15+
let Some(file) = rfd::FileDialog::new()
16+
.add_filter("Signature Files", &["sbin"])
17+
.set_file_name(format!("{}.sbin", view.file().filename()))
18+
.pick_file()
1519
else {
1620
return;
1721
};

plugins/warp/src/plugin/types.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ pub struct LoadTypes;
77

88
impl Command for LoadTypes {
99
fn action(&self, view: &BinaryView) {
10-
let Some(file) = binaryninja::interaction::get_open_filename_input(
11-
"Apply Signature File Types",
12-
"*.sbin",
13-
) else {
10+
// NOTE: Because we only can consume signatures from a specific directory, we don't need to use the interaction API.
11+
// If we did need to load signature files from a project than this would need to change.
12+
let Some(file) = rfd::FileDialog::new()
13+
.add_filter("Signature Files", &["sbin"])
14+
.set_file_name(format!("{}.sbin", view.file().filename()))
15+
.pick_file()
16+
else {
1417
return;
1518
};
1619

rust/src/low_level_il/expression.rs

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,14 @@ where
130130
where
131131
T: FnMut(&LowLevelILExpression<'func, A, M, SSA, ValueExpr>) -> VisitorAction,
132132
{
133-
// First visit the current expression.
134-
let info = self.kind();
133+
// Visit the current expression.
135134
match f(self) {
136-
VisitorAction::Descend => {}
137-
action => return action,
135+
VisitorAction::Descend => {
136+
// Recursively visit sub expressions.
137+
self.kind().visit_sub_expressions(|e| e.visit_tree(f))
138+
}
139+
action => action,
138140
}
139-
// Recursively visit sub expressions.
140-
info.visit_sub_expressions(|e| e.visit_tree(f))
141141
}
142142
}
143143

@@ -165,14 +165,14 @@ where
165165
&LowLevelILExpression<'func, A, M, NonSSA<LiftedNonSSA>, ValueExpr>,
166166
) -> VisitorAction,
167167
{
168-
// First visit the current expression.
169-
let info = self.kind();
168+
// Visit the current expression.
170169
match f(self) {
171-
VisitorAction::Descend => {}
172-
action => return action,
170+
VisitorAction::Descend => {
171+
// Recursively visit sub expressions.
172+
self.kind().visit_sub_expressions(|e| e.visit_tree(f))
173+
}
174+
action => action,
173175
}
174-
// Recursively visit sub expressions.
175-
info.visit_sub_expressions(|e| e.visit_tree(f))
176176
}
177177
}
178178

@@ -200,14 +200,14 @@ where
200200
&LowLevelILExpression<'func, A, M, NonSSA<RegularNonSSA>, ValueExpr>,
201201
) -> VisitorAction,
202202
{
203-
// First visit the current expression.
204-
let info = self.kind();
203+
// Visit the current expression.
205204
match f(self) {
206-
VisitorAction::Descend => {}
207-
action => return action,
205+
VisitorAction::Descend => {
206+
// Recursively visit sub expressions.
207+
self.kind().visit_sub_expressions(|e| e.visit_tree(f))
208+
}
209+
action => action,
208210
}
209-
// Recursively visit sub expressions.
210-
info.visit_sub_expressions(|e| e.visit_tree(f))
211211
}
212212
}
213213

@@ -592,7 +592,11 @@ where
592592
UnimplMem(ref op) => {
593593
visit!(op.mem_expr());
594594
}
595-
_ => {}
595+
Load(ref op) => {
596+
visit!(op.source_mem_expr());
597+
}
598+
// Do not have any sub expressions.
599+
Pop(_) | Reg(_) | RegSplit(_) | Const(_) | ConstPtr(_) | Flag(_) | FlagBit(_) | ExternPtr(_) | FlagCond(_) | FlagGroup(_) | Unimpl(_) | Undef(_) => {}
596600
}
597601

598602
VisitorAction::Sibling

rust/src/low_level_il/instruction.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use binaryninjacore_sys::BNGetLowLevelILByIndex;
2020
use binaryninjacore_sys::BNGetLowLevelILIndexForInstruction;
2121
use binaryninjacore_sys::BNLowLevelILInstruction;
2222
use std::fmt::{Debug, Display, Formatter};
23-
2423
use super::VisitorAction;
2524

2625
#[repr(transparent)]
@@ -340,7 +339,8 @@ where
340339
// TODO: Visit when we support expression lists
341340
}
342341
Value(e) => visit!(e),
343-
_ => {}
342+
// Do not have any sub expressions.
343+
Nop(_) | NoRet(_) | Goto(_) | Syscall(_) | Bp(_) | Trap(_) | Undef(_) => {}
344344
}
345345

346346
VisitorAction::Sibling

rust/tests/low_level_il.rs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use binaryninja::low_level_il::expression::{
77
use binaryninja::low_level_il::instruction::{
88
InstructionHandler, LowLevelILInstructionKind, LowLevelInstructionIndex,
99
};
10-
use binaryninja::low_level_il::LowLevelILRegister;
10+
use binaryninja::low_level_il::{LowLevelILRegister, VisitorAction};
1111
use rstest::*;
1212
use std::path::PathBuf;
1313

@@ -168,3 +168,55 @@ fn test_llil_info(_session: &Session) {
168168
_ => panic!("Expected Ret"),
169169
}
170170
}
171+
172+
#[rstest]
173+
fn test_llil_visitor(_session: &Session) {
174+
let out_dir = env!("OUT_DIR").parse::<PathBuf>().unwrap();
175+
let view = binaryninja::load(out_dir.join("atox.obj")).expect("Failed to create view");
176+
let platform = view.default_platform().unwrap();
177+
178+
// Sample function: __crt_strtox::c_string_character_source<char>::validate
179+
let sample_function = view.function_at(&platform, 0x2bd80).unwrap();
180+
let llil_function = sample_function.low_level_il().unwrap();
181+
let llil_basic_blocks = llil_function.basic_blocks();
182+
let llil_basic_block_iter = llil_basic_blocks.iter();
183+
184+
let mut basic_blocks_visited = 0;
185+
let mut instructions_visited: Vec<LowLevelInstructionIndex> = vec![];
186+
let mut expressions_visited: Vec<LowLevelExpressionIndex> = vec![];
187+
for basic_block in llil_basic_block_iter {
188+
basic_blocks_visited += 1;
189+
for instr in basic_block.iter() {
190+
instructions_visited.push(instr.index);
191+
expressions_visited.push(instr.expr_idx());
192+
instr.visit_tree(&mut |expr| {
193+
expressions_visited.push(expr.index);
194+
VisitorAction::Descend
195+
});
196+
}
197+
}
198+
199+
assert_eq!(basic_blocks_visited, 10);
200+
// This is a flag instruction removed in LLIL.
201+
instructions_visited.push(LowLevelInstructionIndex(38));
202+
for instr_idx in 0..41 {
203+
if instructions_visited.iter().find(|x| x.0 == instr_idx).is_none() {
204+
panic!("Instruction with index {:?} not visited", instr_idx);
205+
};
206+
}
207+
// These are NOP's
208+
expressions_visited.push(LowLevelExpressionIndex(24));
209+
expressions_visited.push(LowLevelExpressionIndex(54));
210+
expressions_visited.push(LowLevelExpressionIndex(62));
211+
expressions_visited.push(LowLevelExpressionIndex(87));
212+
// These are some flag things
213+
expressions_visited.push(LowLevelExpressionIndex(114));
214+
expressions_visited.push(LowLevelExpressionIndex(115));
215+
expressions_visited.push(LowLevelExpressionIndex(116));
216+
expressions_visited.push(LowLevelExpressionIndex(121));
217+
for expr_idx in 0..127 {
218+
if expressions_visited.iter().find(|x| x.0 == expr_idx).is_none() {
219+
panic!("Expression with index {:?} not visited", expr_idx);
220+
};
221+
}
222+
}

0 commit comments

Comments
 (0)