Skip to content

Commit 3355345

Browse files
committed
Add After variants for looking up variables at instructions
Fixes #6397
1 parent 1473293 commit 3355345

File tree

8 files changed

+188
-1
lines changed

8 files changed

+188
-1
lines changed

binaryninjaapi.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10956,6 +10956,7 @@ namespace BinaryNinja {
1095610956
void DeleteAutoStackVariable(int64_t offset);
1095710957
void DeleteUserStackVariable(int64_t offset);
1095810958
bool GetStackVariableAtFrameOffset(Architecture* arch, uint64_t addr, int64_t offset, VariableNameAndType& var);
10959+
bool GetStackVariableAtFrameOffsetAfterInstruction(Architecture* arch, uint64_t addr, int64_t offset, VariableNameAndType& var);
1095910960

1096010961
/*! List of Function Variables
1096110962

@@ -13407,10 +13408,15 @@ namespace BinaryNinja {
1340713408
const std::set<BNDataFlowQueryOption>& options = std::set<BNDataFlowQueryOption>());
1340813409

1340913410
size_t GetSSAVarVersionAtInstruction(const Variable& var, size_t instr) const;
13411+
size_t GetSSAVarVersionAfterInstruction(const Variable& var, size_t instr) const;
1341013412
size_t GetSSAMemoryVersionAtInstruction(size_t instr) const;
13413+
size_t GetSSAMemoryVersionAfterInstruction(size_t instr) const;
1341113414
Variable GetVariableForRegisterAtInstruction(uint32_t reg, size_t instr) const;
13415+
Variable GetVariableForRegisterAfterInstruction(uint32_t reg, size_t instr) const;
1341213416
Variable GetVariableForFlagAtInstruction(uint32_t flag, size_t instr) const;
13417+
Variable GetVariableForFlagAfterInstruction(uint32_t flag, size_t instr) const;
1341313418
Variable GetVariableForStackLocationAtInstruction(int64_t offset, size_t instr) const;
13419+
Variable GetVariableForStackLocationAfterInstruction(int64_t offset, size_t instr) const;
1341413420

1341513421
RegisterValue GetRegisterValueAtInstruction(uint32_t reg, size_t instr);
1341613422
RegisterValue GetRegisterValueAfterInstruction(uint32_t reg, size_t instr);

binaryninjacore.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
// Current ABI version for linking to the core. This is incremented any time
3838
// there are changes to the API that affect linking, including new functions,
3939
// new types, or modifications to existing functions or types.
40-
#define BN_CURRENT_CORE_ABI_VERSION 92
40+
#define BN_CURRENT_CORE_ABI_VERSION 93
4141

4242
// Minimum ABI version that is supported for loading of plugins. Plugins that
4343
// are linked to an ABI version less than this will not be able to load and
@@ -4922,6 +4922,8 @@ extern "C"
49224922
BINARYNINJACOREAPI void BNDeleteUserStackVariable(BNFunction* func, int64_t offset);
49234923
BINARYNINJACOREAPI bool BNGetStackVariableAtFrameOffset(
49244924
BNFunction* func, BNArchitecture* arch, uint64_t addr, int64_t offset, BNVariableNameAndType* var);
4925+
BINARYNINJACOREAPI bool BNGetStackVariableAtFrameOffsetAfterInstruction(
4926+
BNFunction* func, BNArchitecture* arch, uint64_t addr, int64_t offset, BNVariableNameAndType* var);
49254927
BINARYNINJACOREAPI void BNFreeVariableNameAndType(BNVariableNameAndType* var);
49264928

49274929
BINARYNINJACOREAPI BNVariableNameAndType* BNGetFunctionVariables(BNFunction* func, size_t* count);
@@ -5962,14 +5964,24 @@ extern "C"
59625964

59635965
BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAVarVersionAtILInstruction(
59645966
BNMediumLevelILFunction* func, const BNVariable* var, size_t instr);
5967+
BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAVarVersionAfterILInstruction(
5968+
BNMediumLevelILFunction* func, const BNVariable* var, size_t instr);
59655969
BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAMemoryVersionAtILInstruction(
59665970
BNMediumLevelILFunction* func, size_t instr);
5971+
BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAMemoryVersionAfterILInstruction(
5972+
BNMediumLevelILFunction* func, size_t instr);
59675973
BINARYNINJACOREAPI BNVariable BNGetMediumLevelILVariableForRegisterAtInstruction(
59685974
BNMediumLevelILFunction* func, uint32_t reg, size_t instr);
5975+
BINARYNINJACOREAPI BNVariable BNGetMediumLevelILVariableForRegisterAfterInstruction(
5976+
BNMediumLevelILFunction* func, uint32_t reg, size_t instr);
59695977
BINARYNINJACOREAPI BNVariable BNGetMediumLevelILVariableForFlagAtInstruction(
59705978
BNMediumLevelILFunction* func, uint32_t flag, size_t instr);
5979+
BINARYNINJACOREAPI BNVariable BNGetMediumLevelILVariableForFlagAfterInstruction(
5980+
BNMediumLevelILFunction* func, uint32_t flag, size_t instr);
59715981
BINARYNINJACOREAPI BNVariable BNGetMediumLevelILVariableForStackLocationAtInstruction(
59725982
BNMediumLevelILFunction* func, int64_t offset, size_t instr);
5983+
BINARYNINJACOREAPI BNVariable BNGetMediumLevelILVariableForStackLocationAfterInstruction(
5984+
BNMediumLevelILFunction* func, int64_t offset, size_t instr);
59735985

59745986
BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILRegisterValueAtInstruction(
59755987
BNMediumLevelILFunction* func, uint32_t reg, size_t instr);

function.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,6 +1358,23 @@ bool Function::GetStackVariableAtFrameOffset(
13581358
}
13591359

13601360

1361+
bool Function::GetStackVariableAtFrameOffsetAfterInstruction(
1362+
Architecture* arch, uint64_t addr, int64_t offset, VariableNameAndType& result)
1363+
{
1364+
BNVariableNameAndType var;
1365+
if (!BNGetStackVariableAtFrameOffsetAfterInstruction(m_object, arch->GetObject(), addr, offset, &var))
1366+
return false;
1367+
1368+
result.type = Confidence<Ref<Type>>(new Type(BNNewTypeReference(var.type)), var.typeConfidence);
1369+
result.name = var.name;
1370+
result.var = var.var;
1371+
result.autoDefined = var.autoDefined;
1372+
1373+
BNFreeVariableNameAndType(&var);
1374+
return true;
1375+
}
1376+
1377+
13611378
map<Variable, VariableNameAndType> Function::GetVariables()
13621379
{
13631380
size_t count;

mediumlevelil.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,30 +617,60 @@ size_t MediumLevelILFunction::GetSSAVarVersionAtInstruction(const Variable& var,
617617
}
618618

619619

620+
size_t MediumLevelILFunction::GetSSAVarVersionAfterInstruction(const Variable& var, size_t instr) const
621+
{
622+
return BNGetMediumLevelILSSAVarVersionAfterILInstruction(m_object, &var, instr);
623+
}
624+
625+
620626
size_t MediumLevelILFunction::GetSSAMemoryVersionAtInstruction(size_t instr) const
621627
{
622628
return BNGetMediumLevelILSSAMemoryVersionAtILInstruction(m_object, instr);
623629
}
624630

625631

632+
size_t MediumLevelILFunction::GetSSAMemoryVersionAfterInstruction(size_t instr) const
633+
{
634+
return BNGetMediumLevelILSSAMemoryVersionAfterILInstruction(m_object, instr);
635+
}
636+
637+
626638
Variable MediumLevelILFunction::GetVariableForRegisterAtInstruction(uint32_t reg, size_t instr) const
627639
{
628640
return BNGetMediumLevelILVariableForRegisterAtInstruction(m_object, reg, instr);
629641
}
630642

631643

644+
Variable MediumLevelILFunction::GetVariableForRegisterAfterInstruction(uint32_t reg, size_t instr) const
645+
{
646+
return BNGetMediumLevelILVariableForRegisterAfterInstruction(m_object, reg, instr);
647+
}
648+
649+
632650
Variable MediumLevelILFunction::GetVariableForFlagAtInstruction(uint32_t flag, size_t instr) const
633651
{
634652
return BNGetMediumLevelILVariableForFlagAtInstruction(m_object, flag, instr);
635653
}
636654

637655

656+
Variable MediumLevelILFunction::GetVariableForFlagAfterInstruction(uint32_t flag, size_t instr) const
657+
{
658+
return BNGetMediumLevelILVariableForFlagAfterInstruction(m_object, flag, instr);
659+
}
660+
661+
638662
Variable MediumLevelILFunction::GetVariableForStackLocationAtInstruction(int64_t offset, size_t instr) const
639663
{
640664
return BNGetMediumLevelILVariableForStackLocationAtInstruction(m_object, offset, instr);
641665
}
642666

643667

668+
Variable MediumLevelILFunction::GetVariableForStackLocationAfterInstruction(int64_t offset, size_t instr) const
669+
{
670+
return BNGetMediumLevelILVariableForStackLocationAfterInstruction(m_object, offset, instr);
671+
}
672+
673+
644674
RegisterValue MediumLevelILFunction::GetRegisterValueAtInstruction(uint32_t reg, size_t instr)
645675
{
646676
BNRegisterValue value = BNGetMediumLevelILRegisterValueAtInstruction(m_object, reg, instr);

python/function.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2638,6 +2638,18 @@ def get_stack_var_at_frame_offset(
26382638
core.BNFreeVariableNameAndType(found_var)
26392639
return result
26402640

2641+
def get_stack_var_at_frame_offset_after_instruction(
2642+
self, offset: int, addr: int, arch: Optional['architecture.Architecture'] = None
2643+
) -> Optional['variable.Variable']:
2644+
if arch is None:
2645+
arch = self.arch
2646+
found_var = core.BNVariableNameAndType()
2647+
if not core.BNGetStackVariableAtFrameOffsetAfterInstruction(self.handle, arch.handle, addr, offset, found_var):
2648+
return None
2649+
result = variable.Variable.from_BNVariable(self, found_var.var)
2650+
core.BNFreeVariableNameAndType(found_var)
2651+
return result
2652+
26412653
def get_type_tokens(self, settings: Optional['DisassemblySettings'] = None) -> List['DisassemblyTextLine']:
26422654
_settings = None
26432655
if settings is not None:

python/mediumlevelil.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,11 @@ def ssa_memory_version(self) -> int:
698698
"""Version of active memory contents in SSA form for this instruction"""
699699
return core.BNGetMediumLevelILSSAMemoryVersionAtILInstruction(self.function.handle, self.instr_index)
700700

701+
@property
702+
def ssa_memory_version_after(self) -> int:
703+
"""Version of active memory contents in SSA form after this instruction"""
704+
return core.BNGetMediumLevelILSSAMemoryVersionAfterILInstruction(self.function.handle, self.instr_index)
705+
701706
@property
702707
def prefix_operands(self) -> List[MediumLevelILOperandType]:
703708
"""All operands in the expression tree in prefix order"""
@@ -803,22 +808,42 @@ def get_ssa_var_version(self, var: variable.Variable) -> int:
803808
var_data = var.to_BNVariable()
804809
return core.BNGetMediumLevelILSSAVarVersionAtILInstruction(self.function.handle, var_data, self.instr_index)
805810

811+
def get_ssa_var_version_after(self, var: variable.Variable) -> int:
812+
var_data = var.to_BNVariable()
813+
return core.BNGetMediumLevelILSSAVarVersionAfterILInstruction(self.function.handle, var_data, self.instr_index)
814+
806815
def get_var_for_reg(self, reg: 'architecture.RegisterType') -> variable.Variable:
807816
reg = self.function.arch.get_reg_index(reg)
808817
result = core.BNGetMediumLevelILVariableForRegisterAtInstruction(self.function.handle, reg, self.instr_index)
809818
return variable.Variable.from_BNVariable(self.function, result)
810819

820+
def get_var_for_reg_after(self, reg: 'architecture.RegisterType') -> variable.Variable:
821+
reg = self.function.arch.get_reg_index(reg)
822+
result = core.BNGetMediumLevelILVariableForRegisterAfterInstruction(self.function.handle, reg, self.instr_index)
823+
return variable.Variable.from_BNVariable(self.function, result)
824+
811825
def get_var_for_flag(self, flag: 'architecture.FlagType') -> variable.Variable:
812826
flag = self.function.arch.get_flag_index(flag)
813827
result = core.BNGetMediumLevelILVariableForFlagAtInstruction(self.function.handle, flag, self.instr_index)
814828
return variable.Variable.from_BNVariable(self.function, result)
815829

830+
def get_var_for_flag_after(self, flag: 'architecture.FlagType') -> variable.Variable:
831+
flag = self.function.arch.get_flag_index(flag)
832+
result = core.BNGetMediumLevelILVariableForFlagAfterInstruction(self.function.handle, flag, self.instr_index)
833+
return variable.Variable.from_BNVariable(self.function, result)
834+
816835
def get_var_for_stack_location(self, offset: int) -> variable.Variable:
817836
result = core.BNGetMediumLevelILVariableForStackLocationAtInstruction(
818837
self.function.handle, offset, self.instr_index
819838
)
820839
return variable.Variable.from_BNVariable(self.function, result)
821840

841+
def get_var_for_stack_location_after(self, offset: int) -> variable.Variable:
842+
result = core.BNGetMediumLevelILVariableForStackLocationAfterInstruction(
843+
self.function.handle, offset, self.instr_index
844+
)
845+
return variable.Variable.from_BNVariable(self.function, result)
846+
822847
def get_reg_value(self, reg: 'architecture.RegisterType') -> 'variable.RegisterValue':
823848
reg = self.function.arch.get_reg_index(reg)
824849
value = core.BNGetMediumLevelILRegisterValueAtInstruction(self.function.handle, reg, self.instr_index)

rust/src/function.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1944,6 +1944,35 @@ impl Function {
19441944
Some((var, name, var_type))
19451945
}
19461946

1947+
pub fn stack_var_at_frame_offset_after_instruction(
1948+
&self,
1949+
addr: u64,
1950+
offset: i64,
1951+
arch: Option<CoreArchitecture>,
1952+
) -> Option<(Variable, BnString, Conf<Ref<Type>>)> {
1953+
let arch = arch.unwrap_or_else(|| self.arch());
1954+
let mut found_value = BNVariableNameAndType::default();
1955+
let found = unsafe {
1956+
BNGetStackVariableAtFrameOffsetAfterInstruction(
1957+
self.handle,
1958+
arch.handle,
1959+
addr,
1960+
offset,
1961+
&mut found_value,
1962+
)
1963+
};
1964+
if !found {
1965+
return None;
1966+
}
1967+
let var = Variable::from(found_value.var);
1968+
let name = unsafe { BnString::from_raw(found_value.name) };
1969+
let var_type = Conf::new(
1970+
unsafe { Type::ref_from_raw(found_value.type_) },
1971+
found_value.typeConfidence,
1972+
);
1973+
Some((var, name, var_type))
1974+
}
1975+
19471976
pub fn stack_variables_referenced_by(
19481977
&self,
19491978
addr: u64,

rust/src/medium_level_il/instruction.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,19 @@ impl MediumLevelILInstruction {
10291029
SSAVariable::new(var, version)
10301030
}
10311031

1032+
/// Return the ssa version of a [`Variable`] after the given instruction.
1033+
pub fn ssa_variable_version_after(&self, var: Variable) -> SSAVariable {
1034+
let raw_var = BNVariable::from(var);
1035+
let version = unsafe {
1036+
BNGetMediumLevelILSSAVarVersionAfterILInstruction(
1037+
self.function.handle,
1038+
&raw_var,
1039+
self.expr_index.0,
1040+
)
1041+
};
1042+
SSAVariable::new(var, version)
1043+
}
1044+
10321045
/// Set of branching instructions that must take the true or false path to reach this instruction
10331046
pub fn branch_dependencies(&self) -> Array<BranchDependence> {
10341047
let mut count = 0;
@@ -1067,6 +1080,16 @@ impl MediumLevelILInstruction {
10671080
}
10681081
}
10691082

1083+
/// Version of active memory contents in SSA form for this instruction
1084+
pub fn ssa_memory_version_after(&self) -> usize {
1085+
unsafe {
1086+
BNGetMediumLevelILSSAMemoryVersionAfterILInstruction(
1087+
self.function.handle,
1088+
self.expr_index.0,
1089+
)
1090+
}
1091+
}
1092+
10701093
/// Type of expression
10711094
pub fn expr_type(&self) -> Option<Conf<Ref<Type>>> {
10721095
let result = unsafe { BNGetMediumLevelILExprType(self.function.handle, self.expr_index.0) };
@@ -1095,6 +1118,17 @@ impl MediumLevelILInstruction {
10951118
Variable::from(result)
10961119
}
10971120

1121+
pub fn variable_for_register_after(&self, reg_id: RegisterId) -> Variable {
1122+
let result = unsafe {
1123+
BNGetMediumLevelILVariableForRegisterAfterInstruction(
1124+
self.function.handle,
1125+
reg_id.0,
1126+
self.expr_index.0,
1127+
)
1128+
};
1129+
Variable::from(result)
1130+
}
1131+
10981132
pub fn variable_for_flag(&self, flag_id: FlagId) -> Variable {
10991133
let result = unsafe {
11001134
BNGetMediumLevelILVariableForFlagAtInstruction(
@@ -1106,6 +1140,17 @@ impl MediumLevelILInstruction {
11061140
Variable::from(result)
11071141
}
11081142

1143+
pub fn variable_for_flag_after(&self, flag_id: FlagId) -> Variable {
1144+
let result = unsafe {
1145+
BNGetMediumLevelILVariableForFlagAfterInstruction(
1146+
self.function.handle,
1147+
flag_id.0,
1148+
self.expr_index.0,
1149+
)
1150+
};
1151+
Variable::from(result)
1152+
}
1153+
11091154
pub fn variable_for_stack_location(&self, offset: i64) -> Variable {
11101155
let result = unsafe {
11111156
BNGetMediumLevelILVariableForStackLocationAtInstruction(
@@ -1117,6 +1162,17 @@ impl MediumLevelILInstruction {
11171162
Variable::from(result)
11181163
}
11191164

1165+
pub fn variable_for_stack_location_after(&self, offset: i64) -> Variable {
1166+
let result = unsafe {
1167+
BNGetMediumLevelILVariableForStackLocationAfterInstruction(
1168+
self.function.handle,
1169+
offset,
1170+
self.expr_index.0,
1171+
)
1172+
};
1173+
Variable::from(result)
1174+
}
1175+
11201176
pub fn register_value(&self, reg_id: RegisterId) -> RegisterValue {
11211177
unsafe {
11221178
BNGetMediumLevelILRegisterValueAtInstruction(

0 commit comments

Comments
 (0)