def _scan_iterator(self,
                       scanner: 'ScannerInterface',
                       sections: Iterable[Tuple[int, int]],
                       linear: bool = False) -> Iterable[IteratorValue]:
        """Iterator that indicates which blocks in the layer are to be read by
        for the scanning.

        Returns a list of blocks (potentially in lower layers) that make
        up this chunk contiguously. Chunks can be no bigger than
        scanner.chunk_size + scanner.overlap DataLayers by default are
        assumed to have no holes
        """
        for (section_start, section_length) in sections:
            # For each section, split it into scan size chunks
            for chunk_start in range(section_start, section_start + section_length, scanner.chunk_size):
                # Shorten it, if we're at the end of the section
                chunk_length = min(section_start + section_length - chunk_start, scanner.chunk_size + scanner.overlap)

                # Prev offset keeps track of the end of the previous subchunk
                prev_offset = chunk_start
                output = []  # type: List[Tuple[str, int, int]]

                # We populate the response based on subchunks that may be mapped all over the place
                for mapped in self.mapping(chunk_start, chunk_length, ignore_errors = True):
                    # We don't bother with the other data in case the data's been processed by a lower layer
                    offset, sublength, mapped_offset, mapped_length, layer_name = mapped

                    # We need to check if the offset is next to the end of the last one (contiguous)
                    if offset != prev_offset:
                        # Only yield if we've accumulated output
                        if len(output):
                            # Yield all the (joined) items so far
                            # and the ending point of that subchunk (where we'd gotten to previously)
                            yield output, prev_offset
                        output = []

                    # Shift the marker up to the end of what we just received and add it to the output
                    prev_offset = offset + sublength

                    if not linear:
                        output += [(self.name, offset, sublength)]
                    else:
                        output += [(layer_name, mapped_offset, mapped_length)]
                # If there's still output left, output it
                if len(output):
                    yield output, prev_offset


Reads from a particular layer at offset for length bytes .

def read(self, layer: str, offset: int, length: int, pad: bool = False) -> bytes:
        """Reads from a particular layer at offset for length bytes.

        Returns 'bytes' not 'str'

        Args:
            layer: The name of the layer to read from
            offset: Where to begin reading within the layer
            length: How many bytes to read from the layer
            pad: Whether to raise exceptions or return null bytes when errors occur

        Returns:
            The result of reading from the requested layer
        """
        return self[layer].read(offset, length, pad)

def read ( self , layer : str , offset : int , length : int , pad : bool = False ) -> bytes : return self [ layer ] . read ( offset , length , pad )


Writes to a particular layer at offset for length bytes .

def write(self, layer: str, offset: int, data: bytes) -> None:
        """Writes to a particular layer at offset for length bytes."""
        self[layer].write(offset, data)

def write ( self , layer : str , offset : int , data : bytes ) -> None : self [ layer ] . write ( offset , data )


def add_layer(self, layer: DataLayerInterface) -> None:
        """Adds a layer to memory model.

        This will throw an exception if the required dependencies are not met

        Args:
            layer: the layer to add to the list of layers (based on layer.name)
        """
        if layer.name in self._layers:
            raise exceptions.LayerException(layer.name, "Layer already exists: {}".format(layer.name))
        if isinstance(layer, TranslationLayerInterface):
            missing_list = [sublayer for sublayer in layer.dependencies if sublayer not in self._layers]
            if missing_list:
                raise exceptions.LayerException(
                    layer.name, "Layer {} has unmet dependencies: {}".format(layer.name, ", ".join(missing_list)))
        self._layers[layer.name] = layer

def
add_layer
(
self
,
layer
:
DataLayerInterface
)
->
:
if
layer
.
name
in
self
.
_layers
:
raise
exceptions
.
LayerException
(
layer
.
name
,
"Layer already exists: {}"
.
format
(
layer
.
name
)
)
if
isinstance
(
layer
,
TranslationLayerInterface
)
:
missing_list
=
[
sublayer
for
sublayer
in
layer
.
dependencies
if
sublayer
not
in
self
.
_layers
]
if
missing_list
:
raise
exceptions
.
LayerException
(
layer
.
name
,
"Layer {} has unmet dependencies: {}"
.
format
(
layer
.
name
,
", "
.
join
(
missing_list
)
)
)
self
.
_layers
[
layer
.
name
]
=
layer


def del_layer(self, name: str) -> None:
        """Removes the layer called name.

        This will throw an exception if other layers depend upon this layer

        Args:
            name: The name of the layer to delete
        """
        for layer in self._layers:
            depend_list = [superlayer for superlayer in self._layers if name in self._layers[layer].dependencies]
            if depend_list:
                raise exceptions.LayerException(
                    self._layers[layer].name,
                    "Layer {} is depended upon: {}".format(self._layers[layer].name, ", ".join(depend_list)))
        self._layers[name].destroy()
        del self._layers[name]

def
del_layer
(
self
,
name
:
str
)
->
:
for
layer
in
self
.
_layers
:
depend_list
=
[
superlayer
for
superlayer
in
self
.
_layers
if
name
in
self
.
_layers
[
layer
]
.
dependencies
]
if
depend_list
:
raise
exceptions
.
LayerException
(
self
.
_layers
[
layer
]
.
name
,
"Layer {} is depended upon: {}"
.
format
(
self
.
_layers
[
layer
]
.
name
,
", "
.
join
(
depend_list
)
)
)
self
.
_layers
[
name
]
.
destroy
(
)
del
self
.
_layers
[
name
]


Returns an unused layer name to ensure no collision occurs when inserting a layer .

def free_layer_name(self, prefix: str = "layer") -> str:
        """Returns an unused layer name to ensure no collision occurs when
        inserting a layer.

        Args:
            prefix: A descriptive string with which to prefix the layer name

        Returns:
            A string containing a name, prefixed with prefix, not currently in use within the LayerContainer
        """
        if prefix not in self:
            return prefix
        count = 1
        while "{}_{}".format(prefix, count) in self:
            count += 1
        return "{}_{}".format(prefix, count)

def free_layer_name ( self , prefix : str = "layer" ) -> str : if prefix not in self : return prefix count = 1 while "{}_{}" . format ( prefix , count ) in self : count += 1 return "{}_{}" . format ( prefix , count )


def __getitem__(self, name: str) -> DataLayerInterface:
        """Returns the layer of specified name."""
        return self._layers[name]

def __getitem__ ( self , name : str ) -> DataLayerInterface : return self . _layers [ name ]


Runs through the available layers and identifies if there are cycles in the DAG .

def check_cycles(self) -> None:
        """Runs through the available layers and identifies if there are cycles
        in the DAG."""
        # TODO: Is having a cycle check necessary?
        raise NotImplementedError("Cycle checking has not yet been implemented")


Accepts an options object to configure the renderers .

def __init__(self, options: Optional[List[RenderOption]] = None) -> None:
        """Accepts an options object to configure the renderers."""

def __init__ ( self , options : Optional [ List [ RenderOption ] ] = None ) -> None :


def get_render_options(self) -> List[RenderOption]:
        """Returns a list of rendering options."""

def get_render_options ( self ) -> List [ RenderOption ] :


Takes a grid object and renders it based on the object s preferences .

def render(self, grid: 'TreeGrid') -> None:
        """Takes a grid object and renders it based on the object's
        preferences."""

def render ( self , grid : 'TreeGrid' ) -> None :


The key function passed as a sort key to the TreeGrid s visit function .

def __call__(self, values: List[Any]) -> Any:
        """The key function passed as a sort key to the TreeGrid's visit
        function."""

def __call__ ( self , values : List [ Any ] ) -> Any :


def __init__(self, path, treegrid, parent, values):
        """Initializes the TreeNode."""

def __init__ ( self , path , treegrid , parent , values ) :


Returns the list of values from the particular node based on column index .

def values(self) -> List['BaseTypes']:
        """Returns the list of values from the particular node, based on column
        index."""

def values ( self ) -> List [ 'BaseTypes' ] :


def path(self) -> str:
        """Returns a path identifying string.

        This should be seen as opaque by external classes, Parsing of
        path locations based on this string are not guaranteed to remain
        stable.
        """


Returns the parent node of this node or None .

def parent(self) -> Optional['TreeNode']:
        """Returns the parent node of this node or None."""

def parent ( self ) -> Optional [ 'TreeNode' ] :


Return the path depth of the current node .

def path_depth(self) -> int:
        """Return the path depth of the current node."""


Updates the path based on the addition or removal of a node higher up in the tree .

def path_changed(self, path: str, added: bool = False) -> None:
        """Updates the path based on the addition or removal of a node higher
        up in the tree.

        This should only be called by the containing TreeGrid and
        expects to only be called for affected nodes.
        """

def path_changed ( self , path : str , added : bool = False ) -> None :


Constructs a TreeGrid object using a specific set of columns .

def __init__(self, columns: ColumnsType, generator: Generator) -> None:
        """Constructs a TreeGrid object using a specific set of columns.

        The TreeGrid itself is a root element, that can have children but no values.
        The TreeGrid does *not* contain any information about formatting,
        these are up to the renderers and plugins.

        Args:
            columns: A list of column tuples made up of (name, type).
            generator: An iterable containing row for a tree grid, each row contains a indent level followed by the values for each column in order.
        """

def __init__ ( self , columns : ColumnsType , generator : Generator ) -> None :


Method used to sanitize column names for TreeNodes .

def sanitize_name(text: str) -> str:
        """Method used to sanitize column names for TreeNodes."""

def sanitize_name ( text : str ) -> str :


Populates the tree by consuming the TreeGrid s construction generator Func is called on every node so can be used to create output on demand .

def populate(self,
                 function: VisitorSignature = None,
                 initial_accumulator: Any = None,
                 fail_on_errors: bool = True) -> Optional[Exception]:
        """Populates the tree by consuming the TreeGrid's construction
        generator Func is called on every node, so can be used to create output
        on demand.

        This is equivalent to a one-time visit.
        """

def populate ( self , function : VisitorSignature = None , initial_accumulator : Any = None , fail_on_errors : bool = True ) -> Optional [ Exception ] :


Indicates that population has completed and the tree may now be manipulated separately .

def populated(self) -> bool:
        """Indicates that population has completed and the tree may now be
        manipulated separately."""


Returns the available columns and their ordering and types .

def columns(self) -> List[Column]:
        """Returns the available columns and their ordering and types."""

def columns ( self ) -> List [ Column ] :


Returns the subnodes of a particular node in order .

def children(self, node: TreeNode) -> List[TreeNode]:
        """Returns the subnodes of a particular node in order."""

def children ( self , node : TreeNode ) -> List [ TreeNode ] :


Returns the values for a particular node .

def values(self, node: TreeNode) -> Tuple[BaseTypes, ...]:
        """Returns the values for a particular node.

        The values returned are mutable,
        """

def values ( self , node : TreeNode ) -> Tuple [ BaseTypes , ... ] :


Returns true if descendent is a child grandchild etc of node .

def is_ancestor(self, node: TreeNode, descendant: TreeNode) -> bool:
        """Returns true if descendent is a child, grandchild, etc of node."""

def is_ancestor ( self , node : TreeNode , descendant : TreeNode ) -> bool :


def max_depth(self) -> int:
        """Returns the maximum depth of the tree."""


Returns the path depth of a particular node .

def path_depth(node: TreeNode) -> int:
        """Returns the path depth of a particular node."""
        return node.path_depth

def path_depth ( node : TreeNode ) -> int : return node . path_depth


Visits all the nodes in a tree calling function on each one .

def visit(self,
              node: Optional[TreeNode],
              function: VisitorSignature,
              initial_accumulator: _Type,
              sort_key: ColumnSortKey = None) -> None:
        """Visits all the nodes in a tree, calling function on each one.

        function should have the signature function(node, accumulator) and return new_accumulator
        If accumulators are not needed, the function must still accept a second parameter.

        The order of that the nodes are visited is always depth first, however, the order children are traversed can
        be set based on a sort_key function which should accept a node's values and return something that can be
        sorted to receive the desired order (similar to the sort/sorted key).

        If node is None, then the root node is used.

        Args:
            node: The initial node to be visited
            function: The visitor to apply to the nodes under the initial node
            initial_accumulator: An accumulator that allows data to be transfered between one visitor call to the next
            sort_key: Information about the sort order of columns in order to determine the ordering of results
        """

def visit ( self , node : Optional [ TreeNode ] , function : VisitorSignature , initial_accumulator : _Type , sort_key : ColumnSortKey = None ) -> None :


Initializes the context with a symbol_space .

def __init__(self) -> None:
        """Initializes the context with a symbol_space."""


Returns the configuration object for this context .

def config(self) -> 'interfaces.configuration.HierarchicalDict':
        """Returns the configuration object for this context."""


Returns the symbol_space for the context .

def symbol_space(self) -> 'interfaces.symbols.SymbolSpaceInterface':
        """Returns the symbol_space for the context.

        This object must support the :class:`~volatility.framework.interfaces.symbols.SymbolSpaceInterface`
        """


Returns the memory object for the context .

def layers(self) -> 'interfaces.layers.LayerContainer':
        """Returns the memory object for the context."""
        raise NotImplementedError("LayerContainer has not been implemented.")


Adds a named translation layer to the context memory .

def add_layer(self, layer: 'interfaces.layers.DataLayerInterface'):
        """Adds a named translation layer to the context memory.

        Args:
            layer: Layer object to be added to the context memory
        """
        self.layers.add_layer(layer)

def add_layer ( self , layer : 'interfaces.layers.DataLayerInterface' ) : self . layers . add_layer ( layer )


Object factory takes a context symbol offset and optional layer_name .

def object(self,
               object_type: Union[str, 'interfaces.objects.Template'],
               layer_name: str,
               offset: int,
               native_layer_name: str = None,
               **arguments):
        """Object factory, takes a context, symbol, offset and optional
        layer_name.

        Looks up the layer_name in the context, finds the object template based on the symbol,
        and constructs an object using the object template on the layer at the offset.

        Args:
            object_type: Either a string name of the type, or a Template of the type to be constructed
            layer_name: The name of the layer on which to construct the object
            offset: The address within the layer at which to construct the object
            native_layer_name: The layer this object references (should it be a pointer or similar)

        Returns:
             A fully constructed object
        """

def object ( self , object_type : Union [ str , 'interfaces.objects.Template' ] , layer_name : str , offset : int , native_layer_name : str = None , * * arguments ) :


Produce a clone of the context ( and configuration ) allowing modifications to be made without affecting any mutable objects in the original .

def clone(self) -> 'ContextInterface':
        """Produce a clone of the context (and configuration), allowing
        modifications to be made without affecting any mutable objects in the
        original.

        Memory constraints may become an issue for this function
        depending on how much is actually stored in the context
        """
        return copy.deepcopy(self)

def clone ( self ) -> 'ContextInterface' : return copy . deepcopy ( self )


def module(self,
               module_name: str,
               layer_name: str,
               offset: int,
               native_layer_name: Optional[str] = None,
               size: Optional[int] = None) -> 'ModuleInterface':
        """Create a module object.

        A module object is associated with a symbol table, and acts like a context, but offsets locations by a known value
        and looks up symbols, by default within the associated symbol table.  It can also be sized should that information
        be available.

        Args:
            module_name: The name of the module
            layer_name: The layer the module is associated with (which layer the module lives within)
            offset: The initial/base offset of the module (used as the offset for relative symbols)
            native_layer_name: The default native_layer_name to use when the module constructs objects
            size: The size, in bytes, that the module occupys from offset location within the layer named layer_name

        Returns:
            A module object
        """

def module ( self , module_name : str , layer_name : str , offset : int , native_layer_name : Optional [ str ] = None , size : Optional [ int ] = None ) -> 'ModuleInterface' :


Constructs a new os - independent module .

def __init__(self,
                 context: ContextInterface,
                 module_name: str,
                 layer_name: str,
                 offset: int,
                 symbol_table_name: Optional[str] = None,
                 native_layer_name: Optional[str] = None) -> None:
        """Constructs a new os-independent module.

        Args:
            context: The context within which this module will exist
            module_name: The name of the module
            layer_name: The layer within the context in which the module exists
            offset: The offset at which the module exists in the layer
            symbol_table_name: The name of an associated symbol table
            native_layer_name: The default native layer for objects constructed by the module
        """
        self._context = context
        self._module_name = module_name
        self._layer_name = layer_name
        self._offset = offset
        self._native_layer_name = None
        if native_layer_name:
            self._native_layer_name = native_layer_name
        self.symbol_table_name = symbol_table_name or self._module_name
        super().__init__()

def __init__ ( self , context : ContextInterface , module_name : str , layer_name : str , offset : int , symbol_table_name : Optional [ str ] = None , native_layer_name : Optional [ str ] = None ) -> None : self . _context = context self . _module_name = module_name self . _layer_name = layer_name self . _offset = offset self . _native_layer_name = None if native_layer_name : self . _native_layer_name = native_layer_name self . symbol_table_name = symbol_table_name or self . _module_name super ( ) . __init__ ( )


def name(self) -> str:
        """The name of the constructed module."""
        return self._module_name

def name ( self ) -> str : return self . _module_name


Returns the offset that the module resides within the layer of layer_name .

def offset(self) -> int:
        """Returns the offset that the module resides within the layer of
        layer_name."""
        return self._offset

def offset ( self ) -> int : return self . _offset


Layer name in which the Module resides .

def layer_name(self) -> str:
        """Layer name in which the Module resides."""
        return self._layer_name

def layer_name ( self ) -> str : return self . _layer_name


def context(self) -> ContextInterface:
        """Context that the module uses."""
        return self._context

def context ( self ) -> ContextInterface : return self . _context


Returns an object created using the symbol_table_name and layer_name of the Module .

def object(self,
               object_type: str,
               offset: int = None,
               native_layer_name: Optional[str] = None,
               absolute: bool = False,
               **kwargs) -> 'interfaces.objects.ObjectInterface':
        """Returns an object created using the symbol_table_name and layer_name
        of the Module.

        Args:
            object_type: The name of object type to construct (using the module's symbol_table)
            offset: the offset (unless absolute is set) from the start of the module
            native_layer_name: The native layer for objects that reference a different layer (if not the default provided during module construction)
            absolute: A boolean specifying whether the offset is absolute within the layer, or relative to the start of the module

        Returns:
            The constructed object
        """

def object ( self , object_type : str , offset : int = None , native_layer_name : Optional [ str ] = None , absolute : bool = False , * * kwargs ) -> 'interfaces.objects.ObjectInterface' :


def object_from_symbol(self,
                           symbol_name: str,
                           native_layer_name: Optional[str] = None,
                           absolute: bool = False,
                           **kwargs) -> 'interfaces.objects.ObjectInterface':
        """Returns an object created using the symbol_table_name and layer_name
        of the Module.

        Args:
            symbol_name: The name of a symbol (that must be present in the module's symbol table).  The symbol's associated type will be used to construct an object at the symbol's offset.
            native_layer_name: The native layer for objects that reference a different layer (if not the default provided during module construction)
            absolute: A boolean specifying whether the offset is absolute within the layer, or relative to the start of the module

        Returns:
            The constructed object
        """

def object_from_symbol ( self , symbol_name : str , native_layer_name : Optional [ str ] = None , absolute : bool = False , * * kwargs ) -> 'interfaces.objects.ObjectInterface' :


def get_type(self, name: str) -> 'interfaces.objects.Template':
        """Returns a type from the module."""

def get_type ( self , name : str ) -> 'interfaces.objects.Template' :


def get_symbol(self, name: str) -> 'interfaces.symbols.SymbolInterface':
        """Returns a symbol from the module."""

def get_symbol ( self , name : str ) -> 'interfaces.symbols.SymbolInterface' :


Returns an enumeration from the module .

def get_enumeration(self, name: str) -> 'interfaces.objects.Template':
        """Returns an enumeration from the module."""

def get_enumeration ( self , name : str ) -> 'interfaces.objects.Template' :


Determines whether a type is present in the module .

def has_type(self, name: str) -> bool:
        """Determines whether a type is present in the module."""

def has_type ( self , name : str ) -> bool :


Determines whether a symbol is present in the module .

def has_symbol(self, name: str) -> bool:
        """Determines whether a symbol is present in the module."""

def has_symbol ( self , name : str ) -> bool :


Determines whether an enumeration is present in the module .

def has_enumeration(self, name: str) -> bool:
        """Determines whether an enumeration is present in the module."""

def has_enumeration ( self , name : str ) -> bool :


def __init__(self,
                 name: str,
                 address: int,
                 type: Optional[objects.Template] = None,
                 constant_data: Optional[bytes] = None) -> None:
        """

        Args:
            name: Name of the symbol
            address: Numeric address value of the symbol
            type: Optional type structure information associated with the symbol
            constant_data: Potential constant data the symbol points at
        """
        self._name = name
        if constants.BANG in self._name:
            raise ValueError("Symbol names cannot contain the symbol differentiator ({})".format(constants.BANG))

        # Scope can be added at a later date
        self._location = None
        self._address = address
        self._type = type
        self._constant_data = constant_data


def name(self) -> str:
        """Returns the name of the symbol."""
        return self._name

def name ( self ) -> str : return self . _name


Returns the name of the type that the symbol represents .

def type_name(self) -> Optional[str]:
        """Returns the name of the type that the symbol represents."""
        # Objects and ObjectTemplates should *always* get a type_name when they're constructed, so allow the IndexError
        if self.type is None:
            return None
        return self.type.vol['type_name']


Returns the type that the symbol represents .

def type(self) -> Optional[objects.Template]:
        """Returns the type that the symbol represents."""
        return self._type

def type ( self ) -> Optional [ objects . Template ] : return self . _type


Returns the relative address of the symbol within the compilation unit .

def address(self) -> int:
        """Returns the relative address of the symbol within the compilation
        unit."""
        return self._address

def address ( self ) -> int : return self . _address


Returns any constant data associated with the symbol .

def constant_data(self) -> Optional[bytes]:
        """Returns any constant data associated with the symbol."""
        return self._constant_data

def constant_data ( self ) -> Optional [ bytes ] : return self . _constant_data


def __init__(self,
                 name: str,
                 native_types: 'NativeTableInterface',
                 table_mapping: Optional[Dict[str, str]] = None,
                 class_types: Optional[Mapping[str, Type[objects.ObjectInterface]]] = None) -> None:
        """

        Args:
            name: Name of the symbol table
            native_types: The native symbol table used to resolve any base/native types
            table_mapping: A dictionary mapping names of tables (which when present within the table will be changed to the mapped table)
            class_types: A dictionary of types and classes that should be instantiated instead of Struct to construct them
        """
        self.name = name
        if table_mapping is None:
            table_mapping = {}
        self.table_mapping = table_mapping
        self._native_types = native_types
        self._sort_symbols = []  # type: List[Tuple[int, str]]

        # Set any provisioned class_types
        if class_types:
            for class_type in class_types:
                self.set_type_class(class_type, class_types[class_type])

def
__init__
(
self
,
name
:
str
,
native_types
:
'NativeTableInterface'
,
table_mapping
:
Optional
[
Dict
[
str
,
str
]
]
=
,
class_types
:
Optional
[
Mapping
[
str
,
Type
[
objects
.
ObjectInterface
]
]
]
=
)
->
:
self
.
name
=
name
if
table_mapping
is
:
table_mapping
=
{
}
self
.
table_mapping
=
table_mapping
self
.
_native_types
=
native_types
self
.
_sort_symbols
=
[
]
# type: List[Tuple[int, str]]
# Set any provisioned class_types
if
class_types
:
for
class_type
in
class_types
:
self
.
set_type_class
(
class_type
,
class_types
[
class_type
]
)


Resolves a symbol name into a symbol object .

def get_symbol(self, name: str) -> SymbolInterface:
        """Resolves a symbol name into a symbol object.

        If the symbol isn't found, it raises a SymbolError exception
        """
        raise NotImplementedError("Abstract property get_symbol not implemented by subclass.")


Returns an iterator of the Symbol names .

def symbols(self) -> Iterable[str]:
        """Returns an iterator of the Symbol names."""
        raise NotImplementedError("Abstract property symbols not implemented by subclass.")


Returns an iterator of the Symbol type names .

def types(self) -> Iterable[str]:
        """Returns an iterator of the Symbol type names."""
        raise NotImplementedError("Abstract property types not implemented by subclass.")


Resolves a symbol name into an object template .

def get_type(self, name: str) -> objects.Template:
        """Resolves a symbol name into an object template.

        If the symbol isn't found it raises a SymbolError exception
        """
        raise NotImplementedError("Abstract method get_type not implemented by subclass.")


Returns an iterator of the Enumeration names .

def enumerations(self) -> Iterable[Any]:
        """Returns an iterator of the Enumeration names."""
        raise NotImplementedError("Abstract property enumerations not implemented by subclass.")


Returns None or a NativeTable for handling space specific native types .

def natives(self) -> 'NativeTableInterface':
        """Returns None or a NativeTable for handling space specific native
        types."""
        return self._native_types

def natives ( self ) -> 'NativeTableInterface' : return self . _native_types


Checks the natives value and then applies it internally .

def natives(self, value: 'NativeTableInterface') -> None:
        """Checks the natives value and then applies it internally.

        WARNING: This allows changing the underlying size of all the other types referenced in the SymbolTable
        """
        self._native_types = value

def natives ( self , value : 'NativeTableInterface' ) -> None : self . _native_types = value


Overrides the object class for a specific Symbol type .

def set_type_class(self, name: str, clazz: Type[objects.ObjectInterface]) -> None:
        """Overrides the object class for a specific Symbol type.

        Name *must* be present in self.types

        Args:
            name: The name of the type to override the class for
            clazz: The actual class to override for the provided type name
        """
        raise NotImplementedError("Abstract method set_type_class not implemented yet.")


Returns the class associated with a Symbol type .

def get_type_class(self, name: str) -> Type[objects.ObjectInterface]:
        """Returns the class associated with a Symbol type."""
        raise NotImplementedError("Abstract method get_type_class not implemented yet.")


Removes the associated class override for a specific Symbol type .

def del_type_class(self, name: str) -> None:
        """Removes the associated class override for a specific Symbol type."""
        raise NotImplementedError("Abstract method del_type_class not implemented yet.")


Resolves a symbol name into a symbol and then resolves the symbol s type .

def get_symbol_type(self, name: str) -> Optional[objects.Template]:
        """Resolves a symbol name into a symbol and then resolves the symbol's
        type."""
        type_name = self.get_symbol(name).type_name
        if type_name is None:
            return None
        return self.get_type(type_name)

def get_symbol_type ( self , name : str ) -> Optional [ objects . Template ] : type_name = self . get_symbol ( name ) . type_name if type_name is None : return None return self . get_type ( type_name )


Returns the name of all symbols in this table that have type matching type_name .

def get_symbols_by_type(self, type_name: str) -> Iterable[str]:
        """Returns the name of all symbols in this table that have type
        matching type_name."""
        for symbol_name in self.symbols:
            # This allows for searching with and without the table name (in case multiple tables contain
            # the same symbol name and we've not specifically been told which one)
            symbol = self.get_symbol(symbol_name)
            if symbol.type_name is not None and (symbol.type_name == type_name or
                                                 (symbol.type_name.endswith(constants.BANG + type_name))):
                yield symbol.name


Returns the name of all symbols in this table that live at a particular offset .

def get_symbols_by_location(self, offset: int, size: int = 0) -> Iterable[str]:
        """Returns the name of all symbols in this table that live at a
        particular offset."""
        if size < 0:
            raise ValueError("Size must be strictly non-negative")
        if not self._sort_symbols:
            self._sort_symbols = sorted([(self.get_symbol(sn).address, sn) for sn in self.symbols])
        sort_symbols = self._sort_symbols
        result = bisect.bisect_left(sort_symbols, (offset, ""))
        while result < len(sort_symbols) and \
                (sort_symbols[result][0] >= offset and sort_symbols[result][0] <= offset + size):
            yield sort_symbols[result][1]
            result += 1

def
get_symbols_by_location
(
self
,
offset
:
int
,
size
:
int
=
0
)
->
Iterable
[
str
]
:
if
size
<
0
:
raise
ValueError
(
"Size must be strictly non-negative"
)
if
not
self
.
_sort_symbols
:
self
.
_sort_symbols
=
sorted
(
[
(
self
.
get_symbol
(
sn
)
.
address
,
sn
)
for
sn
in
self
.
symbols
]
)
sort_symbols
=
self
.
_sort_symbols
result
=
bisect
.
bisect_left
(
sort_symbols
,
(
offset
,
""
)
)
while
result
<
len
(
sort_symbols
)
and
(
sort_symbols
[
result
]
[
0
]
>=
offset
and
sort_symbols
[
result
]
[
0
]
<=
offset
+
size
)
:
yield
sort_symbols
[
result
]
[
1
]
result
+=
1


Clears the symbol cache of this symbol table .

def clear_symbol_cache(self) -> None:
        """Clears the symbol cache of this symbol table."""
        pass

def clear_symbol_cache ( self ) -> None : pass


Returns an unused table name to ensure no collision occurs when inserting a symbol table .

def free_table_name(self, prefix: str = "layer") -> str:
        """Returns an unused table name to ensure no collision occurs when
        inserting a symbol table."""

def free_table_name ( self , prefix : str = "layer" ) -> str :


Clears the symbol cache for the specified table name . If no table name is specified the caches of all symbol tables are cleared .

def clear_symbol_cache(self, table_name: str) -> None:
        """Clears the symbol cache for the specified table name. If no table
        name is specified, the caches of all symbol tables are cleared."""

def clear_symbol_cache ( self , table_name : str ) -> None :


Returns all symbols based on the type of the symbol .

def get_symbols_by_type(self, type_name: str) -> Iterable[str]:
        """Returns all symbols based on the type of the symbol."""

def get_symbols_by_type ( self , type_name : str ) -> Iterable [ str ] :


Returns all symbols that exist at a specific relative address .

def get_symbols_by_location(self, offset: int, size: int = 0, table_name: Optional[str] = None) -> Iterable[str]:
        """Returns all symbols that exist at a specific relative address."""

def get_symbols_by_location ( self , offset : int , size : int = 0 , table_name : Optional [ str ] = None ) -> Iterable [ str ] :


Look - up a type name across all the contained symbol tables .

def get_type(self, type_name: str) -> objects.Template:
        """Look-up a type name across all the contained symbol tables."""

def get_type ( self , type_name : str ) -> objects . Template :


Look - up a symbol name across all the contained symbol tables .

def get_symbol(self, symbol_name: str) -> SymbolInterface:
        """Look-up a symbol name across all the contained symbol tables."""

def get_symbol ( self , symbol_name : str ) -> SymbolInterface :


Look - up an enumeration across all the contained symbol tables .

def get_enumeration(self, enum_name: str) -> objects.Template:
        """Look-up an enumeration across all the contained symbol tables."""

def get_enumeration ( self , enum_name : str ) -> objects . Template :


Determines whether a type exists in the contained symbol tables .

def has_type(self, name: str) -> bool:
        """Determines whether a type exists in the contained symbol tables."""

def has_type ( self , name : str ) -> bool :


Determines whether a symbol exists in the contained symbol tables .

def has_symbol(self, name: str) -> bool:
        """Determines whether a symbol exists in the contained symbol
        tables."""

def has_symbol ( self , name : str ) -> bool :


Determines whether an enumeration choice exists in the contained symbol tables .

def has_enumeration(self, name: str) -> bool:
        """Determines whether an enumeration choice exists in the contained
        symbol tables."""

def has_enumeration ( self , name : str ) -> bool :


Adds a symbol_list to the end of the space .

def append(self, value: BaseSymbolTableInterface) -> None:
        """Adds a symbol_list to the end of the space."""

def append ( self , value : BaseSymbolTableInterface ) -> None :


Instantiates an SymbolTable based on an IntermediateSymbolFormat JSON file . This is validated against the appropriate schema .

def __init__(self,
                 context: 'interfaces.context.ContextInterface',
                 config_path: str,
                 name: str,
                 native_types: 'NativeTableInterface',
                 table_mapping: Optional[Dict[str, str]] = None,
                 class_types: Optional[Mapping[str, Type[objects.ObjectInterface]]] = None) -> None:
        """Instantiates an SymbolTable based on an IntermediateSymbolFormat JSON file.  This is validated against the
        appropriate schema.

        Args:
            context: The volatility context for the symbol table
            config_path: The configuration path for the symbol table
            name: The name for the symbol table (this is used in symbols e.g. table!symbol )
            isf_url: The URL pointing to the ISF file location
            native_types: The NativeSymbolTable that contains the native types for this symbol table
            table_mapping: A dictionary linking names referenced in the file with symbol tables in the context
            class_types: A dictionary of type names and classes that override StructType when they are instantiated
        """
        configuration.ConfigurableInterface.__init__(self, context, config_path)
        BaseSymbolTableInterface.__init__(self, name, native_types, table_mapping, class_types = class_types)

def __init__ ( self , context : 'interfaces.context.ContextInterface' , config_path : str , name : str , native_types : 'NativeTableInterface' , table_mapping : Optional [ Dict [ str , str ] ] = None , class_types : Optional [ Mapping [ str , Type [ objects . ObjectInterface ] ] ] = None ) -> None : configuration . ConfigurableInterface . __init__ ( self , context , config_path ) BaseSymbolTableInterface . __init__ ( self , name , native_types , table_mapping , class_types = class_types )


def __init__(self, json_data: Dict) -> None:
        """Constructor that accepts json_data."""
        self._json_data = json_data

def __init__ ( self , json_data : Dict ) -> None : self . _json_data = json_data


def __init__(self, filename: str) -> None:
        """Creates a FileHandler

        Args:
            filename: The requested name of the filename for the data
        """
        self._preferred_filename = None
        self.preferred_filename = filename
        super().__init__()

def __init__ ( self , filename : str ) -> None : self . _preferred_filename = None self . preferred_filename = filename super ( ) . __init__ ( )


The preferred filename to save the data to . Until this file has been written this value may not be the final filename the data is written to .

def preferred_filename(self):
        """The preferred filename to save the data to.
        Until this file has been written, this value may not be the final filename the data is written to.
        """
        return self._preferred_filename

def preferred_filename ( self ) : return self . _preferred_filename


def preferred_filename(self, filename):
        """Sets the preferred filename"""
        if self.closed:
            raise IOError("FileHandler name cannot be changed once closed")
        if not isinstance(filename, str):
            raise TypeError("FileHandler preferred filenames must be strings")
        if os.path.sep in filename:
            raise ValueError("FileHandler filenames cannot contain path separators")
        self._preferred_filename = filename


def close(self):
        """Method that commits the file and fixes the final filename for use"""


def __init__(self,
                 context: interfaces.context.ContextInterface,
                 config_path: str,
                 progress_callback: constants.ProgressCallback = None) -> None:
        """

        Args:
            context: The context that the plugin will operate within
            config_path: The path to configuration data within the context configuration data
            progress_callback: A callable that can provide feedback at progress points
        """
        super().__init__(context, config_path)
        self._progress_callback = progress_callback or (lambda f, s: None)
        # Plugins self validate on construction, it makes it more difficult to work with them, but then
        # the validation doesn't need to be repeated over and over again by externals
        if self.unsatisfied(context, config_path):
            vollog.warning("Plugin failed validation")
            raise exceptions.PluginRequirementException("The plugin configuration failed to validate")
        # Populate any optional defaults
        for requirement in self.get_requirements():
            if requirement.name not in self.config:
                self.config[requirement.name] = requirement.default

        self._file_handler = FileHandlerInterface  # type: Type[FileHandlerInterface]

        framework.require_interface_version(*self._required_framework_version)


def open(self):
        """Returns a context manager and thus can be called like open"""
        return self._file_handler

def open ( self ) : return self . _file_handler


Sets the file handler to be used by this plugin .

def set_open_method(self, handler: Type[FileHandlerInterface]) -> None:
        """Sets the file handler to be used by this plugin."""
        if not issubclass(handler, FileHandlerInterface):
            raise ValueError("FileHandler must be a subclass of FileHandlerInterface")
        self._file_handler = handler


Returns a list of Requirement objects for this plugin .

def get_requirements(cls) -> List[interfaces.configuration.RequirementInterface]:
        """Returns a list of Requirement objects for this plugin."""
        return super().get_requirements()

def get_requirements ( cls ) -> List [ interfaces . configuration . RequirementInterface ] : return super ( ) . get_requirements ( )


Executes the functionality of the code .

def run(self) -> interfaces.renderers.TreeGrid:
        """Executes the functionality of the code.

        .. note:: This method expects `self.validate` to have been called to ensure all necessary options have been provided

        Returns:
            A TreeGrid object that can then be passed to a Renderer.
        """

def run ( self ) -> interfaces . renderers . TreeGrid :


Returns a boolean as to whether a particular symbol table within a context is 64 - bit or not .

def symbol_table_is_64bit(context: interfaces.context.ContextInterface, symbol_table_name: str) -> bool:
    """Returns a boolean as to whether a particular symbol table within a
    context is 64-bit or not."""
    return context.symbol_space.get_type(symbol_table_name + constants.BANG + "pointer").size == 8

def symbol_table_is_64bit ( context : interfaces . context . ContextInterface , symbol_table_name : str ) -> bool : return context . symbol_space . get_type ( symbol_table_name + constants . BANG + "pointer" ) . size == 8


Clears the symbol cache for the specified table name . If no table name is specified the caches of all symbol tables are cleared .

def clear_symbol_cache(self, table_name: str = None) -> None:
        """Clears the symbol cache for the specified table name. If no table
        name is specified, the caches of all symbol tables are cleared."""
        table_list = list()  # type: List[interfaces.symbols.BaseSymbolTableInterface]
        if table_name is None:
            table_list = list(self._dict.values())
        else:
            table_list.append(self._dict[table_name])
        for table in table_list:
            table.clear_symbol_cache()


Returns an unused table name to ensure no collision occurs when inserting a symbol table .

def free_table_name(self, prefix: str = "layer") -> str:
        """Returns an unused table name to ensure no collision occurs when
        inserting a symbol table."""
        count = 1
        while prefix + str(count) in self:
            count += 1
        return prefix + str(count)

def free_table_name ( self , prefix : str = "layer" ) -> str : count = 1 while prefix + str ( count ) in self : count += 1 return prefix + str ( count )


Returns all symbols based on the type of the symbol .

def get_symbols_by_type(self, type_name: str) -> Iterable[str]:
        """Returns all symbols based on the type of the symbol."""
        for table in self._dict:
            for symbol_name in self._dict[table].get_symbols_by_type(type_name):
                yield table + constants.BANG + symbol_name

def get_symbols_by_type ( self , type_name : str ) -> Iterable [ str ] : for table in self . _dict : for symbol_name in self . _dict [ table ] . get_symbols_by_type ( type_name ) : yield table + constants . BANG + symbol_name


Returns all symbols that exist at a specific relative address .

def get_symbols_by_location(self, offset: int, size: int = 0, table_name: str = None) -> Iterable[str]:
        """Returns all symbols that exist at a specific relative address."""
        table_list = self._dict.values()  # type: Iterable[interfaces.symbols.BaseSymbolTableInterface]
        if table_name is not None:
            if table_name in self._dict:
                table_list = [self._dict[table_name]]
            else:
                table_list = []
        for table in table_list:
            for symbol_name in table.get_symbols_by_location(offset = offset, size = size):
                yield table.name + constants.BANG + symbol_name


Returns the number of tables within the space .

def __len__(self) -> int:
        """Returns the number of tables within the space."""
        return len(self._dict)

def __len__ ( self ) -> int : return len ( self . _dict )


Returns a specific table from the space .

def __getitem__(self, i: str) -> Any:
        """Returns a specific table from the space."""
        return self._dict[i]

def __getitem__ ( self , i : str ) -> Any : return self . _dict [ i ]


Iterates through all available tables in the symbol space .

def __iter__(self) -> Iterator[str]:
        """Iterates through all available tables in the symbol space."""
        return iter(self._dict)

def __iter__ ( self ) -> Iterator [ str ] : return iter ( self . _dict )


def append(self, value: interfaces.symbols.BaseSymbolTableInterface) -> None:
        """Adds a symbol_list to the end of the space."""
        if not isinstance(value, interfaces.symbols.BaseSymbolTableInterface):
            raise TypeError(value)
        if value.name in self._dict:
            self.remove(value.name)
        self._dict[value.name] = value

def append ( self , value : interfaces . symbols . BaseSymbolTableInterface ) -> None : if not isinstance ( value , interfaces . symbols . BaseSymbolTableInterface ) : raise TypeError ( value ) if value . name in self . _dict : self . remove ( value . name ) self . _dict [ value . name ] = value


Removes a named symbol_list from the space .

def remove(self, key: str) -> None:
        """Removes a named symbol_list from the space."""
        # Reset the resolved list, since we're removing some symbols
        self._resolved = {}
        del self._dict[key]


Takes a symbol name and resolves it with ReferentialTemplates .

def _weak_resolve(self, resolve_type: SymbolType, name: str) -> SymbolSpaceReturnType:
        """Takes a symbol name and resolves it with ReferentialTemplates."""
        if resolve_type == SymbolType.TYPE:
            get_function = 'get_type'
        elif resolve_type == SymbolType.SYMBOL:
            get_function = 'get_symbol'
        elif resolve_type == SymbolType.ENUM:
            get_function = 'get_enumeration'
        else:
            raise TypeError("Weak_resolve called without a proper SymbolType")

        name_array = name.split(constants.BANG)
        if len(name_array) == 2:
            table_name = name_array[0]
            component_name = name_array[1]
            try:
                return getattr(self._dict[table_name], get_function)(component_name)
            except KeyError as e:
                raise exceptions.SymbolError(component_name, table_name,
                                             'Type {} references missing Type/Symbol/Enum: {}'.format(name, e))
        raise exceptions.SymbolError(name, None, "Malformed name: {}".format(name))


Iteratively resolves a type populating linked child ReferenceTemplates with their properly resolved counterparts .

def _iterative_resolve(self, traverse_list):
        """Iteratively resolves a type, populating linked child
        ReferenceTemplates with their properly resolved counterparts."""
        replacements = set()
        # Whole Symbols that still need traversing
        while traverse_list:
            template_traverse_list, traverse_list = [self._resolved[traverse_list[0]]], traverse_list[1:]
            # Traverse a single symbol looking for any ReferenceTemplate objects
            while template_traverse_list:
                traverser, template_traverse_list = template_traverse_list[0], template_traverse_list[1:]
                for child in traverser.children:
                    if isinstance(child, objects.templates.ReferenceTemplate):
                        # If we haven't seen it before, subresolve it and also add it
                        # to the "symbols that still need traversing" list
                        if child.vol.type_name not in self._resolved:
                            traverse_list.append(child.vol.type_name)
                            try:
                                self._resolved[child.vol.type_name] = self._weak_resolve(
                                    SymbolType.TYPE, child.vol.type_name)
                            except exceptions.SymbolError:
                                self._resolved[child.vol.type_name] = self.UnresolvedTemplate(child.vol.type_name)
                        # Stash the replacement
                        replacements.add((traverser, child))
                    elif child.children:
                        template_traverse_list.append(child)
        for (parent, child) in replacements:
            parent.replace_child(child, self._resolved[child.vol.type_name])


def get_type(self, type_name: str) -> interfaces.objects.Template:
        """Takes a symbol name and resolves it.

        This method ensures that all referenced templates (including
        self-referential templates) are satisfied as ObjectTemplates
        """
        # Traverse down any resolutions
        if type_name not in self._resolved:
            self._resolved[type_name] = self._weak_resolve(SymbolType.TYPE, type_name)  # type: ignore
            self._iterative_resolve([type_name])
        if isinstance(self._resolved[type_name], objects.templates.ReferenceTemplate):
            table_name = None
            index = type_name.find(constants.BANG)
            if index > 0:
                table_name, type_name = type_name[:index], type_name[index + 1:]
            raise exceptions.SymbolError(type_name, table_name, "Unresolvable symbol requested: {}".format(type_name))
        return self._resolved[type_name]

def
get_type
(
self
,
type_name
:
str
)
->
interfaces
.
objects
.
Template
:
# Traverse down any resolutions
if
type_name
not
in
self
.
_resolved
:
self
.
_resolved
[
type_name
]
=
self
.
_weak_resolve
(
SymbolType
.
TYPE
,
type_name
)
# type: ignore
self
.
_iterative_resolve
(
[
type_name
]
)
if
isinstance
(
self
.
_resolved
[
type_name
]
,
objects
.
templates
.
ReferenceTemplate
)
:
table_name
=
index
=
type_name
.
find
(
constants
.
BANG
)
if
index
>
0
:
table_name
,
type_name
=
type_name
[
:
index
]
,
type_name
[
index
+
1
:
]
raise
exceptions
.
SymbolError
(
type_name
,
table_name
,
"Unresolvable symbol requested: {}"
.
format
(
type_name
)
)
return
self
.
_resolved
[
type_name
]


Look - up a symbol name across all the contained symbol spaces .

def get_symbol(self, symbol_name: str) -> interfaces.symbols.SymbolInterface:
        """Look-up a symbol name across all the contained symbol spaces."""
        retval = self._weak_resolve(SymbolType.SYMBOL, symbol_name)
        if symbol_name not in self._resolved_symbols and retval.type is not None:
            self._resolved_symbols[symbol_name] = self._subresolve(retval.type)
        if not isinstance(retval, interfaces.symbols.SymbolInterface):
            table_name = None
            index = symbol_name.find(constants.BANG)
            if index > 0:
                table_name, symbol_name = symbol_name[:index], symbol_name[index + 1:]
            raise exceptions.SymbolError(symbol_name, table_name, "Unresolvable Symbol: {}".format(symbol_name))
        return retval

def
get_symbol
(
self
,
symbol_name
:
str
)
->
interfaces
.
symbols
.
SymbolInterface
:
retval
=
self
.
_weak_resolve
(
SymbolType
.
SYMBOL
,
symbol_name
)
if
symbol_name
not
in
self
.
_resolved_symbols
and
retval
.
type
is
not
:
self
.
_resolved_symbols
[
symbol_name
]
=
self
.
_subresolve
(
retval
.
type
)
if
not
isinstance
(
retval
,
interfaces
.
symbols
.
SymbolInterface
)
:
table_name
=
index
=
symbol_name
.
find
(
constants
.
BANG
)
if
index
>
0
:
table_name
,
symbol_name
=
symbol_name
[
:
index
]
,
symbol_name
[
index
+
1
:
]
raise
exceptions
.
SymbolError
(
symbol_name
,
table_name
,
"Unresolvable Symbol: {}"
.
format
(
symbol_name
)
)
return
retval


Ensure an ObjectTemplate doesn t contain any ReferenceTemplates

def _subresolve(self, object_template: interfaces.objects.Template) -> interfaces.objects.Template:
        """Ensure an ObjectTemplate doesn't contain any ReferenceTemplates"""
        for child in object_template.children:
            if isinstance(child, objects.templates.ReferenceTemplate):
                new_child = self.get_type(child.vol.type_name)
            else:
                new_child = self._subresolve(child)
            object_template.replace_child(old_child = child, new_child = new_child)
        return object_template

def _subresolve ( self , object_template : interfaces . objects . Template ) -> interfaces . objects . Template : for child in object_template . children : if isinstance ( child , objects . templates . ReferenceTemplate ) : new_child = self . get_type ( child . vol . type_name ) else : new_child = self . _subresolve ( child ) object_template . replace_child ( old_child = child , new_child = new_child ) return object_template


Look - up a set of enumeration choices from a specific symbol table .

def get_enumeration(self, enum_name: str) -> interfaces.objects.Template:
        """Look-up a set of enumeration choices from a specific symbol
        table."""
        retval = self._weak_resolve(SymbolType.ENUM, enum_name)
        if not isinstance(retval, interfaces.objects.Template):
            table_name = None
            index = enum_name.find(constants.BANG)
            if index > 0:
                table_name, enum_name = enum_name[:index], enum_name[index + 1:]
            raise exceptions.SymbolError(enum_name, table_name, "Unresolvable Enumeration: {}".format(enum_name))
        return retval

def
get_enumeration
(
self
,
enum_name
:
str
)
->
interfaces
.
objects
.
Template
:
retval
=
self
.
_weak_resolve
(
SymbolType
.
ENUM
,
enum_name
)
if
not
isinstance
(
retval
,
interfaces
.
objects
.
Template
)
:
table_name
=
index
=
enum_name
.
find
(
constants
.
BANG
)
if
index
>
0
:
table_name
,
enum_name
=
enum_name
[
:
index
]
,
enum_name
[
index
+
1
:
]
raise
exceptions
.
SymbolError
(
enum_name
,
table_name
,
"Unresolvable Enumeration: {}"
.
format
(
enum_name
)
)
return
retval


Test for membership of a component within a table .

def _membership(self, member_type: SymbolType, name: str) -> bool:
        """Test for membership of a component within a table."""

        name_array = name.split(constants.BANG)
        if len(name_array) == 2:
            table_name = name_array[0]
            component_name = name_array[1]
        else:
            return False

        if table_name not in self:
            return False
        table = self[table_name]

        if member_type == SymbolType.TYPE:
            return component_name in table.types
        elif member_type == SymbolType.SYMBOL:
            return component_name in table.symbols
        elif member_type == SymbolType.ENUM:
            return component_name in table.enumerations
        return False

def _membership ( self , member_type : SymbolType , name : str ) -> bool : name_array = name . split ( constants . BANG ) if len ( name_array ) == 2 : table_name = name_array [ 0 ] component_name = name_array [ 1 ] else : return False if table_name not in self : return False table = self [ table_name ] if member_type == SymbolType . TYPE : return component_name in table . types elif member_type == SymbolType . SYMBOL : return component_name in table . symbols elif member_type == SymbolType . ENUM : return component_name in table . enumerations return False


Instantiates a SymbolTable based on an IntermediateSymbolFormat JSON file . This is validated against the appropriate schema . The validation can be disabled by passing validate = False but this should almost never be done .

def __init__(self,
                 context: interfaces.context.ContextInterface,
                 config_path: str,
                 name: str,
                 isf_url: str,
                 native_types: interfaces.symbols.NativeTableInterface = None,
                 table_mapping: Optional[Dict[str, str]] = None,
                 validate: bool = True,
                 class_types: Optional[Mapping[str, Type[interfaces.objects.ObjectInterface]]] = None,
                 symbol_shift: int = 0,
                 symbol_mask: int = 0) -> None:
        """Instantiates a SymbolTable based on an IntermediateSymbolFormat JSON file.  This is validated against the
        appropriate schema.  The validation can be disabled by passing validate = False, but this should almost never be
        done.

        Args:
            context: The volatility context for the symbol table
            config_path: The configuration path for the symbol table
            name: The name for the symbol table (this is used in symbols e.g. table!symbol )
            isf_url: The URL pointing to the ISF file location
            native_types: The NativeSymbolTable that contains the native types for this symbol table
            table_mapping: A dictionary linking names referenced in the file with symbol tables in the context
            validate: Determines whether the ISF file will be validated against the appropriate schema
            class_types: A dictionary of type names and classes that override StructType when they are instantiated
            symbol_shift: An offset by which to alter all returned symbols for this table
            symbol_mask: An address mask used for all returned symbol offsets from this table (a mask of 0 disables masking)
        """
        # Check there are no obvious errors
        # Open the file and test the version
        self._versions = dict([(x.version, x) for x in class_subclasses(ISFormatTable)])
        fp = volatility.framework.layers.resources.ResourceAccessor().open(isf_url)
        reader = codecs.getreader("utf-8")
        json_object = json.load(reader(fp))  # type: ignore
        fp.close()

        # Validation is expensive, but we cache to store the hashes of successfully validated json objects
        if validate and not schemas.validate(json_object):
            raise exceptions.SymbolSpaceError("File does not pass version validation: {}".format(isf_url))

        metadata = json_object.get('metadata', None)

        # Determine the delegate or throw an exception
        self._delegate = self._closest_version(metadata.get('format', "0.0.0"),
                                               self._versions)(context, config_path, name, json_object, native_types,
                                                               table_mapping)
        if self._delegate.version < constants.ISF_MINIMUM_SUPPORTED:
            raise RuntimeError("ISF version {} is no longer supported: {}".format(metadata.get('format', "0.0.0"),
                                                                                isf_url))
        elif self._delegate.version < constants.ISF_MINIMUM_DEPRECATED:
            vollog.warning("ISF version {} has been deprecated: {}".format(metadata.get('format', "0.0.0"), isf_url))

        # Inherit
        super().__init__(context,
                         config_path,
                         name,
                         native_types or self._delegate.natives,
                         table_mapping = table_mapping,
                         class_types = class_types)

        # Since we've been created with parameters, ensure our config is populated likewise
        self.config['isf_url'] = isf_url
        self.config['symbol_shift'] = symbol_shift
        self.config['symbol_mask'] = symbol_mask


Determines the highest suitable handler for specified version format .

def _closest_version(version: str, versions: Dict[Tuple[int, int, int], Type['ISFormatTable']]) \
            -> Type['ISFormatTable']:
        """Determines the highest suitable handler for specified version
        format.

        An interface version such as Major.Minor.Patch means that Major
        of the provider must be equal to that of the   consumer, and the
        provider (the JSON in this instance) must have a greater minor
        (indicating that only additive   changes have been made) than
        the consumer (in this case, the file reader).
        """
        major, minor, patch = [int(x) for x in version.split(".")]
        supported_versions = [x for x in versions if x[0] == major and x[1] >= minor]
        if not supported_versions:
            raise ValueError(
                "No Intermediate Format interface versions support file interface version: {}".format(version))
        return versions[max(supported_versions)]


Returns an iterator of appropriate file - scheme symbol URLs that can be opened by a ResourceAccessor class .

def file_symbol_url(cls, sub_path: str, filename: Optional[str] = None) -> Generator[str, None, None]:
        """Returns an iterator of appropriate file-scheme symbol URLs that can
        be opened by a ResourceAccessor class.

        Filter reduces the number of results returned to only those URLs
        containing that string
        """

        # Check user-modifiable files first, then compressed ones
        extensions = constants.ISF_EXTENSIONS
        if filename is None:
            filename = "*"
            zip_match = filename
        else:
            # For zipfiles, the path separator is always "/", so we need to change the path
            zip_match = "/".join(os.path.split(filename))

        # Check user symbol directory first, then fallback to the framework's library to allow for overloading
        vollog.log(constants.LOGLEVEL_VVVV,
                   "Searching for symbols in {}".format(", ".join(volatility.symbols.__path__)))
        for path in volatility.symbols.__path__:
            if not os.path.isabs(path):
                path = os.path.abspath(os.path.join(__file__, path))
            for extension in extensions:
                # Hopefully these will not be large lists, otherwise this might be slow
                try:
                    for found in pathlib.Path(path).joinpath(sub_path).resolve().rglob(filename + extension):
                        yield found.as_uri()
                except FileNotFoundError:
                    # If there's no linux symbols, don't cry about it
                    pass

            # Finally try looking in zip files
            zip_path = os.path.join(path, sub_path + ".zip")
            if os.path.exists(zip_path):
                # We have a zipfile, so run through it and look for sub files that match the filename
                with zipfile.ZipFile(zip_path) as zfile:
                    for name in zfile.namelist():
                        for extension in extensions:
                            # By ending with an extension (and therefore, not /), we should not return any directories
                            if name.endswith(zip_match + extension) or (zip_match == "*" and name.endswith(extension)):
                                yield "jar:file:" + str(pathlib.Path(zip_path)) + "!" + name


Takes a context and loads an intermediate symbol table based on a filename .

def create(cls,
               context: interfaces.context.ContextInterface,
               config_path: str,
               sub_path: str,
               filename: str,
               native_types: Optional[interfaces.symbols.NativeTableInterface] = None,
               table_mapping: Optional[Dict[str, str]] = None,
               class_types: Optional[Mapping[str, Type[interfaces.objects.ObjectInterface]]] = None,
               symbol_shift: int = 0,
               symbol_mask: int = 0) -> str:
        """Takes a context and loads an intermediate symbol table based on a
        filename.

        Args:
            context: The context that the current plugin is being run within
            config_path: The configuration path for reading/storing configuration information this symbol table may use
            sub_path: The path under a suitable symbol path (defaults to volatility/symbols and volatility/framework/symbols) to check
            filename: Basename of the file to find under the sub_path
            native_types: Set of native types, defaults to native types read from the intermediate symbol format file
            table_mapping: a dictionary of table names mentioned within the ISF file, and the tables within the context which they map to
            symbol_shift: An offset by which to alter all returned symbols for this table
            symbol_mask: An address mask used for all returned symbol offsets from this table (a mask of 0 disables masking)

        Returns:
             the name of the added symbol table
        """
        urls = list(cls.file_symbol_url(sub_path, filename))
        if not urls:
            raise FileNotFoundError("No symbol files found at provided filename: {}", filename)
        table_name = context.symbol_space.free_table_name(filename)
        table = cls(context = context,
                    config_path = config_path,
                    name = table_name,
                    isf_url = urls[0],
                    native_types = native_types,
                    table_mapping = table_mapping,
                    class_types = class_types,
                    symbol_shift = symbol_shift,
                    symbol_mask = symbol_mask)
        context.symbol_space.append(table)
        return table_name


Determines the appropriate native_types to use from the JSON data .

def _get_natives(self) -> Optional[interfaces.symbols.NativeTableInterface]:
        """Determines the appropriate native_types to use from the JSON
        data."""
        # TODO: Consider how to generate the natives entirely from the ISF
        classes = {"x64": native.x64NativeTable, "x86": native.x86NativeTable}
        for nc in sorted(classes):
            native_class = classes[nc]
            for base_type in self._json_object['base_types']:
                try:
                    if self._json_object['base_types'][base_type]['length'] != native_class.get_type(base_type).size:
                        break
                except TypeError:
                    # TODO: determine whether we should give voids a size - We don't give voids a length, whereas microsoft seemingly do
                    pass
            else:
                vollog.debug("Choosing appropriate natives for symbol library: {}".format(nc))
                return native_class.natives
        return None


Returns a metadata object containing information about the symbol table .

def metadata(self) -> Optional[interfaces.symbols.MetadataInterface]:
        """Returns a metadata object containing information about the symbol
        table."""
        return None

def metadata ( self ) -> Optional [ interfaces . symbols . MetadataInterface ] : return None


Clears the symbol cache of the symbol table .

def clear_symbol_cache(self) -> None:
        """Clears the symbol cache of the symbol table."""
        self._symbol_cache.clear()

def clear_symbol_cache ( self ) -> None : self . _symbol_cache . clear ( )


Returns the location offset given by the symbol name .

def get_symbol(self, name: str) -> interfaces.symbols.SymbolInterface:
        """Returns the location offset given by the symbol name."""
        # TODO: Add the ability to add/remove/change symbols after creation
        # note that this should invalidate/update the cache
        if self._symbol_cache.get(name, None):
            return self._symbol_cache[name]
        symbol = self._json_object['symbols'].get(name, None)
        if not symbol:
            raise exceptions.SymbolError(name, self.name, "Unknown symbol: {}".format(name))
        address = symbol['address'] + self.config.get('symbol_shift', 0)
        if self.config.get('symbol_mask', 0):
            address = address & self.config['symbol_mask']
        self._symbol_cache[name] = interfaces.symbols.SymbolInterface(name = name, address = address)
        return self._symbol_cache[name]


Returns an iterator of the symbol names .

def symbols(self) -> Iterable[str]:
        """Returns an iterator of the symbol names."""
        return list(self._json_object.get('symbols', {}))

def symbols ( self ) -> Iterable [ str ] : return list ( self . _json_object . get ( 'symbols' , { } ) )


Returns an iterator of the available enumerations .

def enumerations(self) -> Iterable[str]:
        """Returns an iterator of the available enumerations."""
        return list(self._json_object.get('enums', {}))

def enumerations ( self ) -> Iterable [ str ] : return list ( self . _json_object . get ( 'enums' , { } ) )


Returns an iterator of the symbol type names .

def types(self) -> Iterable[str]:
        """Returns an iterator of the symbol type names."""
        return list(self._json_object.get('user_types', {})) + list(self.natives.types)

def types ( self ) -> Iterable [ str ] : return list ( self . _json_object . get ( 'user_types' , { } ) ) + list ( self . natives . types )


Converts an intermediate format dict into an object template .

def _interdict_to_template(self, dictionary: Dict[str, Any]) -> interfaces.objects.Template:
        """Converts an intermediate format dict into an object template."""
        if not dictionary:
            raise exceptions.SymbolSpaceError("Invalid intermediate dictionary: {}".format(dictionary))

        type_name = dictionary['kind']
        if type_name == 'base':
            type_name = dictionary['name']

        if type_name in self.natives.types:
            # The symbol is a native type
            native_template = self.natives.get_type(self.name + constants.BANG + type_name)

            # Add specific additional parameters, etc
            update = {}
            if type_name == 'array':
                update['count'] = dictionary['count']
                update['subtype'] = self._interdict_to_template(dictionary['subtype'])
            elif type_name == 'pointer':
                if dictionary.get('base', None):
                    base_type = self.natives.get_type(self.name + constants.BANG + dictionary['base'])
                    update['data_format'] = base_type.vol['data_format']
                update['subtype'] = self._interdict_to_template(dictionary['subtype'])
            elif type_name == 'enum':
                update = self._lookup_enum(dictionary['name'])
            elif type_name == 'bitfield':
                update = {
                    'start_bit': dictionary['bit_position'],
                    'end_bit': dictionary['bit_position'] + dictionary['bit_length']
                }
                update['base_type'] = self._interdict_to_template(dictionary['type'])
            # We do *not* call native_template.clone(), since it slows everything down a lot
            # We require that the native.get_type method always returns a newly constructed python object
            native_template.update_vol(**update)
            return native_template

        # Otherwise
        if dictionary['kind'] not in objects.AggregateTypes.values():
            raise exceptions.SymbolSpaceError("Unknown Intermediate format: {}".format(dictionary))

        reference_name = dictionary['name']
        if constants.BANG not in reference_name:
            reference_name = self.name + constants.BANG + reference_name
        else:
            reference_parts = reference_name.split(constants.BANG)
            reference_name = (self.table_mapping.get(reference_parts[0], reference_parts[0]) + constants.BANG +
                              constants.BANG.join(reference_parts[1:]))

        return objects.templates.ReferenceTemplate(type_name = reference_name)


Looks up an enumeration and returns a dictionary of __init__ parameters for an Enum .

def _lookup_enum(self, name: str) -> Dict[str, Any]:
        """Looks up an enumeration and returns a dictionary of __init__
        parameters for an Enum."""
        lookup = self._json_object['enums'].get(name, None)
        if not lookup:
            raise exceptions.SymbolSpaceError("Unknown enumeration: {}".format(name))
        result = {"choices": copy.deepcopy(lookup['constants']), "base_type": self.natives.get_type(lookup['base'])}
        return result

def
_lookup_enum
(
self
,
name
:
str
)
->
Dict
[
str
,
Any
]
:
lookup
=
self
.
_json_object
[
'enums'
]
.
get
(
name
,
)
if
not
lookup
:
raise
exceptions
.
SymbolSpaceError
(
"Unknown enumeration: {}"
.
format
(
name
)
)
result
=
{
"choices"
:
copy
.
deepcopy
(
lookup
[
'constants'
]
)
,
"base_type"
:
self
.
natives
.
get_type
(
lookup
[
'base'
]
)
}
return
result


def get_enumeration(self, enum_name: str) -> interfaces.objects.Template:
        """Resolves an individual enumeration."""
        if constants.BANG in enum_name:
            raise exceptions.SymbolError(enum_name, self.name,
                                         "Enumeration for a different table requested: {}".format(enum_name))
        if enum_name not in self._json_object['enums']:
            # Fall back to the natives table
            raise exceptions.SymbolError(enum_name, self.name,
                                         "Enumeration not found in {} table: {}".format(self.name, enum_name))
        curdict = self._json_object['enums'][enum_name]
        base_type = self.natives.get_type(curdict['base'])
        # The size isn't actually used, the base-type defines it.
        return objects.templates.ObjectTemplate(type_name = self.name + constants.BANG + enum_name,
                                                object_class = objects.Enumeration,
                                                base_type = base_type,
                                                choices = curdict['constants'])


def get_type(self, type_name: str) -> interfaces.objects.Template:
        """Resolves an individual symbol."""
        if constants.BANG in type_name:
            index = type_name.find(constants.BANG)
            table_name, type_name = type_name[:index], type_name[index + 1:]
            raise exceptions.SymbolError(
                type_name, table_name,
                "Symbol for a different table requested: {}".format(table_name + constants.BANG + type_name))
        if type_name not in self._json_object['user_types']:
            # Fall back to the natives table
            return self.natives.get_type(self.name + constants.BANG + type_name)
        curdict = self._json_object['user_types'][type_name]
        members = {}
        for member_name in curdict['fields']:
            interdict = curdict['fields'][member_name]
            member = (interdict['offset'], self._interdict_to_template(interdict['type']))
            members[member_name] = member
        object_class = self.get_type_class(type_name)
        if object_class == objects.AggregateType:
            for clazz in objects.AggregateTypes:
                if objects.AggregateTypes[clazz] == curdict['kind']:
                    object_class = clazz
        return objects.templates.ObjectTemplate(type_name = self.name + constants.BANG + type_name,
                                                object_class = object_class,
                                                size = curdict['length'],
                                                members = members)


def _get_natives(self) -> Optional[interfaces.symbols.NativeTableInterface]:
        """Determines the appropriate native_types to use from the JSON
        data."""
        classes = {"x64": native.x64NativeTable, "x86": native.x86NativeTable}
        for nc in sorted(classes):
            native_class = classes[nc]
            for base_type in self._json_object['base_types']:
                try:
                    if self._json_object['base_types'][base_type]['size'] != native_class.get_type(base_type).size:
                        break
                except TypeError:
                    # TODO: determine whether we should give voids a size - We don't give voids a length, whereas microsoft seemingly do
                    pass
            else:
                vollog.debug("Choosing appropriate natives for symbol library: {}".format(nc))
                return native_class.natives
        return None


def get_type(self, type_name: str) -> interfaces.objects.Template:
        """Resolves an individual symbol."""
        if constants.BANG in type_name:
            index = type_name.find(constants.BANG)
            table_name, type_name = type_name[:index], type_name[index + 1:]
            raise exceptions.SymbolError(
                type_name, table_name,
                "Symbol for a different table requested: {}".format(table_name + constants.BANG + type_name))
        if type_name not in self._json_object['user_types']:
            # Fall back to the natives table
            if type_name in self.natives.types:
                return self.natives.get_type(self.name + constants.BANG + type_name)
            else:
                raise exceptions.SymbolError(type_name, self.name, "Unknown symbol: {}".format(type_name))
        curdict = self._json_object['user_types'][type_name]
        members = {}
        for member_name in curdict['fields']:
            interdict = curdict['fields'][member_name]
            member = (interdict['offset'], self._interdict_to_template(interdict['type']))
            members[member_name] = member
        object_class = self.get_type_class(type_name)
        if object_class == objects.AggregateType:
            for clazz in objects.AggregateTypes:
                if objects.AggregateTypes[clazz] == curdict['kind']:
                    object_class = clazz
        return objects.templates.ObjectTemplate(type_name = self.name + constants.BANG + type_name,
                                                object_class = object_class,
                                                size = curdict['size'],
                                                members = members)


Returns the symbol given by the symbol name .

def get_symbol(self, name: str) -> interfaces.symbols.SymbolInterface:
        """Returns the symbol given by the symbol name."""
        if self._symbol_cache.get(name, None):
            return self._symbol_cache[name]
        symbol = self._json_object['symbols'].get(name, None)
        if not symbol:
            raise exceptions.SymbolError(name, self.name, "Unknown symbol: {}".format(name))
        symbol_type = None
        if 'type' in symbol:
            symbol_type = self._interdict_to_template(symbol['type'])

        # Mask the addresses if necessary
        address = symbol['address'] + self.config.get('symbol_shift', 0)
        if self.config.get('symbol_mask', 0):
            address = address & self.config['symbol_mask']
        self._symbol_cache[name] = interfaces.symbols.SymbolInterface(name = name,
                                                                      address = address,
                                                                      type = symbol_type)
        return self._symbol_cache[name]

def
get_symbol
(
self
,
name
:
str
)
->
interfaces
.
symbols
.
SymbolInterface
:
if
self
.
_symbol_cache
.
get
(
name
,
)
:
return
self
.
_symbol_cache
[
name
]
symbol
=
self
.
_json_object
[
'symbols'
]
.
get
(
name
,
)
if
not
symbol
:
raise
exceptions
.
SymbolError
(
name
,
self
.
name
,
"Unknown symbol: {}"
.
format
(
name
)
)
symbol_type
=
if
'type'
in
symbol
:
symbol_type
=
self
.
_interdict_to_template
(
symbol
[
'type'
]
)
# Mask the addresses if necessary
address
=
symbol
[
'address'
]
+
self
.
config
.
get
(
'symbol_shift'
,
0
)
if
self
.
config
.
get
(
'symbol_mask'
,
0
)
:
address
=
address
&
self
.
config
[
'symbol_mask'
]
self
.
_symbol_cache
[
name
]
=
interfaces
.
symbols
.
SymbolInterface
(
name
=
name
,
address
=
address
,
type
=
symbol_type
)
return
self
.
_symbol_cache
[
name
]


def _get_natives(self) -> Optional[interfaces.symbols.NativeTableInterface]:
        """Determines the appropriate native_types to use from the JSON
        data."""
        native_dict = {}
        base_types = self._json_object['base_types']
        for base_type in base_types:
            # Void are ignored because voids are not a volatility primitive, they are a specific Volatility object
            if base_type != 'void':
                current = base_types[base_type]
                # TODO: Fix up the typing of this, it bugs out because of the tuple assignment
                if current['kind'] not in self.format_mapping:
                    raise ValueError("Unsupported base kind")
                format_val = (current['size'], current['endian'], current['signed'])
                object_type = self.format_mapping[current['kind']]
                if base_type == 'pointer':
                    object_type = objects.Pointer
                native_dict[base_type] = (object_type, format_val)
        return native.NativeTable(name = "native", native_dictionary = native_dict)


def get_symbol(self, name: str) -> interfaces.symbols.SymbolInterface:
        """Returns the symbol given by the symbol name."""
        if self._symbol_cache.get(name, None):
            return self._symbol_cache[name]
        symbol = self._json_object['symbols'].get(name, None)
        if not symbol:
            raise exceptions.SymbolError(name, self.name, "Unknown symbol: {}".format(name))
        symbol_type = None
        if 'type' in symbol:
            symbol_type = self._interdict_to_template(symbol['type'])
        symbol_constant_data = None
        if 'constant_data' in symbol:
            symbol_constant_data = base64.b64decode(symbol.get('constant_data'))

        # Mask the addresses if necessary
        address = symbol['address'] + self.config.get('symbol_shift', 0)
        if self.config.get('symbol_mask', 0):
            address = address & self.config['symbol_mask']
        self._symbol_cache[name] = interfaces.symbols.SymbolInterface(name = name,
                                                                      address = address,
                                                                      type = symbol_type,
                                                                      constant_data = symbol_constant_data)
        return self._symbol_cache[name]

def
get_symbol
(
self
,
name
:
str
)
->
interfaces
.
symbols
.
SymbolInterface
:
if
self
.
_symbol_cache
.
get
(
name
,
)
:
return
self
.
_symbol_cache
[
name
]
symbol
=
self
.
_json_object
[
'symbols'
]
.
get
(
name
,
)
if
not
symbol
:
raise
exceptions
.
SymbolError
(
name
,
self
.
name
,
"Unknown symbol: {}"
.
format
(
name
)
)
symbol_type
=
if
'type'
in
symbol
:
symbol_type
=
self
.
_interdict_to_template
(
symbol
[
'type'
]
)
symbol_constant_data
=
if
'constant_data'
in
symbol
:
symbol_constant_data
=
base64
.
b64decode
(
symbol
.
get
(
'constant_data'
)
)
# Mask the addresses if necessary
address
=
symbol
[
'address'
]
+
self
.
config
.
get
(
'symbol_shift'
,
0
)
if
self
.
config
.
get
(
'symbol_mask'
,
0
)
:
address
=
address
&
self
.
config
[
'symbol_mask'
]
self
.
_symbol_cache
[
name
]
=
interfaces
.
symbols
.
SymbolInterface
(
name
=
name
,
address
=
address
,
type
=
symbol_type
,
constant_data
=
symbol_constant_data
)
return
self
.
_symbol_cache
[
name
]


def metadata(self) -> Optional[interfaces.symbols.MetadataInterface]:
        """Returns a MetadataInterface object."""
        if self._json_object.get('metadata', {}).get('windows'):
            return metadata.WindowsMetadata(self._json_object['metadata']['windows'])
        if self._json_object.get('metadata', {}).get('linux'):
            return metadata.LinuxMetadata(self._json_object['metadata']['linux'])
        return None

def metadata ( self ) -> Optional [ interfaces . symbols . MetadataInterface ] : if self . _json_object . get ( 'metadata' , { } ) . get ( 'windows' ) : return metadata . WindowsMetadata ( self . _json_object [ 'metadata' ] [ 'windows' ] ) if self . _json_object . get ( 'metadata' , { } ) . get ( 'linux' ) : return metadata . LinuxMetadata ( self . _json_object [ 'metadata' ] [ 'linux' ] ) return None


For each type field it walks its tree of subtypes reducing the hierarchy to just one level . It creates a tuple of offset and object templates for each field .

def _process_fields(self, fields: Dict[str, Dict[str, Any]]) -> Dict[Any, Tuple[int, interfaces.objects.Template]]:
        """For each type field, it walks its tree of subtypes, reducing the hierarchy to just one level.
        It creates a tuple of offset and object templates for each field.
        """
        members = {}
        for new_offset, member_name, member_value in self._reduce_fields(fields):
            member = (new_offset, self._interdict_to_template(member_value['type']))
            members[member_name] = member
        return members

def _process_fields ( self , fields : Dict [ str , Dict [ str , Any ] ] ) -> Dict [ Any , Tuple [ int , interfaces . objects . Template ] ] : members = { } for new_offset , member_name , member_value in self . _reduce_fields ( fields ) : member = ( new_offset , self . _interdict_to_template ( member_value [ 'type' ] ) ) members [ member_name ] = member return members


Reduce the fields bringing them one level up . It supports anonymous types such as structs or unions in any level of depth .

def _reduce_fields(self,
                       fields: Dict[str, Dict[str, Any]],
                       parent_offset: int = 0) -> Generator[Tuple[int, str, Dict], None, None]:
        """Reduce the fields bringing them one level up. It supports anonymous types such as structs or unions in any
        level of depth."""
        for member_name, member_value in fields.items():
            new_offset = parent_offset + member_value.get('offset', 0)
            if member_value.get('anonymous', False) and isinstance(member_value, dict):
                # Gets the subtype from the json ISF and recursively reduce its fields
                subtype = self._json_object['user_types'].get(member_value['type']['name'], {})
                yield from self._reduce_fields(subtype['fields'], new_offset)
            else:
                yield new_offset, member_name, member_value


def get_type(self, type_name: str) -> interfaces.objects.Template:
        """Resolves an individual symbol."""
        index = type_name.find(constants.BANG)
        if index != -1:
            table_name, type_name = type_name[:index], type_name[index + 1:]
            raise exceptions.SymbolError(
                type_name, table_name,
                "Symbol for a different table requested: {}".format(table_name + constants.BANG + type_name))

        type_definition = self._json_object['user_types'].get(type_name)
        if type_definition is None:
            # Fall back to the natives table
            return self.natives.get_type(self.name + constants.BANG + type_name)

        members = self._process_fields(type_definition['fields'])

        object_class = self.get_type_class(type_name)
        if object_class == objects.AggregateType:
            for clazz in objects.AggregateTypes:
                if objects.AggregateTypes[clazz] == type_definition['kind']:
                    object_class = clazz
        return objects.templates.ObjectTemplate(type_name = self.name + constants.BANG + type_name,
                                                object_class = object_class,
                                                size = type_definition['size'],
                                                members = members)


def types(self) -> Iterable[str]:
        """Returns an iterator of the symbol type names."""
        return self._types

def types ( self ) -> Iterable [ str ] : return self . _types


Resolves a symbol name into an object template .

def get_type(self, type_name: str) -> interfaces.objects.Template:
        """Resolves a symbol name into an object template.

        This always construct a new python object, rather than using a
        cached value otherwise changes made later may affect the cached
        copy.  Calling clone after every native type construction was
        extremely slow.
        """
        # NOTE: These need updating whenever the object init signatures change
        prefix = ""
        if constants.BANG in type_name:
            name_split = type_name.split(constants.BANG)
            if len(name_split) > 2:
                raise ValueError("SymbolName cannot contain multiple {} separators".format(constants.BANG))
            table_name, type_name = name_split
            prefix = table_name + constants.BANG

        additional = {}  # type: Dict[str, Any]
        obj = None  # type: Optional[Type[interfaces.objects.ObjectInterface]]
        if type_name == 'void' or type_name == 'function':
            obj = objects.Void
        elif type_name == 'array':
            obj = objects.Array
            additional = {"count": 0, "subtype": self.get_type('void')}
        elif type_name == 'enum':
            obj = objects.Enumeration
            additional = {"base_type": self.get_type('void'), "choices": {}}
        elif type_name == 'bitfield':
            obj = objects.BitField
            additional = {"start_bit": 0, "end_bit": 0, "base_type": self.get_type('void')}
        elif type_name == 'string':
            obj = objects.String
            additional = {"max_length": 0}
        elif type_name == 'bytes':
            obj = objects.Bytes
            additional = {"length": 0}
        if obj is not None:
            return objects.templates.ObjectTemplate(obj, type_name = prefix + type_name, **additional)

        _native_type, native_format = self._native_dictionary[type_name]
        if type_name == 'pointer':
            additional = {'subtype': self.get_type('void')}
        return objects.templates.ObjectTemplate(
            self.get_type_class(type_name),  # pylint: disable=W0142
            type_name = prefix + type_name,
            data_format = objects.DataFormatInfo(*native_format),
            **additional)


def __call__(self, value: int) -> List[str]:
        """Return the appropriate Flags."""
        result = []
        for k, v in self.choices.items():
            if value & v:
                result.append(k)
        return result

def __call__ ( self , value : int ) -> List [ str ] : result = [ ] for k , v in self . choices . items ( ) : if value & v : result . append ( k ) return result


def symbol_table_from_offset(cls,
                                 context: interfaces.context.ContextInterface,
                                 layer_name: str,
                                 offset: int,
                                 symbol_table_class: str,
                                 config_path: str = None,
                                 progress_callback: constants.ProgressCallback = None) -> Optional[str]:
        """Produces the name of a symbol table loaded from the offset for an MZ header

        Args:
            context: The context on which to operate
            layer_name: The name of the (contiguous) layer within the context that contains the MZ file
            offset: The offset in the layer at which the MZ file begins
            symbol_table_class: The type of symbol class to construct the SymbolTable
            config_path: New path for the produced symbol table configuration with the config tree
            progress_callback: Callable called to update ongoing progress

        Returns:
            None if no pdb information can be determined, else returned the name of the loaded symbols for the MZ
        """
        result = cls.get_guid_from_mz(context, layer_name, offset)
        if result is None:
            return None
        guid, age, pdb_name = result
        if config_path is None:
            config_path = interfaces.configuration.path_join('pdbutility', pdb_name.replace('.', '_'))

        return cls.load_windows_symbol_table(context, guid, age, pdb_name, symbol_table_class, config_path,
                                             progress_callback)

def symbol_table_from_offset ( cls , context : interfaces . context . ContextInterface , layer_name : str , offset : int , symbol_table_class : str , config_path : str = None , progress_callback : constants . ProgressCallback = None ) -> Optional [ str ] : result = cls . get_guid_from_mz ( context , layer_name , offset ) if result is None : return None guid , age , pdb_name = result if config_path is None : config_path = interfaces . configuration . path_join ( 'pdbutility' , pdb_name . replace ( '.' , '_' ) ) return cls . load_windows_symbol_table ( context , guid , age , pdb_name , symbol_table_class , config_path , progress_callback )


Loads ( downlading if necessary ) a windows symbol table

def load_windows_symbol_table(cls,
                                  context: interfaces.context.ContextInterface,
                                  guid: str,
                                  age: int,
                                  pdb_name: str,
                                  symbol_table_class: str,
                                  config_path: str = 'pdbutility',
                                  progress_callback: constants.ProgressCallback = None):
        """Loads (downlading if necessary) a windows symbol table"""

        filter_string = os.path.join(pdb_name.strip('\x00'), guid.upper() + "-" + str(age))

        isf_path = False
        # Take the first result of search for the intermediate file
        for value in intermed.IntermediateSymbolTable.file_symbol_url("windows", filter_string):
            isf_path = value
            break
        else:
            # If none are found, attempt to download the pdb, convert it and try again
            cls.download_pdb_isf(context, guid.upper(), age, pdb_name, progress_callback)
            # Try again
            for value in intermed.IntermediateSymbolTable.file_symbol_url("windows", filter_string):
                isf_path = value
                break

        if not isf_path:
            vollog.debug("Required symbol library path not found: {}".format(filter_string))
            return None

        vollog.debug("Using symbol library: {}".format(filter_string))

        # Set the discovered options
        join = interfaces.configuration.path_join
        context.config[join(config_path, "class")] = symbol_table_class
        context.config[join(config_path, "isf_url")] = isf_path
        parent_config_path = interfaces.configuration.parent_path(config_path)
        requirement_name = interfaces.configuration.path_head(config_path)

        # Construct the appropriate symbol table
        requirement = SymbolTableRequirement(name = requirement_name, description = "PDBUtility generated symbol table")
        requirement.construct(context, parent_config_path)
        return context.config[config_path]