diff --git a/volatility/framework/configuration/depresolver.py b/volatility/framework/configuration/depresolver.py index a177542e3..d7acd7763 100644 --- a/volatility/framework/configuration/depresolver.py +++ b/volatility/framework/configuration/depresolver.py @@ -8,31 +8,33 @@ class DependencyResolver(validity.ValidityRoutines): def __init__(self): # Maintain a cache of translation layers self.layer_cache = [] - self.metadata = {} - self.populate_metadata() + self.symbol_cache = [] + self.provides = {} + self.populate_metadata(layers.DataLayerInterface, self.layer_cache) + # self.populate_metadata(, self.symbol_cache) - def populate_metadata(self): - self.metadata = {} - for layer_class in framework.class_subclasses(layers.DataLayerInterface): - for k, v in layer_class.metadata.items(): + def populate_metadata(self, clazz, cache): + self.provides = {} + for provider in framework.class_subclasses(clazz): + for k, v in provider.provides.items(): if not isinstance(v, list): - new_v = self.metadata.get(k, set()) + new_v = self.provides.get(k, set()) new_v.add(v) else: - new_v = self.metadata.get(k, set()).union(set(v)) - self.metadata[k] = new_v - self.layer_cache.append(layer_class) + new_v = self.provides.get(k, set()).union(set(v)) + self.provides[k] = new_v + cache.append(provider) - def satisfies(self, layer_class, requirement): + def satisfies(self, provider, requirement): """Takes the requirement (which should always be a TranslationLayerRequirement) and determines if the layer_class satisfies it""" satisfied = True for k, v in requirement.constraints.items(): - if k in layer_class.metadata: + if k in provider.provides: if isinstance(v, list): - satisfied = satisfied and layer_class.metadata[k] not in v + satisfied = satisfied and provider.provides[k] not in v else: - satisfied = satisfied and (layer_class.metadata[k] == v) + satisfied = satisfied and (provider.provides[k] == v) return satisfied def validate_dependencies(self, deptree, context, path = None): @@ -48,20 +50,22 @@ class DependencyResolver(validity.ValidityRoutines): node_path = path + configuration.CONFIG_SEPARATOR + node.requirement.name if isinstance(node, RequirementTreeNode) and not node.requirement.optional: node_config = context.config.branch(node_path) - for possible_layer, subtree in node.branches.items(): + for provider, subtree in node.branches.items(): if self.validate_dependencies(subtree, context, path = node_path): - # Generate a layer name - layer_name = node.requirement.name - counter = 2 - while layer_name in context.memory: - layer_name = node.requirement.name + str(counter) - counter += 1 + if issubclass(provider, layers.DataLayerInterface): + # Generate a layer name + layer_name = node.requirement.name + counter = 2 + while layer_name in context.memory: + layer_name = node.requirement.name + str(counter) + counter += 1 - # Construct the layer - requirement_dict = node_config.data - context.add_layer(possible_layer(context, node_path, layer_name, **requirement_dict)) - context.config[node_path] = layer_name - break + # Construct the layer + requirement_dict = node_config.data + context.add_layer(provider(context, node_path, layer_name, **requirement_dict)) + context.config[node_path] = layer_name + break + # elif issubclass(provider, ) else: return False try: @@ -104,10 +108,13 @@ class DependencyResolver(validity.ValidityRoutines): if branch: branches[potential_layer] = branch deptree.append(RequirementTreeNode(requirement = requirement, branches = branches)) + elif isinstance(requirement, framework.configuration.SymbolRequirement): + branches = {} + for potential_symbol_space in self.symbol_cache: + if self.satisfies(potential_symbol_space, requirement): + branch = self.build_tree() else: # Add all base-type requirements # Add all optional base-type requirements in order deptree.append(RequirementTreeLeaf(requirement)) return deptree - - diff --git a/volatility/framework/interfaces/layers.py b/volatility/framework/interfaces/layers.py index 7581e0396..d20586ea2 100644 --- a/volatility/framework/interfaces/layers.py +++ b/volatility/framework/interfaces/layers.py @@ -10,14 +10,16 @@ from volatility.framework.interfaces import configuration from abc import ABCMeta, abstractmethod, abstractproperty -class DataLayerInterface(configuration.Configurable, validity.ValidityRoutines, metaclass = ABCMeta): +class DataLayerInterface(configuration.Configurable, configuration.ProviderInterface, + validity.ValidityRoutines, metaclass = ABCMeta): """A Layer that directly holds data (and does not translate it""" - metadata = {"type": "interface"} + provides = {"type": "interface"} def __init__(self, context, config_path, name): - validity.ValidityRoutines.__init__(self) configuration.Configurable.__init__(self, context, config_path) + configuration.ProviderInterface.__init__(self) + validity.ValidityRoutines.__init__(self) self._check_type(name, str) self._name = name @@ -70,7 +72,7 @@ class DataLayerInterface(configuration.Configurable, validity.ValidityRoutines, class TranslationLayerInterface(DataLayerInterface, metaclass = ABCMeta): # Unfortunately class attributes can't easily be inheritted from parent classes - metadata = {"type": "interface"} + provides = {"type": "interface"} @abstractmethod def translate(self, offset): diff --git a/volatility/framework/layers/intel.py b/volatility/framework/layers/intel.py index 274bd73f3..a8caa0605 100644 --- a/volatility/framework/layers/intel.py +++ b/volatility/framework/layers/intel.py @@ -13,7 +13,7 @@ from volatility.framework import interfaces, exceptions, configuration class Intel(interfaces.layers.TranslationLayerInterface): """Translation Layer for the Intel IA32 memory mapping""" - metadata = {"type": "memory", + provides = {"type": "memory", "architecture": "ia32" } @@ -157,7 +157,7 @@ class IntelPAE(Intel): class Intel32e(Intel): - metadata = {"type": "memory", + provides = {"type": "memory", "architecture": "ia64" } diff --git a/volatility/framework/layers/physical.py b/volatility/framework/layers/physical.py index eaa4edeaa..1a783bbe5 100644 --- a/volatility/framework/layers/physical.py +++ b/volatility/framework/layers/physical.py @@ -12,7 +12,7 @@ from volatility.framework import interfaces, exceptions, configuration class BufferDataLayer(interfaces.layers.DataLayerInterface): """A DataLayer class backed by a buffer in memory, designed for testing and swift data access""" - metadata = {"type": "physical"} + provides = {"type": "physical"} def __init__(self, context, config_path, name, buffer): interfaces.layers.DataLayerInterface.__init__(self, context, config_path, name) @@ -53,7 +53,7 @@ class BufferDataLayer(interfaces.layers.DataLayerInterface): class FileLayer(interfaces.layers.DataLayerInterface): """a DataLayer backed by a file on the filesystem""" - metadata = {"type": "physical"} + provides = {"type": "physical"} def __init__(self, context, config_path, name, filename): interfaces.layers.DataLayerInterface.__init__(self, context, config_path, name)