summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/callingconvention.py54
-rw-r--r--python/function.py102
-rw-r--r--python/highlevelil.py30
-rw-r--r--python/mediumlevelil.py51
-rw-r--r--python/types.py6
-rw-r--r--python/variable.py178
6 files changed, 187 insertions, 234 deletions
diff --git a/python/callingconvention.py b/python/callingconvention.py
index 096a6b73..44573503 100644
--- a/python/callingconvention.py
+++ b/python/callingconvention.py
@@ -372,7 +372,7 @@ class CallingConvention(object):
func_obj = None
else:
func_obj = function.Function(handle = core.BNNewFunctionReference(func))
- in_var_obj = variable.Variable(func_obj, in_var[0].type, in_var[0].index, in_var[0].storage)
+ in_var_obj = variable.CoreVariable.from_BNVariable(in_var[0])
out_var = self.perform_get_incoming_var_for_parameter_var(in_var_obj, func_obj)
result[0].type = out_var.source_type
result[0].index = out_var.index
@@ -389,7 +389,7 @@ class CallingConvention(object):
func_obj = None
else:
func_obj = function.Function(handle = core.BNNewFunctionReference(func))
- in_var_obj = variable.Variable(func_obj, in_var[0].type, in_var[0].index, in_var[0].storage)
+ in_var_obj = variable.CoreVariable.from_BNVariable(in_var[0])
out_var = self.perform_get_parameter_var_for_incoming_var(in_var_obj, func_obj)
result[0].type = out_var.source_type
result[0].index = out_var.index
@@ -408,28 +408,19 @@ class CallingConvention(object):
return variable.RegisterValue()
def perform_get_incoming_flag_value(self, reg, func):
- return variable.RegisterValue()
+ return variable.Undetermined()
- def perform_get_incoming_var_for_parameter_var(self, in_var, func):
- in_buf = core.BNVariable()
- in_buf.type = in_var.source_type
- in_buf.index = in_var.index
- in_buf.storage = in_var.storage
- out_var = core.BNGetDefaultIncomingVariableForParameterVariable(self.handle, in_buf)
- name = None
- if (func is not None) and (out_var.type == VariableSourceType.RegisterVariableSourceType):
- name = func.arch.get_reg_name(out_var.storage)
- return variable.Variable(func, out_var.type, out_var.index, out_var.storage, name)
+ def perform_get_incoming_var_for_parameter_var(self, in_var:'variable.CoreVariable',
+ func:Optional['function.Function']=None):
+ out_var = core.BNGetDefaultIncomingVariableForParameterVariable(self.handle, in_var.to_BNVariable())
+ return variable.CoreVariable.from_BNVariable(out_var)
- def perform_get_parameter_var_for_incoming_var(self, in_var, func):
- in_buf = core.BNVariable()
- in_buf.type = in_var.source_type
- in_buf.index = in_var.index
- in_buf.storage = in_var.storage
- out_var = core.BNGetDefaultParameterVariableForIncomingVariable(self.handle, in_buf)
- return variable.Variable(func, out_var.type, out_var.index, out_var.storage)
+ def perform_get_parameter_var_for_incoming_var(self, in_var:'variable.CoreVariable',
+ func:Optional['function.Function']=None):
+ out_var = core.BNGetDefaultParameterVariableForIncomingVariable(self.handle, in_var.to_BNVariable())
+ return variable.CoreVariable.from_BNVariable(out_var)
- def with_confidence(self, confidence):
+ def with_confidence(self, confidence:int):
return CallingConvention(self.arch, handle = core.BNNewCallingConventionReference(self.handle),
confidence = confidence)
@@ -447,32 +438,23 @@ class CallingConvention(object):
func_handle = func.handle
return variable.RegisterValue(self.arch, core.BNGetIncomingFlagValue(self.handle, reg_num, func_handle))
- def get_incoming_var_for_parameter_var(self, in_var, func):
- in_buf = core.BNVariable()
- in_buf.type = in_var.source_type
- in_buf.index = in_var.index
- in_buf.storage = in_var.storage
+ def get_incoming_var_for_parameter_var(self, in_var:'variable.CoreVariable', func:'function.Function'):
+ in_buf = in_var.to_BNVariable()
if func is None:
func_obj = None
else:
func_obj = func.handle
out_var = core.BNGetIncomingVariableForParameterVariable(self.handle, in_buf, func_obj)
- name = None
- if (func is not None) and (out_var.type == VariableSourceType.RegisterVariableSourceType):
- name = func.arch.get_reg_name(out_var.storage)
- return variable.Variable(func, out_var.type, out_var.index, out_var.storage, name)
+ return variable.Variable.from_BNVariable(func, out_var)
- def get_parameter_var_for_incoming_var(self, in_var, func):
- in_buf = core.BNVariable()
- in_buf.type = in_var.source_type
- in_buf.index = in_var.index
- in_buf.storage = in_var.storage
+ def get_parameter_var_for_incoming_var(self, in_var:'variable.CoreVariable', func:'function.Function'):
+ in_buf = in_var.to_BNVariable()
if func is None:
func_obj = None
else:
func_obj = func.handle
out_var = core.BNGetParameterVariableForIncomingVariable(self.handle, in_buf, func_obj)
- return variable.Variable(func, out_var.type, out_var.index, out_var.storage)
+ return variable.Variable.from_BNVariable(func, out_var)
@property
def arch(self):
diff --git a/python/function.py b/python/function.py
index 64aabdbb..64d54327 100644
--- a/python/function.py
+++ b/python/function.py
@@ -858,8 +858,19 @@ class Function(object):
assert v is not None, "core.BNGetStackLayout returned None"
try:
for i in range(0, count.value):
- yield variable.Variable(self, v[i].var.type, v[i].var.index, v[i].var.storage, v[i].name,
- types.Type(handle = core.BNNewTypeReference(v[i].type), platform = self.platform, confidence = v[i].typeConfidence))
+ yield variable.Variable.from_BNVariable(self, v[i].var)
+ finally:
+ core.BNFreeVariableNameAndTypeList(v, count.value)
+
+ @property
+ def core_var_stack_layout(self) -> Generator['variable.CoreVariable', None, None]:
+ """List of function stack variables (read-only)"""
+ count = ctypes.c_ulonglong()
+ v = core.BNGetStackLayout(self.handle, count)
+ assert v is not None, "core.BNGetStackLayout returned None"
+ try:
+ for i in range(0, count.value):
+ yield variable.CoreVariable.from_BNVariable(v[i].var)
finally:
core.BNFreeVariableNameAndTypeList(v, count.value)
@@ -871,8 +882,19 @@ class Function(object):
assert v is not None, "core.BNGetFunctionVariables returned None"
try:
for i in range(0, count.value):
- yield variable.Variable(self, v[i].var.type, v[i].var.index, v[i].var.storage, v[i].name,
- types.Type(handle = core.BNNewTypeReference(v[i].type), platform = self.platform, confidence = v[i].typeConfidence))
+ yield variable.Variable.from_BNVariable(self, v[i].var)
+ finally:
+ core.BNFreeVariableNameAndTypeList(v, count.value)
+
+ @property
+ def core_vars(self) -> Generator['variable.CoreVariable', None, None]:
+ """Generator of CoreVariable objects"""
+ count = ctypes.c_ulonglong()
+ v = core.BNGetFunctionVariables(self.handle, count)
+ assert v is not None, "core.BNGetFunctionVariables returned None"
+ try:
+ for i in range(0, count.value):
+ yield variable.CoreVariable.from_BNVariable(v[i].var)
finally:
core.BNFreeVariableNameAndTypeList(v, count.value)
@@ -1005,7 +1027,7 @@ class Function(object):
result = core.BNGetFunctionParameterVariables(self.handle)
var_list = []
for i in range(0, result.count):
- var_list.append(variable.Variable(self, result.vars[i].type, result.vars[i].index, result.vars[i].storage))
+ var_list.append(variable.Variable.from_BNVariable(self, result.vars[i]))
confidence = result.confidence
core.BNFreeParameterVariables(result)
return variable.ParameterVariables(var_list, confidence, self)
@@ -1919,8 +1941,8 @@ class Function(object):
result = []
for i in range(0, count.value):
var_type = types.Type(core.BNNewTypeReference(refs[i].type), platform = self.platform, confidence = refs[i].typeConfidence)
- result.append(variable.StackVariableReference(refs[i].sourceOperand, var_type,
- refs[i].name, variable.Variable.from_identifier(self, refs[i].varIdentifier, refs[i].name, var_type),
+ var = variable.Variable.from_identifier(self, refs[i].varIdentifier)
+ result.append(variable.StackVariableReference(refs[i].sourceOperand, var_type, refs[i].name, var,
refs[i].referencedOffset, refs[i].size))
core.BNFreeStackVariableReferenceList(refs, count.value)
return result
@@ -2499,46 +2521,26 @@ class Function(object):
def create_auto_var(self, var:'variable.Variable', var_type:'types.Type', name:str,
ignore_disjoint_uses:bool=False) -> None:
- var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
tc = core.BNTypeWithConfidence()
tc.type = var_type.handle
tc.confidence = var_type.confidence
- core.BNCreateAutoVariable(self.handle, var_data, tc, name, ignore_disjoint_uses)
+ core.BNCreateAutoVariable(self.handle, var.to_BNVariable(), tc, name, ignore_disjoint_uses)
def create_user_var(self, var:'variable.Variable', var_type:'types.Type', name:str,
ignore_disjoint_uses:bool=False) -> None:
- var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
tc = core.BNTypeWithConfidence()
tc.type = var_type.handle
tc.confidence = var_type.confidence
- core.BNCreateUserVariable(self.handle, var_data, tc, name, ignore_disjoint_uses)
+ core.BNCreateUserVariable(self.handle, var.to_BNVariable(), tc, name, ignore_disjoint_uses)
def delete_auto_var(self, var:'variable.Variable') -> None:
- var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
- core.BNDeleteAutoVariable(self.handle, var_data)
+ core.BNDeleteAutoVariable(self.handle, var.to_BNVariable())
def delete_user_var(self, var:'variable.Variable') -> None:
- var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
- core.BNDeleteUserVariable(self.handle, var_data)
+ core.BNDeleteUserVariable(self.handle, var.to_BNVariable())
def is_var_user_defined(self, var:'variable.Variable') -> bool:
- var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
- return core.BNIsVariableUserDefined(self.handle, var_data)
+ return core.BNIsVariableUserDefined(self.handle, var.to_BNVariable())
def get_stack_var_at_frame_offset(self, offset:int, addr:int, arch:Optional['architecture.Architecture']=None) -> \
Optional['variable.Variable']:
@@ -2549,9 +2551,7 @@ class Function(object):
found_var = core.BNVariableNameAndType()
if not core.BNGetStackVariableAtFrameOffset(self.handle, arch.handle, addr, offset, found_var):
return None
- result = variable.Variable(self, found_var.var.type, found_var.var.index, found_var.var.storage,
- found_var.name, types.Type(handle = core.BNNewTypeReference(found_var.type), platform = self.platform,
- confidence = found_var.typeConfidence))
+ result = variable.Variable.from_BNVariable(self, found_var.var)
core.BNFreeVariableNameAndType(found_var)
return result
@@ -2576,7 +2576,7 @@ class Function(object):
raise Exception("can not get_reg_value_at_exit if Function.arch is")
result = core.BNGetFunctionRegisterValueAtExit(self.handle, self.arch.get_reg_index(reg))
- return variable.RegisterValue(self.arch, result.value, confidence = result.confidence)
+ return variable.RegisterValue.from_BNRegisterValue(result, self.arch)
def set_auto_call_stack_adjustment(self, addr:int, adjust:Union[int, 'types.SizeWithConfidence'],\
arch:Optional['architecture.Architecture']=None) -> None:
@@ -2764,11 +2764,7 @@ class Function(object):
def_site.arch = self.arch.handle
def_site.address = def_addr
- var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
- core.BNSetUserVariableValue(self.handle, var_data, def_site, value._to_api_object())
+ core.BNSetUserVariableValue(self.handle, var.to_BNVariable(), def_site, value._to_api_object())
def clear_user_var_value(self, var:'variable.Variable', def_addr:int) -> None:
"""
@@ -2795,11 +2791,7 @@ class Function(object):
def_site.arch = self.arch.handle
def_site.address = def_addr
- var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
- core.BNClearUserVariableValue(self.handle, var_data, def_site)
+ core.BNClearUserVariableValue(self.handle, var.to_BNVariable(), def_site)
def get_all_user_var_values(self) -> \
Mapping['variable.Variable', Mapping['ArchAndAddr', 'variable.PossibleValueSet']]:
@@ -2816,7 +2808,7 @@ class Function(object):
i = 0
for i in range(count.value):
var_val = var_values[i]
- var = variable.Variable(self, var_val.var.type, var_val.var.index, var_val.var.storage)
+ var = variable.Variable.from_BNVariable(self, var_val.var)
if var not in result:
result[var] = {}
def_site = ArchAndAddr(var_val.defSite.arch, var_val.defSite.address)
@@ -2948,11 +2940,7 @@ class Function(object):
>>> current_function.get_mlil_var_refs(var)
"""
count = ctypes.c_ulonglong(0)
- var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
- refs = core.BNGetMediumLevelILVariableReferences(self.handle, var_data, count)
+ refs = core.BNGetMediumLevelILVariableReferences(self.handle, var.to_BNVariable(), count)
assert refs is not None, "core.BNGetMediumLevelILVariableReferences returned None"
result = []
for i in range(0, count.value):
@@ -3002,7 +2990,7 @@ class Function(object):
refs = core.BNGetMediumLevelILVariableReferencesInRange(self.handle, arch.handle, addr, length, count)
assert refs is not None, "core.BNGetMediumLevelILVariableReferencesInRange returned None"
for i in range(0, count.value):
- var = variable.Variable(self, refs[i].var.type, refs[i].var.index, refs[i].var.storage)
+ var = variable.Variable.from_BNVariable(self, refs[i].var)
if refs[i].source.func:
func = Function(self.view, core.BNNewFunctionReference(refs[i].source.func))
else:
@@ -3032,11 +3020,7 @@ class Function(object):
>>> current_function.get_hlil_var_refs(var)
"""
count = ctypes.c_ulonglong(0)
- var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
- refs = core.BNGetHighLevelILVariableReferences(self.handle, var_data, count)
+ refs = core.BNGetHighLevelILVariableReferences(self.handle, var.to_BNVariable(), count)
assert refs is not None, "core.BNGetHighLevelILVariableReferences returned None"
result = []
for i in range(0, count.value):
@@ -3080,7 +3064,7 @@ class Function(object):
refs = core.BNGetHighLevelILVariableReferencesInRange(self.handle, arch.handle, addr, length, count)
assert refs is not None, "core.BNGetHighLevelILVariableReferencesInRange returned None"
for i in range(0, count.value):
- var = variable.Variable(self, refs[i].var.type, refs[i].var.index, refs[i].var.storage)
+ var = variable.Variable.from_BNVariable(self, refs[i].var)
if refs[i].source.func:
func = Function(self.view, core.BNNewFunctionReference(refs[i].source.func))
else:
diff --git a/python/highlevelil.py b/python/highlevelil.py
index 71c58920..831d232d 100644
--- a/python/highlevelil.py
+++ b/python/highlevelil.py
@@ -624,10 +624,7 @@ class HighLevelILInstruction(object):
return core.BNGetHighLevelILSSAMemoryVersionAtILInstruction(self._function.handle, self._instr_index)
def get_ssa_var_version(self, var:'variable.Variable') -> int:
- var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
+ var_data = var.to_BNVariable()
return core.BNGetHighLevelILSSAVarVersionAtILInstruction(self._function.handle, var_data, self._instr_index)
@@ -837,10 +834,7 @@ class HighLevelILFunction(object):
return core.BNGetHighLevelILNonSSAInstructionIndex(self.handle, instr)
def get_ssa_var_definition(self, ssa_var:'mediumlevelil.SSAVariable') -> Optional[HighLevelILInstruction]:
- var_data = core.BNVariable()
- var_data.type = ssa_var.var.source_type
- var_data.index = ssa_var.var.index
- var_data.storage = ssa_var.var.storage
+ var_data = ssa_var.var.to_BNVariable()
result = core.BNGetHighLevelILSSAVarDefinition(self.handle, var_data, ssa_var.version)
if result >= core.BNGetHighLevelILExprCount(self.handle):
return None
@@ -854,10 +848,7 @@ class HighLevelILFunction(object):
def get_ssa_var_uses(self, ssa_var:'mediumlevelil.SSAVariable') -> List[HighLevelILInstruction]:
count = ctypes.c_ulonglong()
- var_data = core.BNVariable()
- var_data.type = ssa_var.var.source_type
- var_data.index = ssa_var.var.index
- var_data.storage = ssa_var.var.storage
+ var_data = ssa_var.var.to_BNVariable()
instrs = core.BNGetHighLevelILSSAVarUses(self.handle, var_data, ssa_var.version, count)
assert instrs is not None, "core.BNGetHighLevelILSSAVarUses returned None"
result = []
@@ -884,18 +875,12 @@ class HighLevelILFunction(object):
:return: whether the variable is live at any point in the function
:rtype: bool
"""
- var_data = core.BNVariable()
- var_data.type = ssa_var.var.source_type
- var_data.index = ssa_var.var.index
- var_data.storage = ssa_var.var.storage
+ var_data = ssa_var.var.to_BNVariable()
return core.BNIsHighLevelILSSAVarLive(self.handle, var_data, ssa_var.version)
def get_var_definitions(self, var:'variable.Variable') -> List[HighLevelILInstruction]:
count = ctypes.c_ulonglong()
- var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
+ var_data = var.to_BNVariable()
instrs = core.BNGetHighLevelILVariableDefinitions(self.handle, var_data, count)
assert instrs is not None, "core.BNGetHighLevelILVariableDefinitions returned None"
result = []
@@ -906,10 +891,7 @@ class HighLevelILFunction(object):
def get_var_uses(self, var:'variable.Variable') -> List[HighLevelILInstruction]:
count = ctypes.c_ulonglong()
- var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
+ var_data = var.to_BNVariable()
instrs = core.BNGetHighLevelILVariableUses(self.handle, var_data, count)
assert instrs is not None, "core.BNGetHighLevelILVariableUses returned None"
result = []
diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py
index 167930b6..53b5619e 100644
--- a/python/mediumlevelil.py
+++ b/python/mediumlevelil.py
@@ -629,10 +629,7 @@ class MediumLevelILInstruction(object):
return result
def get_ssa_var_possible_values(self, ssa_var:SSAVariable, options:List[DataFlowQueryOption]=[]):
- var_data = core.BNVariable()
- var_data.type = ssa_var.var.source_type
- var_data.index = ssa_var.var.index
- var_data.storage = ssa_var.var.storage
+ var_data = ssa_var.var.to_BNVariable()
option_array = (ctypes.c_int * len(options))()
idx = 0
for option in options:
@@ -645,25 +642,22 @@ class MediumLevelILInstruction(object):
return result
def get_ssa_var_version(self, var:variable.Variable) -> int:
- var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
+ var_data = var.to_BNVariable()
return core.BNGetMediumLevelILSSAVarVersionAtILInstruction(self._function.handle, var_data, self._instr_index)
def get_var_for_reg(self, reg:'architecture.RegisterType') -> variable.Variable:
reg = self._function.arch.get_reg_index(reg)
result = core.BNGetMediumLevelILVariableForRegisterAtInstruction(self._function.handle, reg, self._instr_index)
- return variable.Variable(self._function.source_function, result.type, result.index, result.storage)
+ return variable.Variable.from_BNVariable(self._function.source_function, result)
def get_var_for_flag(self, flag:'architecture.FlagType') -> variable.Variable:
flag = self._function.arch.get_flag_index(flag)
result = core.BNGetMediumLevelILVariableForFlagAtInstruction(self._function.handle, flag, self._instr_index)
- return variable.Variable(self._function.source_function, result.type, result.index, result.storage)
+ return variable.Variable.from_BNVariable(self._function.source_function, result)
def get_var_for_stack_location(self, offset:int) -> variable.Variable:
result = core.BNGetMediumLevelILVariableForStackLocationAtInstruction(self._function.handle, offset, self._instr_index)
- return variable.Variable(self._function.source_function, result.type, result.index, result.storage)
+ return variable.Variable.from_BNVariable(self._function.source_function, result)
def get_reg_value(self, reg:'architecture.RegisterType') -> 'variable.RegisterValue':
reg = self._function.arch.get_reg_index(reg)
@@ -1113,10 +1107,7 @@ class MediumLevelILFunction(object):
return core.BNGetMediumLevelILNonSSAInstructionIndex(self.handle, instr)
def get_ssa_var_definition(self, ssa_var:SSAVariable) -> Optional[MediumLevelILInstruction]:
- var_data = core.BNVariable()
- var_data.type = ssa_var.var.source_type
- var_data.index = ssa_var.var.index
- var_data.storage = ssa_var.var.storage
+ var_data = ssa_var.var.to_BNVariable()
result = core.BNGetMediumLevelILSSAVarDefinition(self.handle, var_data, ssa_var.version)
if result >= core.BNGetMediumLevelILInstructionCount(self.handle):
return None
@@ -1130,10 +1121,7 @@ class MediumLevelILFunction(object):
def get_ssa_var_uses(self, ssa_var:SSAVariable) -> List[MediumLevelILInstruction]:
count = ctypes.c_ulonglong()
- var_data = core.BNVariable()
- var_data.type = ssa_var.var.source_type
- var_data.index = ssa_var.var.index
- var_data.storage = ssa_var.var.storage
+ var_data = ssa_var.var.to_BNVariable()
instrs = core.BNGetMediumLevelILSSAVarUses(self.handle, var_data, ssa_var.version, count)
assert instrs is not None, "core.BNGetMediumLevelILSSAVarUses returned None"
result = []
@@ -1160,18 +1148,12 @@ class MediumLevelILFunction(object):
:return: whether the variable is live at any point in the function
:rtype: bool
"""
- var_data = core.BNVariable()
- var_data.type = ssa_var.var.source_type
- var_data.index = ssa_var.var.index
- var_data.storage = ssa_var.var.storage
+ var_data = ssa_var.var.to_BNVariable()
return core.BNIsMediumLevelILSSAVarLive(self.handle, var_data, ssa_var.version)
def get_var_definitions(self, var:'variable.Variable') -> List[MediumLevelILInstruction]:
count = ctypes.c_ulonglong()
- var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
+ var_data = var.to_BNVariable()
instrs = core.BNGetMediumLevelILVariableDefinitions(self.handle, var_data, count)
assert instrs is not None, "core.BNGetMediumLevelILVariableDefinitions returned None"
result = []
@@ -1182,10 +1164,7 @@ class MediumLevelILFunction(object):
def get_var_uses(self, var:'variable.Variable') -> List[MediumLevelILInstruction]:
count = ctypes.c_ulonglong()
- var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
+ var_data = var.to_BNVariable()
instrs = core.BNGetMediumLevelILVariableDefinitions(self.handle, var_data, count)
assert instrs is not None, "core.BNGetMediumLevelILVariableDefinitions returned None"
result = []
@@ -1195,10 +1174,7 @@ class MediumLevelILFunction(object):
return result
count = ctypes.c_ulonglong()
- var_data = core.BNVariable()
- var_data.type = var.source_type
- var_data.index = var.index
- var_data.storage = var.storage
+ var_data = var.to_BNVariable()
instrs = core.BNGetMediumLevelILVariableUses(self.handle, var_data, count)
result = []
for i in range(0, count.value):
@@ -1207,10 +1183,7 @@ class MediumLevelILFunction(object):
return result
def get_ssa_var_value(self, ssa_var:SSAVariable) -> 'variable.RegisterValue':
- var_data = core.BNVariable()
- var_data.type = ssa_var.var.source_type
- var_data.index = ssa_var.var.index
- var_data.storage = ssa_var.var.storage
+ var_data = ssa_var.var.to_BNVariable()
value = core.BNGetMediumLevelILSSAVarValue(self.handle, var_data, ssa_var.version)
result = variable.RegisterValue(self._arch, value)
return result
diff --git a/python/types.py b/python/types.py
index bead9a64..3cd44bd8 100644
--- a/python/types.py
+++ b/python/types.py
@@ -19,7 +19,8 @@
# IN THE SOFTWARE.
import ctypes
-from typing import Generator, List, Union
+from typing import Generator, List, Union, Mapping, Tuple, Optional
+from dataclasses import dataclass
# Binary Ninja components
from . import _binaryninjacore as core
@@ -28,6 +29,7 @@ from . import callingconvention
from . import function
from . import variable
from . import architecture
+from . import types
from . import log
QualifiedNameType = Union[List[str], str, 'QualifiedName', List[bytes]]
@@ -588,7 +590,7 @@ class Type(object):
name = self._platform.arch.get_reg_name(params[i].location.storage)
elif params[i].location.type == VariableSourceType.StackVariableSourceType:
name = "arg_%x" % params[i].location.storage
- param_location = variable.Variable(None, params[i].location.type, params[i].location.index,
+ param_location = variable.VariableNameAndType(params[i].location.type, params[i].location.index,
params[i].location.storage, name, param_type)
result.append(FunctionParameter(param_type, params[i].name, param_location))
core.BNFreeTypeParameterList(params, count.value)
diff --git a/python/variable.py b/python/variable.py
index 187d5e3d..011402d8 100644
--- a/python/variable.py
+++ b/python/variable.py
@@ -683,21 +683,76 @@ class StackVariableReference(object):
@decorators.passive
-class Variable(object):
- def __init__(self, func, source_type, index, storage, name = None, var_type = None, identifier = None):
+@dataclass(frozen=True, order=True)
+class CoreVariable:
+ _source_type:int
+ index:int
+ storage:int
+
+ @property
+ def identifier(self) -> int:
+ return core.BNToVariableIdentifier(self.to_BNVariable())
+
+ @property
+ def source_type(self) -> VariableSourceType:
+ return VariableSourceType(self._source_type)
+
+ def to_BNVariable(self):
+ v = core.BNVariable()
+ v.type = self._source_type
+ v.index = self.index
+ v.storage = self.storage
+ return v
+
+ @classmethod
+ def from_BNVariable(cls, var:core.BNVariable):
+ return cls(var.type, var.index, var.storage)
+
+ @classmethod
+ def from_identifier(cls, identifier):
+ var = core.BNFromVariableIdentifier(identifier)
+ return cls(var.type, var.index, var.storage)
+
+@decorators.passive
+@dataclass(frozen=True, order=True)
+class VariableNameAndType(CoreVariable):
+ name:str
+ type:'binaryninja.types.Type'
+
+ @classmethod
+ def from_identifier(cls, identifier, name, type):
+ var = core.BNFromVariableIdentifier(identifier)
+ return cls(name, type, var.type, var.index, var.storage)
+
+ @classmethod
+ def from_core_variable(cls, var, name, type):
+ return cls(name, type, var.type, var.index, var.storage)
+
+
+class Variable:
+ def __init__(self, func:'binaryninja.function.Function', source_type:VariableSourceType, index:int, storage:int):
self._function = func
- self._source_type = source_type
- self._index = index
- self._storage = storage
- self._identifier = identifier
- self._name = name
- self._type = var_type
+ self._var = CoreVariable(source_type, index, storage)
+
+ @classmethod
+ def from_variable_name_and_type(cls, func:'binaryninja.function.Function', var:VariableNameAndType):
+ return cls(func, VariableSourceType(var.type), var.index, var.storage)
+
+ @classmethod
+ def from_core_variable(cls, func:'binaryninja.function.Function', var:CoreVariable):
+ return cls(func, var.source_type, var.index, var.storage)
+
+ @classmethod
+ def from_BNVariable(cls, func:'binaryninja.function.Function', var:core.BNVariable):
+ return cls(func, var.type, var.index, var.storage)
+
+ @classmethod
+ def from_identifier(cls, func:'binaryninja.function.Function', identifier:int):
+ var = core.BNFromVariableIdentifier(identifier)
+ return cls(func, VariableSourceType(var.type), var.index, var.storage)
def __repr__(self):
- if self.type is not None:
- return f"<var {self.type.get_string_before_name()} {self.name}{self.type.get_string_after_name()}>"
- else:
- return f"<var {self.name}>"
+ return f"<var {self.type.get_string_before_name()} {self.name}{self.type.get_string_after_name()}>"
def __str__(self):
return self.name
@@ -705,7 +760,7 @@ class Variable(object):
def __eq__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
- return (self.identifier, self.function) == (other.identifier, other.function)
+ return (self.identifier, self._function) == (other.identifier, other._function)
def __ne__(self, other):
if not isinstance(other, self.__class__):
@@ -715,108 +770,83 @@ class Variable(object):
def __lt__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
- return (self.identifier, self.function) < (other.identifier, other.function)
+ return (self.identifier, self._function) < (other.identifier, other._function)
def __gt__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
- return (self.identifier, self.function) > (other.identifier, other.function)
+ return (self.identifier, self._function) > (other.identifier, other._function)
def __le__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
- return (self.identifier, self.function) <= (other.identifier, other.function)
+ return (self.identifier, self._function) <= (other.identifier, other._function)
def __ge__(self, other):
if not isinstance(other, self.__class__):
return NotImplemented
- return (self.identifier, self.function) >= (other.identifier, other.function)
+ return (self.identifier, self._function) >= (other.identifier, other._function)
def __hash__(self):
- return hash((self.identifier, self.function))
-
- @property
- def function(self) -> 'binaryninja.function.Function':
- """Function where the variable is defined"""
- return self._function
-
- @function.setter
- def function(self, value:'binaryninja.function.Function'):
- self._function = value
+ return hash((self.identifier))
@property
def source_type(self) -> VariableSourceType:
- """:class:`~enums.VariableSourceType`"""
- if not isinstance(self._source_type, VariableSourceType):
- self._source_type = VariableSourceType(self._source_type)
-
- return self._source_type
-
- @source_type.setter
- def source_type(self, value:VariableSourceType) -> None:
- self._source_type = value
+ return self._var.source_type
@property
def index(self) -> int:
- return self._index
-
- @index.setter
- def index(self, value:int) -> None:
- self._index = value
+ return self._var.index
@property
def storage(self) -> int:
"""Stack offset for StackVariableSourceType, register index for RegisterVariableSourceType"""
- return self._storage
-
- @storage.setter
- def storage(self, value:int) -> None:
- self._storage = value
+ return self._var.storage
@property
def identifier(self) -> int:
- if self._identifier is None:
- self._identifier = core.BNToVariableIdentifier(self.to_BNVariable())
- return self._identifier
+ return self._var.identifier
+
+ @property
+ def core_var(self) -> CoreVariable:
+ return self._var
+
+ @property
+ def var_name_and_type(self) -> VariableNameAndType:
+ return VariableNameAndType.from_core_variable(self._var, self.name, self.type)
@property
def name(self):
"""Name of the variable"""
- if self._name is None:
- if self._function is not None:
- self._name = core.BNGetVariableName(self._function.handle, self.to_BNVariable())
- return self._name
+ return core.BNGetVariableName(self._function.handle, self._var.to_BNVariable())
+
+ @name.setter
+ def name(self, name:Optional[str]) -> None:
+ if name is None:
+ name = ""
+ self._function.create_user_var(self, self.type, name)
@property
- def type(self) -> Optional['binaryninja.types.Type']:
- if self._type is None:
- if self._function is not None:
- var_type_conf = core.BNGetVariableType(self._function.handle, self.to_BNVariable())
- if var_type_conf.type:
- self._type = binaryninja.types.Type(var_type_conf.type, platform = self._function.platform, confidence = var_type_conf.confidence)
- return self._type
+ def type(self) -> 'binaryninja.types.Type':
+ var_type_conf = core.BNGetVariableType(self._function.handle, self._var.to_BNVariable())
+ assert var_type_conf.type
+ _type = binaryninja.types.Type(var_type_conf.type, self._function.platform, var_type_conf.confidence)
+ return _type
- def to_BNVariable(self):
- v = core.BNVariable()
- v.type = self.source_type
- v.index = self._index
- v.storage = self._storage
- return v
+ @type.setter
+ def type(self, new_type:'binaryninja.types.Type') -> None:
+ self._function.create_user_var(self, new_type, self.name)
@property
def dead_store_elimination(self):
- if self._function is not None and self._identifier is not None:
- return DeadStoreElimination(core.BNGetFunctionVariableDeadStoreElimination(self._function.handle, self.to_BNVariable()))
- return None
+ return DeadStoreElimination(core.BNGetFunctionVariableDeadStoreElimination(self._function.handle, self._var.to_BNVariable()))
@dead_store_elimination.setter
def dead_store_elimination(self, value):
- core.BNSetFunctionVariableDeadStoreElimination(self._function.handle, self.to_BNVariable(), value)
+ core.BNSetFunctionVariableDeadStoreElimination(self._function.handle, self._var.to_BNVariable(), value)
- @staticmethod
- def from_identifier(func, identifier, name=None, var_type=None):
- var = core.BNFromVariableIdentifier(identifier)
- return Variable(func, VariableSourceType(var.type), var.index, var.storage, name, var_type, identifier)
+ def to_BNVariable(self):
+ return self._var.to_BNVariable()
@decorators.passive
class ConstantReference(object):