Move metadata to providers variable, and genericize the rudimentary resolver.

This commit is contained in:
Mike Auty
2016-01-15 01:50:02 +00:00
parent 3a8decd57c
commit b36d84ab0d
4 changed files with 45 additions and 36 deletions
@@ -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
+6 -4
View File
@@ -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):
+2 -2
View File
@@ -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"
}
+2 -2
View File
@@ -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)