Toggle Light / Dark / Auto color theme
Toggle table of contents sidebar
Source code for angr.analyses.decompiler.structured_codegen.base
from typing import Dict , Optional , Set , Union
from sortedcontainers import SortedDict
from ....sim_variable import SimVariable
#
# Position Mapping Classes
#
[docs] class PositionMappingElement :
__slots__ = ( "start" , "length" , "obj" )
[docs] def __init__ ( self , start , length , obj ):
self . start : int = start
self . length : int = length
self . obj = obj
def __contains__ ( self , offset ):
return self . start <= offset < self . start + self . length
def __repr__ ( self ):
return "< %d - %d : %s >" % ( self . start , self . start + self . length , self . obj )
[docs] class PositionMapping :
__slots__ = ( "_posmap" ,)
DUPLICATION_CHECK = True
[docs] def __init__ ( self ):
self . _posmap : Union [ SortedDict , Dict [ int , PositionMappingElement ]] = SortedDict ()
[docs] def items ( self ):
return self . _posmap . items ()
#
# Public methods
#
[docs] def add_mapping ( self , start_pos , length , obj ):
# duplication check
if self . DUPLICATION_CHECK :
try :
pre = next ( self . _posmap . irange ( maximum = start_pos , reverse = True ))
if start_pos in self . _posmap [ pre ]:
raise ValueError ( "New mapping is overlapping with an existing element." )
except StopIteration :
pass
self . _posmap [ start_pos ] = PositionMappingElement ( start_pos , length , obj )
[docs] def get_node ( self , pos : int ):
element = self . get_element ( pos )
if element is None :
return None
return element . obj
[docs] def get_element ( self , pos : int ) -> Optional [ PositionMappingElement ]:
try :
pre = next ( self . _posmap . irange ( maximum = pos , reverse = True ))
except StopIteration :
return None
element = self . _posmap [ pre ]
if pos in element :
return element
return None
[docs] class InstructionMappingElement :
__slots__ = ( "ins_addr" , "posmap_pos" )
[docs] def __init__ ( self , ins_addr , posmap_pos ):
self . ins_addr : int = ins_addr
self . posmap_pos : int = posmap_pos
def __contains__ ( self , offset : int ):
return self . ins_addr == offset
def __repr__ ( self ):
return "< %d : %d >" % ( self . ins_addr , self . posmap_pos )
[docs] class InstructionMapping :
__slots__ = ( "_insmap" ,)
[docs] def __init__ ( self ):
self . _insmap : Union [ SortedDict , Dict [ int , InstructionMappingElement ]] = SortedDict ()
[docs] def items ( self ):
return self . _insmap . items ()
[docs] def add_mapping ( self , ins_addr , posmap_pos ):
if ins_addr in self . _insmap :
if posmap_pos <= self . _insmap [ ins_addr ] . posmap_pos :
self . _insmap [ ins_addr ] = InstructionMappingElement ( ins_addr , posmap_pos )
else :
self . _insmap [ ins_addr ] = InstructionMappingElement ( ins_addr , posmap_pos )
[docs] def get_nearest_pos ( self , ins_addr : int ) -> Optional [ int ]:
try :
pre_max = next ( self . _insmap . irange ( maximum = ins_addr , reverse = True ))
pre_min = next ( self . _insmap . irange ( minimum = ins_addr , reverse = True ))
except StopIteration :
return None
e1 : InstructionMappingElement = self . _insmap [ pre_max ]
e2 : InstructionMappingElement = self . _insmap [ pre_min ]
if abs ( ins_addr - e1 . ins_addr ) <= abs ( ins_addr - e2 . ins_addr ):
return e1 . posmap_pos
else :
return e2 . posmap_pos
[docs] class BaseStructuredCodeGenerator :
[docs] def __init__ ( self , flavor = None ):
self . flavor = flavor
self . text = None
self . map_pos_to_node = None
self . map_pos_to_addr = None
self . map_addr_to_pos = None
self . map_ast_to_pos : Optional [ Dict [ SimVariable , Set [ PositionMappingElement ]]] = None
[docs] def reapply_options ( self , options ):
pass
[docs] def regenerate_text ( self ) -> None :
pass
[docs] def reload_variable_types ( self ) -> None :
pass