Skip to content

Commit 10c5dac

Browse files
rbranemesare
authored andcommitted
Add more HLIL related functions to rust
1 parent 087a142 commit 10c5dac

File tree

5 files changed

+254
-20
lines changed

5 files changed

+254
-20
lines changed

rust/src/hlil/function.rs

Lines changed: 137 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
11
use std::hash::{Hash, Hasher};
22

3-
use binaryninjacore_sys::BNFreeHighLevelILFunction;
4-
use binaryninjacore_sys::BNGetHighLevelILBasicBlockList;
5-
use binaryninjacore_sys::BNGetHighLevelILIndexForInstruction;
6-
use binaryninjacore_sys::BNGetHighLevelILInstructionCount;
7-
use binaryninjacore_sys::BNGetHighLevelILOwnerFunction;
8-
use binaryninjacore_sys::BNGetHighLevelILRootExpr;
9-
use binaryninjacore_sys::BNGetHighLevelILSSAForm;
10-
use binaryninjacore_sys::BNHighLevelILFunction;
11-
use binaryninjacore_sys::BNNewHighLevelILFunctionReference;
3+
use binaryninjacore_sys::*;
124

5+
use crate::architecture::CoreArchitecture;
136
use crate::basicblock::BasicBlock;
147
use crate::function::Function;
158
use crate::rc::{Array, Ref, RefCountable};
9+
use crate::types::{HighLevelILSSAVariable, SSAVariable, Variable};
1610

1711
use super::{HighLevelILBlock, HighLevelILInstruction, HighLevelILLiftedInstruction};
1812

@@ -73,6 +67,10 @@ impl HighLevelILFunction {
7367
})
7468
}
7569

70+
pub fn set_root(&self, new_root: &HighLevelILInstruction) {
71+
unsafe { BNSetHighLevelILRootExpr(self.handle, new_root.index) }
72+
}
73+
7674
pub fn lifted_root(&self) -> HighLevelILLiftedInstruction {
7775
self.root().lift()
7876
}
@@ -122,6 +120,136 @@ impl HighLevelILFunction {
122120
}
123121
.to_owned()
124122
}
123+
124+
pub fn current_address(&self) -> u64 {
125+
unsafe { BNHighLevelILGetCurrentAddress(self.handle) }
126+
}
127+
128+
pub fn set_current_address(&self, address: u64, arch: Option<CoreArchitecture>) {
129+
let arch = arch.unwrap_or_else(|| self.get_function().arch()).0;
130+
unsafe { BNHighLevelILSetCurrentAddress(self.handle, arch, address) }
131+
}
132+
133+
/// Gets the instruction that contains the given SSA variable's definition.
134+
///
135+
/// Since SSA variables can only be defined once, this will return the single instruction where that occurs.
136+
/// For SSA variable version 0s, which don't have definitions, this will return None instead.
137+
pub fn ssa_variable_definition(&self, variable: SSAVariable) -> Option<HighLevelILInstruction> {
138+
let index = unsafe {
139+
BNGetHighLevelILSSAVarDefinition(
140+
self.handle,
141+
&variable.variable.raw(),
142+
variable.version,
143+
)
144+
};
145+
(index < self.instruction_count())
146+
.then(|| HighLevelILInstruction::new(self.to_owned(), index))
147+
}
148+
149+
pub fn ssa_memory_definition(&self, version: usize) -> Option<HighLevelILInstruction> {
150+
let index = unsafe { BNGetHighLevelILSSAMemoryDefinition(self.handle, version) };
151+
(index < self.instruction_count())
152+
.then(|| HighLevelILInstruction::new(self.to_owned(), index))
153+
}
154+
155+
/// Gets all the instructions that use the given SSA variable.
156+
pub fn ssa_variable_uses(&self, variable: SSAVariable) -> Array<HighLevelILInstruction> {
157+
let mut count = 0;
158+
let instrs = unsafe {
159+
BNGetHighLevelILSSAVarUses(
160+
self.handle,
161+
&variable.variable.raw(),
162+
variable.version,
163+
&mut count,
164+
)
165+
};
166+
assert!(!instrs.is_null());
167+
unsafe { Array::new(instrs, count, self.to_owned()) }
168+
}
169+
170+
pub fn ssa_memory_uses(&self, version: usize) -> Array<HighLevelILInstruction> {
171+
let mut count = 0;
172+
let instrs = unsafe { BNGetHighLevelILSSAMemoryUses(self.handle, version, &mut count) };
173+
assert!(!instrs.is_null());
174+
unsafe { Array::new(instrs, count, self.to_owned()) }
175+
}
176+
177+
/// Determines if `variable` is live at any point in the function
178+
pub fn is_ssa_variable_live(&self, variable: SSAVariable) -> bool {
179+
unsafe {
180+
BNIsHighLevelILSSAVarLive(self.handle, &variable.variable.raw(), variable.version)
181+
}
182+
}
183+
184+
/// Determines if `variable` is live at a given point in the function
185+
pub fn is_ssa_variable_live_at(
186+
&self,
187+
variable: SSAVariable,
188+
instr: &HighLevelILInstruction,
189+
) -> bool {
190+
unsafe {
191+
BNIsHighLevelILSSAVarLiveAt(
192+
self.handle,
193+
&variable.variable.raw(),
194+
variable.version,
195+
instr.index,
196+
)
197+
}
198+
}
199+
200+
pub fn variable_definitions(&self, variable: Variable) -> Array<HighLevelILInstruction> {
201+
let mut count = 0;
202+
let defs = unsafe {
203+
BNGetHighLevelILVariableDefinitions(self.handle, &variable.raw(), &mut count)
204+
};
205+
assert!(!defs.is_null());
206+
unsafe { Array::new(defs, count, self.to_owned()) }
207+
}
208+
209+
pub fn variable_uses(&self, variable: Variable) -> Array<HighLevelILInstruction> {
210+
let mut count = 0;
211+
let instrs =
212+
unsafe { BNGetHighLevelILVariableUses(self.handle, &variable.raw(), &mut count) };
213+
assert!(!instrs.is_null());
214+
unsafe { Array::new(instrs, count, self.to_owned()) }
215+
}
216+
217+
/// Determines if `variable` is live at a given point in the function
218+
pub fn is_variable_live_at(&self, variable: Variable, instr: &HighLevelILInstruction) -> bool {
219+
unsafe { BNIsHighLevelILVarLiveAt(self.handle, &variable.raw(), instr.index) }
220+
}
221+
222+
/// This gets just the HLIL variables - you may be interested in the union
223+
/// of [crate::function::Function::parameter_variables] and
224+
/// [crate::mlil::function::MediumLevelILFunction::aliased_variables] as well for all the
225+
/// variables used in the function
226+
pub fn variables(&self) -> Array<Variable> {
227+
let mut count = 0;
228+
let variables = unsafe { BNGetHighLevelILVariables(self.handle, &mut count) };
229+
assert!(!variables.is_null());
230+
unsafe { Array::new(variables, count, ()) }
231+
}
232+
233+
/// This returns a list of Variables that are taken reference to and used
234+
/// elsewhere. You may also wish to consider [HighLevelILFunction::variables]
235+
/// and [crate::function::Function::parameter_variables]
236+
pub fn aliased_variables(&self) -> Array<Variable> {
237+
let mut count = 0;
238+
let variables = unsafe { BNGetHighLevelILAliasedVariables(self.handle, &mut count) };
239+
assert!(!variables.is_null());
240+
unsafe { Array::new(variables, count, ()) }
241+
}
242+
243+
/// This gets just the HLIL SSA variables - you may be interested in the union
244+
/// of [crate::function::Function::parameter_variables] and
245+
/// [crate::mlil::function::MediumLevelILFunction::aliased_variables] as well for all the
246+
/// variables used in the function
247+
pub fn ssa_variables(&self) -> Array<HighLevelILSSAVariable> {
248+
let mut count = 0;
249+
let variables = unsafe { BNGetHighLevelILVariables(self.handle, &mut count) };
250+
assert!(!variables.is_null());
251+
unsafe { Array::new(variables, count, self.to_owned()) }
252+
}
125253
}
126254

127255
impl ToOwned for HighLevelILFunction {

rust/src/hlil/instruction.rs

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
use binaryninjacore_sys::BNGetHighLevelILByIndex;
2-
use binaryninjacore_sys::BNHighLevelILOperation;
1+
use binaryninjacore_sys::*;
32

43
use crate::architecture::CoreIntrinsic;
4+
use crate::disassembly::DisassemblyTextLine;
55
use crate::operand_iter::OperandIter;
6-
use crate::rc::Ref;
7-
use crate::types::{ConstantData, RegisterValue, RegisterValueType, SSAVariable, Variable};
6+
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref};
7+
use crate::types::{
8+
Conf, ConstantData, RegisterValue, RegisterValueType, SSAVariable, Type, Variable,
9+
};
810

911
use super::operation::*;
1012
use super::{HighLevelILFunction, HighLevelILLiftedInstruction, HighLevelILLiftedInstructionKind};
@@ -884,6 +886,48 @@ impl HighLevelILInstruction {
884886
}
885887
}
886888

889+
/// HLIL text lines
890+
pub fn lines(&self) -> Array<DisassemblyTextLine> {
891+
let mut count = 0;
892+
let lines = unsafe {
893+
BNGetHighLevelILExprText(
894+
self.function.handle,
895+
self.index,
896+
self.function.full_ast,
897+
&mut count,
898+
core::ptr::null_mut(),
899+
)
900+
};
901+
unsafe { Array::new(lines, count, ()) }
902+
}
903+
904+
/// Type of expression
905+
pub fn expr_type(&self) -> Option<Conf<Ref<Type>>> {
906+
let result = unsafe { BNGetHighLevelILExprType(self.function.handle, self.index) };
907+
(!result.type_.is_null()).then(|| {
908+
Conf::new(
909+
unsafe { Type::ref_from_raw(result.type_) },
910+
result.confidence,
911+
)
912+
})
913+
}
914+
915+
/// Version of active memory contents in SSA form for this instruction
916+
pub fn ssa_memory_version(&self) -> usize {
917+
unsafe { BNGetHighLevelILSSAMemoryVersionAtILInstruction(self.function.handle, self.index) }
918+
}
919+
920+
pub fn ssa_variable_version(&self, variable: Variable) -> SSAVariable {
921+
let version = unsafe {
922+
BNGetHighLevelILSSAVarVersionAtILInstruction(
923+
self.function.handle,
924+
&variable.raw(),
925+
self.index,
926+
)
927+
};
928+
SSAVariable { variable, version }
929+
}
930+
887931
fn lift_operand(&self, expr_idx: usize) -> Box<HighLevelILLiftedInstruction> {
888932
Box::new(self.function.lifted_instruction_from_idx(expr_idx))
889933
}
@@ -963,6 +1007,22 @@ impl HighLevelILInstruction {
9631007
}
9641008
}
9651009

1010+
impl CoreArrayProvider for HighLevelILInstruction {
1011+
type Raw = usize;
1012+
type Context = Ref<HighLevelILFunction>;
1013+
type Wrapped<'a> = Self;
1014+
}
1015+
1016+
unsafe impl CoreArrayProviderInner for HighLevelILInstruction {
1017+
unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
1018+
unsafe { BNFreeILInstructionList(raw) }
1019+
}
1020+
1021+
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
1022+
Self::new(context.clone(), *raw)
1023+
}
1024+
}
1025+
9661026
impl core::fmt::Debug for HighLevelILInstruction {
9671027
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
9681028
write!(

rust/src/hlil/operation.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
use binaryninjacore_sys::BNGetGotoLabelName;
1+
use core::ffi;
2+
3+
use binaryninjacore_sys::*;
24

35
use crate::architecture::CoreIntrinsic;
46
use crate::function::Function;
57
use crate::rc::Ref;
6-
use crate::string::BnString;
8+
use crate::string::{BnStrCompatible, BnString};
79
use crate::types::{ConstantData, SSAVariable, Variable};
810

911
use super::HighLevelILLiftedInstruction;
@@ -18,6 +20,17 @@ impl GotoLabel {
1820
pub fn name(&self) -> BnString {
1921
unsafe { BnString::from_raw(BNGetGotoLabelName(self.function.handle, self.target)) }
2022
}
23+
24+
fn set_name<S: BnStrCompatible>(&self, name: S) {
25+
let raw = name.into_bytes_with_nul();
26+
unsafe {
27+
BNSetUserGotoLabelName(
28+
self.function.handle,
29+
self.target,
30+
raw.as_ref().as_ptr() as *const ffi::c_char,
31+
)
32+
}
33+
}
2134
}
2235

2336
// ADC, SBB, RLC, RRC
@@ -315,6 +328,16 @@ pub struct LiftedLabel {
315328
pub target: GotoLabel,
316329
}
317330

331+
impl LiftedLabel {
332+
pub fn name(&self) -> BnString {
333+
self.target.name()
334+
}
335+
336+
pub fn set_name<S: BnStrCompatible>(&self, name: S) {
337+
self.target.set_name(name)
338+
}
339+
}
340+
318341
// IF
319342
#[derive(Copy, Clone)]
320343
pub struct If {

rust/src/mlil/function.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ use crate::function::{Function, Location};
1111
use crate::rc::{Array, CoreArrayProvider, CoreArrayProviderInner, Ref, RefCountable};
1212
use crate::string::BnStrCompatible;
1313
use crate::types::{
14-
Conf, PossibleValueSet, RegisterValue, SSAVariable, Type, UserVariableValues, Variable,
14+
Conf, MediumLevelILSSAVariable, PossibleValueSet, RegisterValue, SSAVariable, Type,
15+
UserVariableValues, Variable,
1516
};
1617

1718
use super::{MediumLevelILBlock, MediumLevelILInstruction, MediumLevelILLiftedInstruction};
@@ -571,7 +572,7 @@ impl MediumLevelILFunction {
571572
/// union of [MediumLevelILFunction::aliased_variables] and
572573
/// [crate::function::Function::parameter_variables] for all the
573574
/// variables used in the function.
574-
pub fn ssa_variables(&self) -> Array<Array<SSAVariable>> {
575+
pub fn ssa_variables(&self) -> Array<MediumLevelILSSAVariable> {
575576
let mut count = 0;
576577
let vars = unsafe { BNGetMediumLevelILVariables(self.handle, &mut count) };
577578
unsafe { Array::new(vars, count, self.to_owned()) }

rust/src/types.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use crate::{
2424
callingconvention::CallingConvention,
2525
filemetadata::FileMetadata,
2626
function::Function,
27+
hlil::HighLevelILFunction,
2728
mlil::MediumLevelILFunction,
2829
rc::*,
2930
string::{raw_to_string, BnStrCompatible, BnString},
@@ -1491,13 +1492,14 @@ unsafe impl CoreArrayProviderInner for SSAVariable {
14911492
}
14921493
}
14931494

1494-
impl CoreArrayProvider for Array<SSAVariable> {
1495+
pub struct MediumLevelILSSAVariable;
1496+
impl CoreArrayProvider for MediumLevelILSSAVariable {
14951497
type Raw = BNVariable;
14961498
type Context = Ref<MediumLevelILFunction>;
1497-
type Wrapped<'a> = Self;
1499+
type Wrapped<'a> = Array<SSAVariable>;
14981500
}
14991501

1500-
unsafe impl CoreArrayProviderInner for Array<SSAVariable> {
1502+
unsafe impl CoreArrayProviderInner for MediumLevelILSSAVariable {
15011503
unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
15021504
BNFreeVariableList(raw)
15031505
}
@@ -1510,6 +1512,26 @@ unsafe impl CoreArrayProviderInner for Array<SSAVariable> {
15101512
}
15111513
}
15121514

1515+
pub struct HighLevelILSSAVariable;
1516+
impl CoreArrayProvider for HighLevelILSSAVariable {
1517+
type Raw = BNVariable;
1518+
type Context = Ref<HighLevelILFunction>;
1519+
type Wrapped<'a> = Array<SSAVariable>;
1520+
}
1521+
1522+
unsafe impl CoreArrayProviderInner for HighLevelILSSAVariable {
1523+
unsafe fn free(raw: *mut Self::Raw, _count: usize, _context: &Self::Context) {
1524+
BNFreeVariableList(raw)
1525+
}
1526+
1527+
unsafe fn wrap_raw<'a>(raw: &'a Self::Raw, context: &'a Self::Context) -> Self::Wrapped<'a> {
1528+
let mut count = 0;
1529+
let versions =
1530+
unsafe { BNGetHighLevelILVariableSSAVersions(context.handle, raw, &mut count) };
1531+
Array::new(versions, count, Variable::from_raw(*raw))
1532+
}
1533+
}
1534+
15131535
///////////////
15141536
// NamedVariable
15151537

0 commit comments

Comments
 (0)