Source code for binaryninja.basicblock

# 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.importctypesfromdataclassesimportdataclassfromtypingimportGenerator,Optional,List,Tuple,Union# Binary Ninja componentsimportbinaryninjafrom.import_binaryninjacoreascorefrom.enumsimportBranchType,HighlightStandardColorfrom.importbinaryviewfrom.importarchitecturefrom.importhighlightas_highlightfrom.importfunctionas_function
[docs]@dataclass(frozen=True)classBasicBlockEdge:"""``class BasicBlockEdge`` represents the edges that connect basic blocks in graph view.:cvar type: The :py:meth:`enums.BranchType` of the edge; Whether the edge is a true branch, false branch, unconditional, etc.:cvar source: The basic block that the edge originates from.:cvar target: The basic block that the edge is going to.:cvar backedge: Whether this edge targets to a node whose control flow can eventually flow back through the source node of this edge.:Example:>>> current_basic_block.outgoing_edges[<TrueBranch: x86_64@0x6>, <FalseBranch: x86_64@0x1f>]"""type:BranchTypesource:'BasicBlock'target:'BasicBlock'back_edge:boolfall_through:booldef__repr__(self):ifself.type==BranchType.UnresolvedBranch:returnf"<{self.type.name}>"elifself.target.arch:returnf"<{self.type.name}:{self.target.arch.name}@{self.target.start:#x}>"else:returnf"<{self.type.name}:{self.target.start:#x}>"
[docs]@dataclass(frozen=True)classPendingBasicBlockEdge:"""``class PendingBasicBlockEdge`` represents a pending edge that has not yet been resolved.:cvar type: The edge branch type.:cvar arch: The architecture of the target basic block.:cvar target: The address of the target basic block.:cvar fall_through: Whether this edge is a fallthrough edge."""type:BranchTypearch:'architecture.Architecture'target:intfallthrough:bool
[docs]classBasicBlock:"""The ``class BasicBlock`` object is returned during analysis and should not be directly instantiated.Basic blocks contain a sequence of instructions that must execute in-order with no branches.We include calls in basic blocks, which technically violates that assumption, but you can markfunctions as `func.can_return = False` if a given function should terminate basic blocks.:Example:>>> for func in bv.functions:>>> for bb in func:>>> # Any block-based analysis could start here>>> for inst in bb:>>> pass # Optionally do something here with instructions"""
[docs]def__init__(self,handle:core.BNBasicBlockHandle,view:Optional['binaryview.BinaryView']=None):self._view=view_handle=core.BNBasicBlockHandleself.handle:core.BNBasicBlockHandle=ctypes.cast(handle,_handle)self._arch=Noneself._func=Noneself._instStarts:Optional[List[int]]=Noneself._instLengths:Optional[List[int]]=None
def__del__(self):ifcoreisnotNone:core.BNFreeBasicBlock(self.handle)@classmethoddef_from_core_block(cls,block:core.BNBasicBlockHandle)->Optional[Union['BasicBlock','binaryninja.lowlevelil.LowLevelILBasicBlock','binaryninja.mediumlevelil.MediumLevelILBasicBlock','binaryninja.highlevelil.HighLevelILBasicBlock']]:"""From a BNBasicBlockHandle, get a BasicBlock or one of the IL subclasses (takes ref)"""func_handle=core.BNGetBasicBlockFunction(block)ifnotfunc_handle:core.BNFreeBasicBlock(block)returnNoneview=binaryview.BinaryView(handle=core.BNGetFunctionData(func_handle))func=_function.Function(view,func_handle)ifcore.BNIsLowLevelILBasicBlock(block):returnbinaryninja.lowlevelil.LowLevelILBasicBlock(block,binaryninja.lowlevelil.LowLevelILFunction(func.arch,core.BNGetBasicBlockLowLevelILFunction(block),func),view)elifcore.BNIsMediumLevelILBasicBlock(block):mlil_func=binaryninja.mediumlevelil.MediumLevelILFunction(func.arch,core.BNGetBasicBlockMediumLevelILFunction(block),func)returnbinaryninja.mediumlevelil.MediumLevelILBasicBlock(block,mlil_func,view)elifcore.BNIsHighLevelILBasicBlock(block):hlil_func=binaryninja.highlevelil.HighLevelILFunction(func.arch,core.BNGetBasicBlockHighLevelILFunction(block),func)returnbinaryninja.highlevelil.HighLevelILBasicBlock(block,hlil_func,view)else:returnBasicBlock(block,view)def__repr__(self):arch=self.archifself.is_il:# IL indices are shown as decimalifarch:returnf"<{self.__class__.__name__}:{arch.name}@{self.start}-{self.end}>"else:returnf"<{self.__class__.__name__}:{self.start}-{self.end}>"else:ifarch:returnf"<{self.__class__.__name__}:{arch.name}@{self.start:#x}-{self.end:#x}>"else:returnf"<{self.__class__.__name__}:{self.start:#x}-{self.end:#x}>"def__len__(self):returnint(core.BNGetBasicBlockLength(self.handle))def__lt__(self,other:'BasicBlock')->bool:ifnotisinstance(other,self.__class__):returnNotImplementedreturnself.start<other.startdef__gt__(self,other:'BasicBlock')->bool:ifnotisinstance(other,self.__class__):returnNotImplementedreturnself.start>other.startdef__le__(self,other:'BasicBlock')->bool:ifnotisinstance(other,self.__class__):returnNotImplementedreturnself.start<=other.startdef__ge__(self,other:'BasicBlock')->bool:ifnotisinstance(other,self.__class__):returnNotImplementedreturnself.start>=other.startdef__eq__(self,other):ifnotisinstance(other,self.__class__):returnNotImplementedreturnctypes.addressof(self.handle.contents)==ctypes.addressof(other.handle.contents)def__ne__(self,other):ifnotisinstance(other,self.__class__):returnNotImplementedreturnnot(self==other)def__hash__(self):returnhash((self.start,self.end,self.arch))def__iter__(self)->Generator[Tuple[List['_function.InstructionTextToken'],int],None,None]:ifself.viewisNone:raiseException("Attempting to iterate a Basic Block with no BinaryView")ifself._instStartsisNone:# don't add instruction start cache--the object is likely ephemeralidx=self.startwhileidx<self.end:data=self.view.read(idx,min(self.arch.max_instr_length,self.end-idx))result=self.arch.get_instruction_text(data,idx)assertresultisnotNonetext,size=resultifsize==0:breakyieldtext,sizeidx+=sizeelse:assertself._instLengthsisnotNoneforstart,lengthinzip(self._instStarts,self._instLengths):result=self.arch.get_instruction_text(self.view.read(start,length),start)assertresultisnotNonetext,size=resultifsize==0:breakyieldtext,sizedef__getitem__(self,i):self._buildStartCache()assertself._instStartsisnotNoneassertself._instLengthsisnotNoneifself.viewisNone:raiseException("Attempting to iterate a Basic Block with no BinaryView")ifisinstance(i,slice):return[self[index]forindexinrange(*i.indices(len(self._instStarts)))]start=self._instStarts[i]length=self._instLengths[i]data=self.view.read(start,length)returnself.arch.get_instruction_text(data,start)def__contains__(self,i:int):returnself.start<=i<self.enddef_buildStartCache(self)->None:ifself._instStartsisNone:# build the instruction start cacheifself.viewisNone:raiseException("Attempting to buildStartCache when BinaryView for BasicBlock is None")self._instStarts=[]self._instLengths=[]start=self.startwhilestart<self.end:length=self.view.get_instruction_length(start,self.arch)iflength==0:# invalid instruction. avoid infinite loopbreakself._instLengths.append(length)self._instStarts.append(start)start+=lengthdef_create_instance(self,handle:core.BNBasicBlockHandle)->'BasicBlock':"""Internal method used to instantiate child instances"""returnBasicBlock(handle,self.view)@propertydefinstruction_count(self)->int:self._buildStartCache()assertself._instStartsisnotNonereturnlen(self._instStarts)@propertydeffunction(self)->Optional['_function.Function']:"""Basic block function (read-only)"""ifself._funcisnotNone:returnself._funcfunc=core.BNGetBasicBlockFunction(self.handle)iffuncisNone:returnNoneself._func=_function.Function(self._view,func)returnself._func@propertydefil_function(self)->Optional['_function.ILFunctionType']:"""IL Function of which this block is a part, if the block is part of an IL Function."""func=self.functioniffuncisNone:returnNoneil_type=self.function_graph_typeifil_type==_function.FunctionGraphType.NormalFunctionGraph:returnNoneelifil_type==_function.FunctionGraphType.LowLevelILFunctionGraph:returnfunc.low_level_ilelifil_type==_function.FunctionGraphType.LiftedILFunctionGraph:returnfunc.lifted_ilelifil_type==_function.FunctionGraphType.LowLevelILSSAFormFunctionGraph:func_llil=func.low_level_ilreturnfunc_llil.ssa_formiffunc_llilisnotNoneelseNoneelifil_type==_function.FunctionGraphType.MediumLevelILFunctionGraph:returnfunc.medium_level_ilelifil_type==_function.FunctionGraphType.MediumLevelILSSAFormFunctionGraph:func_mlil=func.medium_level_ilreturnfunc_mlil.ssa_formiffunc_mlilisnotNoneelseNoneelifil_type==_function.FunctionGraphType.MappedMediumLevelILFunctionGraph:returnfunc.mapped_medium_level_ilelifil_type==_function.FunctionGraphType.MappedMediumLevelILSSAFormFunctionGraph:func_mmlil=func.mapped_medium_level_ilreturnfunc_mmlil.ssa_formiffunc_mmlilisnotNoneelseNoneelifil_type==_function.FunctionGraphType.HighLevelILFunctionGraph:returnfunc.high_level_ilelifil_type==_function.FunctionGraphType.HighLevelILSSAFormFunctionGraph:func_hlil=func.high_level_ilreturnfunc_hlil.ssa_formiffunc_hlilisnotNoneelseNoneelifil_type==_function.FunctionGraphType.HighLevelLanguageRepresentationFunctionGraph:returnfunc.high_level_ilelse:returnNone@propertydefil_function_if_available(self)->Optional['_function.ILFunctionType']:"""IL Function of which this block is a part, if the block is part of an IL Function, and if the function has generated IL already."""func=self.functioniffuncisNone:returnNoneil_type=self.function_graph_typeifil_type==_function.FunctionGraphType.NormalFunctionGraph:returnNoneelifil_type==_function.FunctionGraphType.LowLevelILFunctionGraph:returnfunc.llil_if_availableelifil_type==_function.FunctionGraphType.LiftedILFunctionGraph:returnfunc.lifted_il_if_availableelifil_type==_function.FunctionGraphType.LowLevelILSSAFormFunctionGraph:iffunc.llil_if_availableisNone:returnNonereturnfunc.llil_if_available.ssa_formelifil_type==_function.FunctionGraphType.MediumLevelILFunctionGraph:returnfunc.mlil_if_availableelifil_type==_function.FunctionGraphType.MediumLevelILSSAFormFunctionGraph:iffunc.mlil_if_availableisNone:returnNonereturnfunc.mlil_if_available.ssa_formelifil_type==_function.FunctionGraphType.MappedMediumLevelILFunctionGraph:returnfunc.mmlil_if_availableelifil_type==_function.FunctionGraphType.MappedMediumLevelILSSAFormFunctionGraph:iffunc.mmlil_if_availableisNone:returnNonereturnfunc.mmlil_if_available.ssa_formelifil_type==_function.FunctionGraphType.HighLevelILFunctionGraph:returnfunc.hlil_if_availableelifil_type==_function.FunctionGraphType.HighLevelILSSAFormFunctionGraph:iffunc.hlil_if_availableisNone:returnNonereturnfunc.hlil_if_available.ssa_formelifil_type==_function.FunctionGraphType.HighLevelLanguageRepresentationFunctionGraph:returnfunc.hlil_if_availableelse:returnNone@propertydefview(self)->Optional['binaryview.BinaryView']:"""BinaryView that contains the basic block (read-only)"""ifself._viewisnotNone:returnself._viewifself.functionisNone:returnNoneself._view=self.function.viewreturnself._view@propertydefarch(self)->'architecture.Architecture':"""Basic block architecture (read-only)"""# The arch for a BasicBlock isn't going to change so just cache# it the first time we need itifself._archisnotNone:returnself._archarch=core.BNGetBasicBlockArchitecture(self.handle)assertarchisnotNone,"core.BNGetBasicBlockArchitecture returned None"self._arch=architecture.CoreArchitecture._from_cache(arch)returnself._arch@propertydefsource_block(self)->Optional['BasicBlock']:"""The corresponding assembly-level basic block for this basic block (read-only)"""block=core.BNGetBasicBlockSource(self.handle)ifblockisNone:returnNonereturnBasicBlock(block,self._view)@propertydefstart(self)->int:"""Basic block start (read-only)"""returncore.BNGetBasicBlockStart(self.handle)@propertydefend(self)->int:"""Basic block end (read-only)"""returncore.BNGetBasicBlockEnd(self.handle)@end.setterdefend(self,value:int)->None:"""Sets the end of the basic block.. note:: This setter is intended for use by architecture plugins only."""core.BNSetBasicBlockEnd(self.handle,value)@propertydeflength(self)->int:"""Basic block length (read-only)"""returncore.BNGetBasicBlockLength(self.handle)@propertydefindex(self)->int:"""Basic block index in list of blocks for the function (read-only)"""returncore.BNGetBasicBlockIndex(self.handle)def_make_edges(self,edges,count:int,direction:bool)->List[BasicBlockEdge]:assertedgesisnotNone,"Got empty edges list from core"ifself.viewisNone:raiseValueError("Attempting to get BasicBlock edges when BinaryView is None")result:List[BasicBlockEdge]=[]try:foriinrange(0,count):branch_type=BranchType(edges[i].type)handle=core.BNNewBasicBlockReference(edges[i].target)asserthandleisnotNonetarget=self._create_instance(handle)ifdirection:sink,source=target,selfelse:sink,source=self,targetresult.append(BasicBlockEdge(branch_type,sink,source,edges[i].backEdge,edges[i].fallThrough))returnresultfinally:core.BNFreeBasicBlockEdgeList(edges,count)@propertydefoutgoing_edges(self)->List[BasicBlockEdge]:"""List of basic block outgoing edges (read-only)"""count=ctypes.c_ulonglong(0)returnself._make_edges(core.BNGetBasicBlockOutgoingEdges(self.handle,count),count.value,False)@propertydefincoming_edges(self)->List[BasicBlockEdge]:"""List of basic block incoming edges (read-only)"""count=ctypes.c_ulonglong(0)returnself._make_edges(core.BNGetBasicBlockIncomingEdges(self.handle,count),count.value,True)@propertydefhas_undetermined_outgoing_edges(self)->bool:"""Whether basic block has undetermined outgoing edges (read-only)"""returncore.BNBasicBlockHasUndeterminedOutgoingEdges(self.handle)@has_undetermined_outgoing_edges.setterdefhas_undetermined_outgoing_edges(self,value:bool)->None:"""Sets whether basic block has undetermined outgoing edges"""core.BNBasicBlockSetUndeterminedOutgoingEdges(self.handle,value)@propertydefcan_exit(self)->bool:"""Whether basic block can return or is tagged as 'No Return' (read-only)"""returncore.BNBasicBlockCanExit(self.handle)@can_exit.setterdefcan_exit(self,value:bool)->None:"""Sets whether basic block can return or is tagged as 'No Return'"""core.BNBasicBlockSetCanExit(self.handle,value)@propertydefhas_invalid_instructions(self)->bool:"""Whether basic block has any invalid instructions (read-only)"""returncore.BNBasicBlockHasInvalidInstructions(self.handle)@has_invalid_instructions.setterdefhas_invalid_instructions(self,value:bool)->None:"""Sets whether basic block has any invalid instructions"""core.BNBasicBlockSetHasInvalidInstructions(self.handle,value)
[docs]defadd_pending_outgoing_edge(self,typ:BranchType,addr:int,arch:'architecture.Architecture',fallthrough:bool=False)->None:"""Adds a pending outgoing edge to the basic block. This is used to add edges that are not yet resolved... note:: This method is intended for use by architecture plugins only.:param BranchType typ: The type of the branch.:param int addr: The address of the target basic block.:param Architecture arch: The architecture of the target basic block.:param bool fallthrough: Whether this edge is a fallthrough edge."""core.BNBasicBlockAddPendingOutgoingEdge(self.handle,typ.value,addr,arch.handle,fallthrough)
[docs]defget_pending_outgoing_edges(self)->list[PendingBasicBlockEdge]:"""Returns a list of pending outgoing edges for the basic block. These are edges that have not yet been resolved... note:: This method is intended for use by architecture plugins only.:return: List of PendingBasicBlockEdge objects."""count=ctypes.c_ulonglong(0)pending_edges=core.BNGetBasicBlockPendingOutgoingEdges(self.handle,ctypes.byref(count))ifpending_edgesisNone:return[]result:List[PendingBasicBlockEdge]=[]try:foriinrange(count.value):result.append(PendingBasicBlockEdge(type=BranchType(pending_edges[i].type),arch=architecture.CoreArchitecture._from_cache(pending_edges[i].arch),target=pending_edges[i].target,fallthrough=pending_edges[i].fallThrough))returnresultfinally:core.BNFreePendingBasicBlockEdgeList(pending_edges)
[docs]defclear_pending_outgoing_edges(self)->None:"""Clears all pending outgoing edges for the basic block. This is used to remove edges that have not yet been resolved... note:: This method is intended for use by architecture plugins only."""core.BNClearBasicBlockPendingOutgoingEdges(self.handle)
[docs]defget_instruction_data(self,addr:int)->bytes:"""Returns the raw instruction data for the basic block at the specified address... note:: This method is intended for use by architecture plugins only.:return: Raw instruction data as bytes."""size=ctypes.c_ulonglong(0)data=core.BNBasicBlockGetInstructionData(self.handle,addr,ctypes.byref(size))ifdataisNone:returnb''returnctypes.string_at(data,size.value)
[docs]defadd_instruction_data(self,data:bytes)->None:"""Adds raw instruction data to the basic block... note:: This method is intended for use by architecture plugins only.:param bytes data: Raw instruction data to add to the basic block."""ifnotisinstance(data,bytes):raiseTypeError("data must be of type bytes")core.BNBasicBlockAddInstructionData(self.handle,data,len(data))
@propertydeffallthrough_to_function(self)->bool:"""Whether the basic block has a fallthrough edge to a function."""returncore.BNBasicBlockIsFallThroughToFunction(self.handle)@fallthrough_to_function.setterdeffallthrough_to_function(self,value:bool)->None:"""Sets whether the basic block has a fallthrough edge to a function... note:: This setter is intended for use by architecture plugins only."""ifnotisinstance(value,bool):raiseTypeError("value must be of type bool")core.BNBasicBlockSetFallThroughToFunction(self.handle,value)def_make_blocks(self,blocks,count:int)->List['BasicBlock']:assertblocksisnotNone,"core returned empty block list"try:result:List['BasicBlock']=[]foriinrange(0,count):handle=core.BNNewBasicBlockReference(blocks[i])asserthandleisnotNoneresult.append(self._create_instance(handle))returnresultfinally:core.BNFreeBasicBlockList(blocks,count)@propertydefdominators(self)->List['BasicBlock']:"""List of dominators for this basic block (read-only).A dominator of a basic block B is a block that must be executed before B can be executed.In other words, every path from the entry block to B must go through the dominator.This includes B itself - every block dominates itself. See:py:func:`BasicBlock.strict_dominators` for dominators that don't include B."""count=ctypes.c_ulonglong()blocks=core.BNGetBasicBlockDominators(self.handle,count,False)returnself._make_blocks(blocks,count.value)@propertydefpost_dominators(self)->List['BasicBlock']:"""List of post-dominators for this basic block (read-only)A post-dominator of a basic block B is a block that must be executed after B is executed.In other words, every path from B to an exit block must go through the post-dominator.This includes B itself - every block post-dominates itself. See:py:func:`BasicBlock.strict_post_dominators` for post-dominators that don't include B.If B has outgoing edges that can lead to different exit blocks, then this will only include B."""count=ctypes.c_ulonglong()blocks=core.BNGetBasicBlockDominators(self.handle,count,True)returnself._make_blocks(blocks,count.value)@propertydefstrict_dominators(self)->List['BasicBlock']:"""List of strict dominators for this basic block (read-only)A strict dominator of a basic block B is a dominator of B that is not B itself.See :py:func:`BasicBlock.dominators` for the definition of a dominator."""count=ctypes.c_ulonglong()blocks=core.BNGetBasicBlockStrictDominators(self.handle,count,False)returnself._make_blocks(blocks,count.value)@propertydefstrict_post_dominators(self)->List['BasicBlock']:"""List of strict post-dominators for this basic block (read-only)A strict post-dominator of a basic block B is a post-dominator of B that is not B itself.See :py:func:`BasicBlock.post_dominators` for the definition of a post-dominator."""count=ctypes.c_ulonglong()blocks=core.BNGetBasicBlockStrictDominators(self.handle,count,True)returnself._make_blocks(blocks,count.value)@propertydefimmediate_dominator(self)->Optional['BasicBlock']:"""Immediate dominator of this basic block (read-only)The immediate dominator of a basic block B is the dominator closest to B in the control flow graph.In other words, among all dominators of B, it is the dominator that doesn't dominate any otherdominator of B except itself. Each basic block except the entry block has a unique immediate dominator."""result=core.BNGetBasicBlockImmediateDominator(self.handle,False)ifnotresult:returnNonereturnself._create_instance(result)@propertydefimmediate_post_dominator(self)->Optional['BasicBlock']:"""Immediate post-dominator of this basic block (read-only)The immediate post-dominator of a basic block B is the post-dominator closest to B in the control flow graph.In other words, among all post-dominators of B, it is the post-dominator that doesn't post-dominate any otherpost-dominator of B except itself.If B has outgoing edges that can lead to different exit blocks, then this will not exist."""result=core.BNGetBasicBlockImmediateDominator(self.handle,True)ifnotresult:returnNonereturnself._create_instance(result)@propertydefdominator_tree_children(self)->List['BasicBlock']:"""List of child blocks in the dominator tree for this basic block (read-only)The dominator tree children of a basic block B are the blocks dominated by B.See :py:func:`BasicBlock.dominators` for the definition of a dominator."""count=ctypes.c_ulonglong()blocks=core.BNGetBasicBlockDominatorTreeChildren(self.handle,count,False)returnself._make_blocks(blocks,count.value)@propertydefpost_dominator_tree_children(self)->List['BasicBlock']:"""List of child blocks in the post-dominator tree for this basic block (read-only)The post-dominator tree children of a basic block B are the blocks post-dominated by B.See :py:func:`BasicBlock.post_dominators` for the definition of a post-dominator."""count=ctypes.c_ulonglong()blocks=core.BNGetBasicBlockDominatorTreeChildren(self.handle,count,True)returnself._make_blocks(blocks,count.value)@propertydefdominance_frontier(self)->List['BasicBlock']:"""Dominance frontier for this basic block (read-only)The dominance frontier of a basic block B is the set of blocks that are not strictly dominated by B,but are immediately control-dependent on B. In other words, it contains the blocks where B's dominance"stops" - the blocks that have at least one predecessor not dominated by B, while having anotherpredecessor that is dominated by B."""count=ctypes.c_ulonglong()blocks=core.BNGetBasicBlockDominanceFrontier(self.handle,count,False)returnself._make_blocks(blocks,count.value)@propertydefpost_dominance_frontier(self)->List['BasicBlock']:"""Post-dominance frontier for this basic block (read-only)The post-dominance frontier of a basic block B is the set of blocks that are not strictly post-dominatedby B, but have at least one successor that is post-dominated by B. In other words, it contains the blockswhere B's post-dominance "stops" - the blocks that have at least one successor not post-dominated by B,while having another successor that is post-dominated by B."""count=ctypes.c_ulonglong()blocks=core.BNGetBasicBlockDominanceFrontier(self.handle,count,True)returnself._make_blocks(blocks,count.value)@propertydefannotations(self)->List[List['_function.InstructionTextToken']]:"""List of automatic annotations for the start of this block (read-only)"""ifself.functionisNone:raiseValueError("Attempting to call BasicBlock.annotations when Function is None")returnself.function.get_block_annotations(self.start,self.arch)@propertydefdisassembly_text(self)->List['_function.DisassemblyTextLine']:"""``disassembly_text`` property which returns a list of function.DisassemblyTextLine objects for the current basic block.:Example:>>> current_basic_block.disassembly_text[<0x100000f30: _main:>, ...]"""returnself.get_disassembly_text()@propertydefhighlight(self)->'_highlight.HighlightColor':"""Gets or sets the highlight color for basic block:Example:>>> current_basic_block.highlight = HighlightStandardColor.BlueHighlightColor>>> current_basic_block.highlight<color: blue>"""return_highlight.HighlightColor._from_core_struct(core.BNGetBasicBlockHighlight(self.handle))@highlight.setterdefhighlight(self,value:'_highlight.HighlightColor')->None:self.set_user_highlight(value)@propertydeffunction_graph_type(self)->'_function.FunctionGraphType':"""Type of function graph from which this block represents instructions"""return_function.FunctionGraphType(core.BNGetBasicBlockFunctionGraphType(self.handle))@propertydefis_il(self)->bool:"""Whether the basic block contains IL"""returncore.BNIsILBasicBlock(self.handle)@propertydefis_low_level_il(self)->bool:"""Whether the basic block contains Low Level IL"""returncore.BNIsLowLevelILBasicBlock(self.handle)@propertydefis_medium_level_il(self)->bool:"""Whether the basic block contains Medium Level IL"""returncore.BNIsMediumLevelILBasicBlock(self.handle)@propertydefis_high_level_il(self)->bool:"""Whether the basic block contains High Level IL"""returncore.BNIsHighLevelILBasicBlock(self.handle)
[docs]defget_iterated_dominance_frontier(self,blocks:List['BasicBlock'])->List['BasicBlock']:"""Calculates the iterated dominance frontier of the given blocks (this is used to determine φ node placement)"""iflen(blocks)==0:return[]block_set=(ctypes.POINTER(core.BNBasicBlock)*len(blocks))()# type: ignoreforiinrange(len(blocks)):block_set[i]=blocks[i].handlecount=ctypes.c_ulonglong()out_blocks=core.BNGetBasicBlockIteratedDominanceFrontier(block_set,len(blocks),count)returnself._make_blocks(out_blocks,count.value)
[docs]defmark_recent_use(self)->None:core.BNMarkBasicBlockAsRecentlyUsed(self.handle)
[docs]defget_disassembly_text(self,settings:Optional['_function.DisassemblySettings']=None)->List['_function.DisassemblyTextLine']:"""``get_disassembly_text`` returns a list of DisassemblyTextLine objects for the current basic block.:param DisassemblySettings settings: (optional) DisassemblySettings object:Example:>>> current_basic_block.get_disassembly_text()[<0x100000f30: _main:>, <0x100000f30: push rbp>, ... ]"""settings_obj=Noneifsettings:settings_obj=settings.handlecount=ctypes.c_ulonglong()lines=core.BNGetBasicBlockDisassemblyText(self.handle,settings_obj,count)assertlinesisnotNone,"core.BNGetBasicBlockDisassemblyText returned None"result=[]try:foriinrange(0,count.value):addr=lines[i].addrif(lines[i].instrIndex!=0xffffffffffffffff)andhasattr(self,'il_function'):il_instr=self.il_function[lines[i].instrIndex]# type: ignoreelse:il_instr=Nonecolor=_highlight.HighlightColor._from_core_struct(lines[i].highlight)tokens=_function.InstructionTextToken._from_core_struct(lines[i].tokens,lines[i].count)result.append(_function.DisassemblyTextLine(tokens,addr,il_instr,color))returnresultfinally:core.BNFreeDisassemblyTextLines(lines,count.value)
[docs]defset_auto_highlight(self,color:'_highlight.HighlightColor')->None:"""``set_auto_highlight`` highlights the current BasicBlock with the supplied color... warning:: Use only in analysis plugins. Do not use in regular plugins, as colors won't be saved to the database.:param HighlightStandardColor or HighlightColor color: Color value to use for highlighting"""ifnotisinstance(color,HighlightStandardColor)andnotisinstance(color,_highlight.HighlightColor):raiseValueError("Specified color is not one of HighlightStandardColor, HighlightColor")ifisinstance(color,HighlightStandardColor):color=_highlight.HighlightColor(color)core.BNSetAutoBasicBlockHighlight(self.handle,color._to_core_struct())
[docs]defset_user_highlight(self,color:'_highlight.HighlightColor')->None:"""``set_user_highlight`` highlights the current BasicBlock with the supplied color:param HighlightStandardColor or HighlightColor color: Color value to use for highlighting:Example:>>> current_basic_block.set_user_highlight(_highlight.HighlightColor(red=0xff, blue=0xff, green=0))>>> current_basic_block.set_user_highlight(HighlightStandardColor.BlueHighlightColor)"""ifnotisinstance(color,HighlightStandardColor)andnotisinstance(color,_highlight.HighlightColor):raiseValueError("Specified color is not one of HighlightStandardColor, HighlightColor")ifisinstance(color,HighlightStandardColor):color=_highlight.HighlightColor(color)core.BNSetUserBasicBlockHighlight(self.handle,color._to_core_struct())
[docs]defget_instruction_containing_address(self,addr:int)->Tuple[bool,int]:start=ctypes.c_uint64()ret:bool=core.BNGetBasicBlockInstructionContainingAddress(self.handle,addr,start)returnret,start.value