Source code for binaryninja.variable

# coding=utf-8# Copyright (c) 2015-2025 Vector 35 Inc## Permission is hereby granted, free of charge, to any person obtaining a copy# of this software and associated documentation files (the "Software"), to# deal in the Software without restriction, including without limitation the# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or# sell copies of the Software, and to permit persons to whom the Software is# furnished to do so, subject to the following conditions:## The above copyright notice and this permission notice shall be included in# all copies or substantial portions of the Software.## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS# IN THE SOFTWARE.importctypesfromtypingimportList,Generator,Optional,Union,Set,Dict,Tuplefromdataclassesimportdataclassimportbinaryninjafrom.import_binaryninjacoreascorefrom.importdatabufferfrom.importdecoratorsfrom.enumsimportRegisterValueType,VariableSourceType,DeadStoreElimination,FunctionGraphType,BuiltinTypeFunctionOrILFunction=Union["binaryninja.function.Function","binaryninja.lowlevelil.LowLevelILFunction","binaryninja.mediumlevelil.MediumLevelILFunction","binaryninja.highlevelil.HighLevelILFunction"]
[docs]@dataclass(frozen=True)classLookupTableEntry:from_values:List[int]to_value:inttype:RegisterValueType=RegisterValueType.LookupTableValuedef__repr__(self):returnf"[{', '.join([f'{i:#x}'foriinself.from_values])}] ->{self.to_value:#x}"
[docs]@dataclass(frozen=True)classRegisterValue:value:intoffset:inttype:RegisterValueType=RegisterValueType.UndeterminedValueconfidence:int=core.max_confidencesize:int=0def_to_core_struct(self)->core.BNRegisterValue:result=core.BNRegisterValue()result.state=self.typeresult.value=self.valueresult.offset=self.offsetresult.size=self.sizereturnresultdef_to_core_struct_with_confidence(self):result=core.BNRegisterValueWithConfidence()result.value=self._to_core_struct()result.confidence=self.confidencereturnresultdef__bool__(self):returnself.value!=0def__int__(self):returnself.valuedef__eq__(self,other):ifisinstance(other,int):returnint(self)==otherelifisinstance(other,bool):returnbool(self)==otherelifisinstance(other,self.__class__):return(self.type,self.offset,self.type,self.confidence)==(other.type,other.offset,other.type,other.confidence)assertFalse,f"no comparison for types{repr(self)} and{repr(other)}"
[docs]@classmethoddeffrom_BNRegisterValue(cls,reg_value:Union[core.BNRegisterValue,core.BNRegisterValueWithConfidence],arch:Optional['binaryninja.architecture.Architecture']=None)->'RegisterValue':confidence=core.max_confidenceifisinstance(reg_value,core.BNRegisterValueWithConfidence):confidence=reg_value.confidencereg_value=reg_value.valueifreg_value.state==RegisterValueType.EntryValue:reg=NoneifarchisnotNone:reg=arch.get_reg_name(binaryninja.architecture.RegisterIndex(reg_value.value))returnEntryRegisterValue(reg_value.value,reg=reg,confidence=confidence)elifreg_value.state==RegisterValueType.ConstantValue:returnConstantRegisterValue(reg_value.value,confidence=confidence)elifreg_value.state==RegisterValueType.ConstantPointerValue:returnConstantPointerRegisterValue(reg_value.value,confidence=confidence)elifreg_value.state==RegisterValueType.StackFrameOffset:returnStackFrameOffsetRegisterValue(reg_value.value,confidence=confidence)elifreg_value.state==RegisterValueType.ImportedAddressValue:returnImportedAddressRegisterValue(reg_value.value,confidence=confidence)elifreg_value.state==RegisterValueType.UndeterminedValue:returnUndetermined()elifreg_value.state==RegisterValueType.ReturnAddressValue:returnReturnAddressRegisterValue(reg_value.value,confidence=confidence)elifreg_value.state==RegisterValueType.ExternalPointerValue:returnExternalPointerRegisterValue(reg_value.value,reg_value.offset,confidence=confidence)elifreg_value.state&RegisterValueType.ConstantDataValue==RegisterValueType.ConstantDataValue:returnConstantDataRegisterValue(reg_value.value,0,RegisterValueType(reg_value.state),confidence=confidence,size=reg_value.size)assertFalse,f"RegisterValueType{reg_value.state} not handled"
[docs]@classmethoddefto_BNRegisterValue(cls,reg_value:'RegisterValue')->core.BNRegisterValue:returnreg_value._to_core_struct()
[docs]@dataclass(frozen=True,eq=False)classUndetermined(RegisterValue):value:int=0offset:int=0type:RegisterValueType=RegisterValueType.UndeterminedValuedef__repr__(self):return"<undetermined>"
[docs]@dataclass(frozen=True,eq=False)classConstantRegisterValue(RegisterValue):offset:int=0type:RegisterValueType=RegisterValueType.ConstantValuedef__repr__(self):returnf"<const{self.value:#x}>"
[docs]@dataclass(frozen=True,eq=False)classConstantPointerRegisterValue(RegisterValue):offset:int=0type:RegisterValueType=RegisterValueType.ConstantPointerValuedef__repr__(self):returnf"<const ptr{self.value:#x}>"
[docs]@dataclass(frozen=True,eq=False)classImportedAddressRegisterValue(RegisterValue):offset:int=0type:RegisterValueType=RegisterValueType.ImportedAddressValuedef__repr__(self):returnf"<imported address from entry{self.value:#x}>"
[docs]@dataclass(frozen=True,eq=False)classReturnAddressRegisterValue(RegisterValue):offset:int=0type:RegisterValueType=RegisterValueType.ReturnAddressValuedef__repr__(self):return"<return address>"
[docs]@dataclass(frozen=True,eq=False)classEntryRegisterValue(RegisterValue):value:int=0offset:int=0type:RegisterValueType=RegisterValueType.EntryValuereg:Optional['binaryninja.architecture.RegisterName']=Nonedef__repr__(self):ifself.regisnotNone:returnf"<entry{self.reg}>"returnf"<entry{self.value}>"
[docs]@dataclass(frozen=True,eq=False)classStackFrameOffsetRegisterValue(RegisterValue):offset:int=0type:RegisterValueType=RegisterValueType.StackFrameOffsetdef__repr__(self):returnf"<stack frame offset{self.value:#x}>"
[docs]@dataclass(frozen=True,eq=False)classExternalPointerRegisterValue(RegisterValue):type:RegisterValueType=RegisterValueType.ExternalPointerValuedef__repr__(self):returnf"<external{self.value:#x} + offset{self.offset:#x}>"
[docs]@dataclass(frozen=True,eq=False)classConstantDataRegisterValue(RegisterValue):def__repr__(self):ifself.type==RegisterValueType.ConstantDataZeroExtendValue:returnf"<const data{{zx.{self.size}({self.value:#x})}}>"ifself.type==RegisterValueType.ConstantDataSignExtendValue:returnf"<const data{{sx.{self.size}({self.value:#x})}}>"ifself.type==RegisterValueType.ConstantDataAggregateValue:returnf"<const data{{aggregate.{self.size}}} @{self.value:#x}>"returnf"<const data{{invalid}}{self.type}{self.value:#x}>"
[docs]@dataclass(frozen=True,eq=False)classConstantData(RegisterValue):function:'_function.Function'=Nonedef__repr__(self):ifself.type==RegisterValueType.ConstantDataZeroExtendValue:returnf"<{self.__class__.__name__}:{{zx.{self.size}({self.value:#x})}}>"ifself.type==RegisterValueType.ConstantDataSignExtendValue:returnf"<{self.__class__.__name__}:{{sx.{self.size}({self.value:#x})}}>"ifself.type==RegisterValueType.ConstantDataAggregateValue:returnf"<{self.__class__.__name__}:{{aggregate.{self.size}}} @{self.value:#x}>"returnf"<{self.__class__.__name__}:{{invalid}}{self.type}{self.value:#x}>"@propertydefdata(self)->databuffer.DataBuffer:ifself.functionisNone:raiseValueError(f"ConstantData requires a Function instance:{self.size}")returnself.function.get_constant_data(self.type,self.value,self.size)@propertydefdata_and_builtin(self)->Tuple[databuffer.DataBuffer,BuiltinType]:ifself.functionisNone:raiseValueError(f"ConstantData requires a Function instance:{self.size}")returnself.function.get_constant_data_and_builtin(self.type,self.value,self.size)
[docs]@dataclass(frozen=True)classValueRange:start:intend:intstep:intdef__repr__(self):ifself.step==1:returnf"<range:{self.start:#x} to{self.end:#x}>"returnf"<range:{self.start:#x} to{self.end:#x}, step{self.step:#x}>"def__contains__(self,other):ifnotisinstance(other,int):returnNotImplementedreturnotherinrange(self.start,self.end,self.step)
[docs]@decorators.passiveclassPossibleValueSet:"""`class PossibleValueSet` PossibleValueSet is used to define possible valuesthat a variable can take. It contains methods to instantiate differentvalue sets such as Constant, Signed/Unsigned Ranges, etc."""
[docs]def__init__(self,arch=None,value=None):ifvalueisNone:self._type=RegisterValueType.UndeterminedValuereturnself._type=RegisterValueType(value.state)ifvalue.state==RegisterValueType.EntryValue:ifarchisNone:self._reg=value.valueelse:self._reg=arch.get_reg_name(value.value)elifvalue.state==RegisterValueType.ConstantValue:self._value=value.valueelifvalue.state==RegisterValueType.ConstantPointerValue:self._value=value.valueelifvalue.state==RegisterValueType.StackFrameOffset:self._offset=value.valueelifvalue.state&RegisterValueType.ConstantDataValue==RegisterValueType.ConstantDataValue:self._value=value.valueself._size=value.sizeelifvalue.state==RegisterValueType.SignedRangeValue:self._offset=value.valueself._ranges=[]foriinrange(0,value.count):start=value.ranges[i].startend=value.ranges[i].endstep=value.ranges[i].stepifstart&(1<<63):start|=~((1<<63)-1)ifend&(1<<63):end|=~((1<<63)-1)self._ranges.append(ValueRange(start,end,step))elifvalue.state==RegisterValueType.UnsignedRangeValue:self._offset=value.valueself._ranges=[]foriinrange(0,value.count):start=value.ranges[i].startend=value.ranges[i].endstep=value.ranges[i].stepself._ranges.append(ValueRange(start,end,step))elifvalue.state==RegisterValueType.LookupTableValue:self._table=[]self._mapping={}foriinrange(0,value.count):from_list=[]forjinrange(0,value.table[i].fromCount):from_list.append(value.table[i].fromValues[j])self._mapping[value.table[i].fromValues[j]]=value.table[i].toValueself._table.append(LookupTableEntry(from_list,value.table[i].toValue))elif(value.state==RegisterValueType.InSetOfValues)or(value.state==RegisterValueType.NotInSetOfValues):self._values=set()foriinrange(0,value.count):self._values.add(value.valueSet[i])self._count=value.count
def__repr__(self):ifself._type==RegisterValueType.EntryValue:returnf"<entry{self.reg}>"ifself._type==RegisterValueType.ConstantValue:returnf"<const{self.value:#x}>"ifself._type==RegisterValueType.ConstantPointerValue:returnf"<const ptr{self.value:#x}>"ifself._type==RegisterValueType.StackFrameOffset:returnf"<stack frame offset{self._offset:#x}>"ifself._type==RegisterValueType.ConstantDataZeroExtendValue:returnf"<const data{{zx.{self._size}({self.value:#x})}}>"ifself._type==RegisterValueType.ConstantDataSignExtendValue:returnf"<const data{{sx.{self._size}({self.value:#x})}}>"ifself._type==RegisterValueType.ConstantDataAggregateValue:returnf"<const data{{aggregate.{self._size}}} @{self.value:#x}>"ifself._type==RegisterValueType.SignedRangeValue:returnf"<signed ranges:{repr(self.ranges)}>"ifself._type==RegisterValueType.UnsignedRangeValue:returnf"<unsigned ranges:{repr(self.ranges)}>"ifself._type==RegisterValueType.LookupTableValue:returnf"<table:{', '.join([repr(i)foriinself.table])}>"ifself._type==RegisterValueType.InSetOfValues:returnf"<in set([{', '.join(hex(i)foriinsorted(self.values))}])>"ifself._type==RegisterValueType.NotInSetOfValues:returnf"<not in set([{', '.join(hex(i)foriinsorted(self.values))}])>"ifself._type==RegisterValueType.ReturnAddressValue:return"<return address>"return"<undetermined>"def__contains__(self,other):ifself.typein[RegisterValueType.ConstantValue,RegisterValueType.ConstantPointerValue]andisinstance(other,int):returnself.value==otherifself.typein[RegisterValueType.ConstantValue,RegisterValueType.ConstantPointerValue]andhasattr(other,"value"):returnself.value==other.valueifnotisinstance(other,int):returnNotImplemented#Initial implementation only checks numbers, no set logicifself.type==RegisterValueType.StackFrameOffset:returnNotImplementedifself.typein[RegisterValueType.SignedRangeValue,RegisterValueType.UnsignedRangeValue]:forrnginself.ranges:ifotherinrng:returnTruereturnFalseifself.type==RegisterValueType.InSetOfValues:returnotherinself.valuesifself.type==RegisterValueType.NotInSetOfValues:returnnototherinself.valuesreturnNotImplementeddef__eq__(self,other):# Allow comparing some value types to an intifself.typein[RegisterValueType.ConstantValue,RegisterValueType.ConstantPointerValue]andisinstance(other,int):returnself.value==other# Otherwise just allow comparing to other PossibleValueSet instancesifnotisinstance(other,self.__class__):returnNotImplemented# If the PVS type isn't the same, they're not equalifself.type!=other.type:returnFalseifself.typein[RegisterValueType.ConstantValue,RegisterValueType.ConstantPointerValue]:returnself.value==other.valueelifself.type==RegisterValueType.StackFrameOffset:returnself.offset==other.offsetelifself.type&RegisterValueType.ConstantDataValue==RegisterValueType.ConstantDataValue:returnself.value==other.valueandself._size==other._sizeelifself.typein[RegisterValueType.SignedRangeValue,RegisterValueType.UnsignedRangeValue]:returnself.ranges==other.rangeselifself.typein[RegisterValueType.InSetOfValues,RegisterValueType.NotInSetOfValues]:returnself.values==other.valueselifself.type==RegisterValueType.UndeterminedValue:returnTrue# UndeterminedValue is always equal to itselfreturnNotImplementeddef__ne__(self,other):ifnotisinstance(other,self.__class__):returnNotImplementedreturnnot(self==other)def_to_core_struct(self)->core.BNPossibleValueSet:result=core.BNPossibleValueSet()result.state=RegisterValueType(self.type)ifself.type==RegisterValueType.UndeterminedValue:returnresultelifself.type==RegisterValueType.ConstantValue:result.value=self.valueelifself.type==RegisterValueType.ConstantPointerValue:result.value=self.valueelifself.type==RegisterValueType.StackFrameOffset:result.offset=self.valueelifself.type&RegisterValueType.ConstantDataValue==RegisterValueType.ConstantDataValue:result.value=self.valueresult.size=self.sizeelifself.type==RegisterValueType.SignedRangeValue:result.offset=self.valueresult.ranges=(core.BNValueRange*self.count)()foriinrange(0,self.count):start=self.ranges[i].startend=self.ranges[i].endifstart&(1<<63):start|=~((1<<63)-1)ifend&(1<<63):end|=~((1<<63)-1)value_range=core.BNValueRange()value_range.start=startvalue_range.end=endvalue_range.step=self.ranges[i].stepresult.ranges[i]=value_rangeresult.count=self.countelifself.type==RegisterValueType.UnsignedRangeValue:result.offset=self.valueresult.ranges=(core.BNValueRange*self.count)()foriinrange(0,self.count):value_range=core.BNValueRange()value_range.start=self.ranges[i].startvalue_range.end=self.ranges[i].endvalue_range.step=self.ranges[i].stepresult.ranges[i]=value_rangeresult.count=self.countelifself.type==RegisterValueType.LookupTableValue:result.table=[]result.mapping={}foriinrange(self.count):from_list=[]forjinrange(0,len(self.table[i].from_values)):from_list.append(self.table[i].from_values[j])result.mapping[self.table[i].from_values[j]]=result.table[i].to_valueresult.table.append(LookupTableEntry(from_list,result.table[i].to_value))result.count=self.countelif(self.type==RegisterValueType.InSetOfValues)or(self.type==RegisterValueType.NotInSetOfValues):values=(ctypes.c_longlong*self.count)()i=0forvalueinself.values:values[i]=valuei+=1int_ptr=ctypes.POINTER(ctypes.c_longlong)result.valueSet=ctypes.cast(values,int_ptr)result.count=self.countreturnresult@propertydeftype(self)->RegisterValueType:returnself._type@propertydefreg(self)->'binaryninja.architecture.RegisterName':returnself._reg@propertydefvalue(self)->int:returnself._value@propertydefoffset(self)->int:returnself._offset@propertydefsize(self)->int:returnself._size@propertydefranges(self)->List[ValueRange]:returnself._ranges@propertydeftable(self)->List[LookupTableEntry]:returnself._table@propertydefmapping(self)->Dict[int,int]:returnself._mapping@propertydefvalues(self)->Set[int]:returnself._values@propertydefcount(self)->int:returnself._count
[docs]@staticmethoddefundetermined()->'PossibleValueSet':"""Create a PossibleValueSet object of type UndeterminedValue.:return: PossibleValueSet object of type UndeterminedValue:rtype: PossibleValueSet"""returnPossibleValueSet()
[docs]@staticmethoddefconstant(value:int)->'PossibleValueSet':"""Create a constant valued PossibleValueSet object.:param int value: Integer value of the constant:rtype: PossibleValueSet"""result=PossibleValueSet()result._type=RegisterValueType.ConstantValueresult._value=valuereturnresult
[docs]@staticmethoddefconstant_ptr(value:int)->'PossibleValueSet':"""Create constant pointer valued PossibleValueSet object.:param int value: Integer value of the constant pointer:rtype: PossibleValueSet"""result=PossibleValueSet()result._type=RegisterValueType.ConstantPointerValueresult._value=valuereturnresult
[docs]@staticmethoddefstack_frame_offset(offset:int)->'PossibleValueSet':"""Create a PossibleValueSet object for a stack frame offset.:param int offset: Integer value of the offset:rtype: PossibleValueSet"""result=PossibleValueSet()result._type=RegisterValueType.StackFrameOffsetresult._offset=offsetreturnresult
[docs]@staticmethoddefsigned_range_value(ranges:List[ValueRange])->'PossibleValueSet':"""Create a PossibleValueSet object for a signed range of values.:param list(ValueRange) ranges: List of ValueRanges:rtype: PossibleValueSet:Example:>>> v_1 = ValueRange(-5, -1, 1)>>> v_2 = ValueRange(7, 10, 1)>>> val = PossibleValueSet.signed_range_value([v_1, v_2])<signed ranges: [<range: -0x5 to -0x1>, <range: 0x7 to 0xa>]>"""result=PossibleValueSet()result._value=0result._type=RegisterValueType.SignedRangeValueresult._ranges=rangesresult._count=len(ranges)returnresult
[docs]@staticmethoddefunsigned_range_value(ranges:List[ValueRange])->'PossibleValueSet':"""Create a PossibleValueSet object for a unsigned signed range of values.:param list(ValueRange) ranges: List of ValueRanges:rtype: PossibleValueSet:Example:>>> v_1 = ValueRange(0, 5, 1)>>> v_2 = ValueRange(7, 10, 1)>>> val = PossibleValueSet.unsigned_range_value([v_1, v_2])<unsigned ranges: [<range: 0x0 to 0x5>, <range: 0x7 to 0xa>]>"""result=PossibleValueSet()result._value=0result._type=RegisterValueType.UnsignedRangeValueresult._ranges=rangesresult._count=len(ranges)returnresult
[docs]@staticmethoddefin_set_of_values(values:Union[List[int],Set[int]])->'PossibleValueSet':"""Create a PossibleValueSet object for a value in a set of values.:param list(int) values: List of integer values:rtype: PossibleValueSet"""result=PossibleValueSet()result._type=RegisterValueType.InSetOfValuesresult._values=set(values)result._count=len(values)returnresult
[docs]@staticmethoddefnot_in_set_of_values(values)->'PossibleValueSet':"""Create a PossibleValueSet object for a value NOT in a set of values.:param list(int) values: List of integer values:rtype: PossibleValueSet"""result=PossibleValueSet()result._type=RegisterValueType.NotInSetOfValuesresult._values=set(values)result._count=len(values)returnresult
[docs]@staticmethoddeflookup_table_value(lookup_table,mapping)->'PossibleValueSet':"""Create a PossibleValueSet object for a value which is a member of alookup table.:param list(LookupTableEntry) lookup_table: List of table entries:param dict of (int, int) mapping: Mapping used for resolution:rtype: PossibleValueSet"""result=PossibleValueSet()result._type=RegisterValueType.LookupTableValueresult._table=lookup_tableresult._mapping=mappingreturnresult
[docs]@dataclass(frozen=True)classStackVariableReference:_source_operand:Optional[int]type:'binaryninja.types.Type'name:strvar:'Variable'referenced_offset:intsize:intdef__repr__(self):ifself.source_operandisNone:ifself.referenced_offset!=self.var.storage:returnf"<ref to{self.name}{self.referenced_offset-self.var.storage:+#x}>"returnf"<ref to{self.name}>"ifself.referenced_offset!=self.var.storage:returnf"<operand{self.source_operand} ref to{self.var.storage}{self.var.storage:+#x}>"returnf"<operand{self.source_operand} ref to{self.name}>"@propertydefsource_operand(self):ifself._source_operand==0xffffffff:returnNonereturnself._source_operand
[docs]@dataclass(frozen=True,order=True)classCoreVariable:"""``class CoreVariable`` is the base class for other variable types,such as :py:meth:`VariableNameAndType` and :py:meth:`Variable`:cvar index: Internal identifier:cvar storage: If this variable is a stack variable(`source_type == VariableSourceType.StackVariableSourceType`),then the storage location is the offset onto the stack that containsthe first byte of this variable. Otherwise it's used as an internal identifier."""_source_type:intindex:intstorage:int@propertydefidentifier(self)->int:"""A UID for a variable within a function."""returncore.BNToVariableIdentifier(self.to_BNVariable())@propertydefsource_type(self)->VariableSourceType:"""Whether this variable was created based off of an underlying register, stack location, or flag."""returnVariableSourceType(self._source_type)
[docs]defto_BNVariable(self):v=core.BNVariable()v.type=self._source_typev.index=self.indexv.storage=self.storagereturnv
[docs]@classmethoddeffrom_BNVariable(cls,var:core.BNVariable):returncls(var.type,var.index,var.storage)
[docs]@classmethoddeffrom_identifier(cls,identifier):var=core.BNFromVariableIdentifier(identifier)returncls(var.type,var.index,var.storage)
[docs]@dataclass(frozen=True,order=True)classVariableNameAndType(CoreVariable):"""``class VariableNameAndType`` is a lightweight wrapper around avariable and its name, useful for shuttling between APIs that requirethem both. While :py:meth:`Variable` has :py:meth:`Variable.name` and:py:meth:`Variable.type` fields, those require additional core callseach time you fetch them.:cvar name: The variable's name:cvar type: The variable's type"""name:strtype:'binaryninja.types.Type'
[docs]@classmethoddeffrom_identifier(cls,identifier,name,type):var=core.BNFromVariableIdentifier(identifier)returncls(var.type,var.index,var.storage,name,type)
[docs]@classmethoddeffrom_core_variable(cls,var,name,type):returncls(var.type,var.index,var.storage,name,type)
[docs]classVariable(CoreVariable):"""``class Variable`` represents variables in Binary Ninja. Variables are resolvedin medium level IL, so variables objects are only valid for MLIL and above."""
[docs]def__init__(self,func:FunctionOrILFunction,source_type:VariableSourceType,index:int,storage:int):super(Variable,self).__init__(int(source_type),index,storage)ifisinstance(func,binaryninja.function.Function):self._function=funcself._il_function=Noneelse:self._function=func.source_functionself._il_function=func
[docs]@classmethoddeffrom_variable_name_and_type(cls,func:FunctionOrILFunction,var:VariableNameAndType):returncls(func,VariableSourceType(var.type),var.index,var.storage)
[docs]@classmethoddeffrom_core_variable(cls,func:FunctionOrILFunction,var:CoreVariable):returncls(func,var.source_type,var.index,var.storage)
[docs]@classmethoddeffrom_BNVariable(cls,func:FunctionOrILFunction,var:core.BNVariable):returncls(func,var.type,var.index,var.storage)
[docs]@classmethoddeffrom_identifier(cls,func:FunctionOrILFunction,identifier:int):var=core.BNFromVariableIdentifier(identifier)returncls(func,VariableSourceType(var.type),var.index,var.storage)
def__repr__(self):ifself.typeisnotNone:returnf"<var{self.type.get_string_before_name()}{self.name}{self.type.get_string_after_name()}>"else:returnf"<var{self.name}>"def__str__(self):returnself.namedef__eq__(self,other):ifnotisinstance(other,self.__class__):returnNotImplementedreturnsuper().__eq__(other)and(self._function==other._function)def__ne__(self,other):ifnotisinstance(other,self.__class__):returnNotImplementedreturnnot(self==other)def__lt__(self,other):ifnotisinstance(other,self.__class__):returnNotImplementedreturnsuper().__lt__(other)andself._function<other._functiondef__gt__(self,other):ifnotisinstance(other,self.__class__):returnNotImplementedreturnsuper().__gt__(other)andself._function>other._functiondef__le__(self,other):ifnotisinstance(other,self.__class__):returnNotImplementedreturnsuper().__le__(other)andself._function<=other._functiondef__ge__(self,other):ifnotisinstance(other,self.__class__):returnNotImplementedreturnsuper().__ge__(other)andself._function>=other._functiondef__hash__(self):returnhash((self._function,super().__hash__()))@propertydefcore_variable(self)->CoreVariable:"""Retrieve the underlying :py:meth:`CoreVariable` class"""returnCoreVariable(self._source_type,self.index,self.storage)@propertydefvar_name_and_type(self)->VariableNameAndType:"""Convert to :py:meth:`VariableNameAndType` """returnVariableNameAndType.from_core_variable(self,self.name,self.type)@propertydefname(self)->str:"""Name of the variable, Settings this property is slow because it ensures that analysis has been updated. If you are renaming many variables, use :py:meth:`set_name_async`, then call :py:meth:`update_analysis` when complete."""returncore.BNGetVariableNameOrDefault(self._function.handle,self.to_BNVariable())@name.setterdefname(self,name:Optional[str])->None:self.set_name_async(name)self._function.view.update_analysis_and_wait()@propertydeflast_seen_name(self)->str:"""Name of the variable, or the name most recently assigned if the variable has since been removed (read-only). """returncore.BNGetLastSeenVariableNameOrDefault(self._function.handle,self.to_BNVariable())@propertydeftype(self)->Optional['binaryninja.types.Type']:var_type_conf=core.BNGetVariableType(self._function.handle,self.to_BNVariable())ifvar_type_conf.type:returnbinaryninja.types.Type.create(var_type_conf.type,self._function.platform,var_type_conf.confidence)returnNone@type.setterdeftype(self,new_type:'binaryninja.types.Type')->None:self.set_type_async(new_type)self._function.view.update_analysis_and_wait()@propertydefssa_versions(self)->Generator[int,None,None]:"""Returns the SSA versions associated with this variable. Doesn't return anything for aliased variables."""ifself._il_functionisNone:raiseNotImplementedError("No IL function associated with variable")version_count=ctypes.c_ulonglong()ifself._il_function.il_formin[FunctionGraphType.MediumLevelILFunctionGraph,FunctionGraphType.MediumLevelILSSAFormFunctionGraph]:versions=core.BNGetMediumLevelILVariableSSAVersions(self._il_function.handle,self.to_BNVariable(),version_count)elifself._il_function.il_formin[FunctionGraphType.HighLevelILFunctionGraph,FunctionGraphType.HighLevelILSSAFormFunctionGraph]:versions=core.BNGetHighLevelILVariableSSAVersions(self._il_function.handle,self.to_BNVariable(),version_count)else:raiseNotImplementedError("Unsupported IL form")ifversionsisNone:raiseNotImplementedError("No SSA versions; is this an aliased variable?")try:forversion_iinrange(version_count.value):yieldversions[version_i]finally:core.BNFreeILInstructionList(versions)@propertydefdead_store_elimination(self)->DeadStoreElimination:"""returns the dead store elimination setting for this variable"""returnDeadStoreElimination(core.BNGetFunctionVariableDeadStoreElimination(self._function.handle,self.to_BNVariable()))@dead_store_elimination.setterdefdead_store_elimination(self,value):core.BNSetFunctionVariableDeadStoreElimination(self._function.handle,self.to_BNVariable(),value)@propertydefis_parameter_variable(self)->bool:"""returns whether this variable is a function parameter"""returnselfinself._function.parameter_vars@propertydefoffset_to_next_variable(self)->Optional[int]:"""returns number of bytes to the next variable on the stack"""ifself.source_type!=VariableSourceType.StackVariableSourceType:returnNonefori,varinenumerate(self._function.stack_layout):ifvar==self:ifi+1<len(self._function.stack_layout):returnabs(self.storage-self._function.stack_layout[i+1].storage)else:returnabs(self.storage)returnNone@propertydeffunction(self)->'binaryninja.function.Function':"""returns the source Function object which this variable belongs to"""returnself._function@propertydefil_function(self)->'function.ILFunctionType':"""returns the IL Function object which this variable belongs to"""returnself._il_function
[docs]defset_name_async(self,name:Optional[str])->None:"""``set_name_async`` provides a way to asynchronously set the name of a variable. This method should be usedwhen speed is of concern."""ifnameisNone:name=""self._function.create_user_var(self,self.type,name)
[docs]defset_type_async(self,new_type:'binaryninja.types.Type')->None:"""``set_type_async`` provides a way to asynchronously set the type of a variable. This method should be usedwhen speed is of concern."""self._function.create_user_var(self,new_type,self.name)
[docs]defset_name_and_type_async(self,name:Optional[str],new_type:'binaryninja.types.Type')->None:"""``set_name_and_type_async`` provides a way to asynchronously set both the name and type of a variable. This method should be usedwhen speed is of concern."""self._function.create_user_var(self,new_type,name)
[docs]@dataclass(frozen=True)classConstantReference:value:intsize:intpointer:boolintermediate:booldef__repr__(self):ifself.pointer:return"<constant pointer%#x>"%self.valueifself.size==0:return"<constant%#x>"%self.valuereturn"<constant%#x size%d>"%(self.value,self.size)
[docs]@dataclass(frozen=True)classIndirectBranchInfo:source_arch:'binaryninja.architecture.Architecture'source_addr:intdest_arch:'binaryninja.architecture.Architecture'dest_addr:intauto_defined:booldef__repr__(self):returnf"<branch{self.source_arch.name}:{self.source_addr:#x} ->{self.dest_arch.name}:{self.dest_addr:#x}>"
[docs]@decorators.passiveclassParameterVariables:
[docs]def__init__(self,var_list:List[Variable],confidence:int=core.max_confidence,func:Optional['binaryninja.function.Function']=None):self._vars=var_listself._confidence=confidenceself._func=func
def__repr__(self):returnf"<ParameterVariables:{str(self._vars)}>"def__len__(self):returnlen(self._vars)def__iter__(self)->Generator['Variable',None,None]:forvarinself._vars:yieldvardef__eq__(self,other)->bool:return(self._vars,self._confidence,self._func)==(other._vars,other._confidence,other._func)def__getitem__(self,idx)->'Variable':returnself._vars[idx]def__setitem__(self,idx:int,value:'Variable'):self._vars[idx]=valueifself._funcisnotNone:self._func.parameter_vars=self
[docs]defwith_confidence(self,confidence:int)->'ParameterVariables':returnParameterVariables(list(self._vars),confidence,self._func)
@propertydefvars(self)->List['Variable']:returnself._vars@propertydefconfidence(self)->int:returnself._confidence@propertydeffunction(self)->Optional['binaryninja.function.Function']:returnself._func
[docs]@dataclass(frozen=True,order=True)classAddressRange:start:int# Inclusive starting addressend:int# Exclusive ending addressdef__repr__(self):returnf"<{self.start:#x}-{self.end:#x}>"def__contains__(self,i:int):returnself.start<=i<self.end