ResourceView is an object which is an instance of a
ViewableResourceTag and may contain
methods and attributes. A
Resource tagged with that
ViewableResourceTag may be analyzed
for the information necessary to create an instance of that
ViewableResourceTag - this means
calling analyzers which produce all of the attributes defined for that tag.
Many ResourceTags represent abstractions of firmware artifacts which certainly have some
information associated with them. For example, an Instruction certainly has a virtual address, a
size, and a mnemonic. In OFRAK these could be represented as individual ResourceAttributes types,
which are each analyzed individually. But this presents a couple of problems:
1) It is not obvious which attributes a particular tag can be expected to have, since they are
2) If attributes are divided into individual classes (which is desirable for consistency when
dealing with a particular abstraction, e.g. every resource that has a virtual address should
represent that address in the same way) then to represent all of the "certain" attributes of a
given tag, multiple instances of attributes and/or a container to hold them are needed.
3) Since the certainty that resources with a given tag have some specific attributes is not
actually enforced, it is not a guarantee and this creates the need to handle cases where those
attributes are not present. In order to be guaranteed the presence of those attributes, they
should be fetched through
Resource.analyze(...) however this is an async call which
may generate some I/O. For debugging (and in general for easier reasoning) it would be much
easier if all of these "certain" attributes could be analyzed together and stored together in a
Additionally, there are cases where it is useful to have a representation of a resource without actually creating a proper Resource. At the very least this might represent all of the attributes of that resource. This avoids the unnecessary creating & deleting of temporary resources. Instead, a familiar representation would be created in the meantime, and turned into a proper Resource once finalized.
ResourceView class is merely the base class to inherit from in order to create a new viewable
ViewableResourceTag is equivalent to a
ResourceTag and can be used in all the same
ways. In addition, if a resource is tagged with a particular
ViewableResourceTag, a client
can get a view instance of the resource. This view instance will be an instance of that
ViewableResourceTag type, with all of the attributes that tag should have. The class
definition of the tag defines what these attributes are, as well as any methods also available to
A view may also contain an instance of the Resource it is "viewing": When a client calls
v = r.view_as(T) the returned view
v of type
T will have an attribute
r. This attribute is optional though; views can be created independently of any
Resource by instantiating them with the class's normal dataclass constructor.
It's easiest to understand the
ResourceView by first imagining it totally independently from the
Resource. On that level it is pretty simple: It is just a dataclass, and it represents some
specific firmware abstraction. Now add in that one can convert easily back and forth between the
ResourceView and the
Resource - the former is specific to one firmware abstraction, and the
latter is a generic interface for all firmware artifacts OFRAK works with.
When to Use
When should one define a tag as a
ViewableResourceTag (by inheriting from
instead of a simple
* It's a good idea to make a tag viewable when any resource with this tag should certainly have
some attributes, and any resource with those attributes should certainly be considered an
instance of that tag. A viewable tag is a purposeful coupling of attributes to a tag, so you
should be sure that is what you want to do.
* Another case it's a good idea to make a tag viewable is when there is some frequent functionality
you want to expose in a method of that tag. As mentioned before, it is a common pattern to write
methods for a tag which wrap queries to find related resources.
* If you make a tag viewable because you want to write methods for it, be careful to not throw in
attributes to that class without good reason. They should still satisfy the "certainly" clauses
under the first bullet.
Notes on Metaclass Terminology
ViewableResourceTag are both metaclasses. This means that an instance of
either one is a class.
ResourceView is a class, which is an instance of
Then an instance of
ResourceView is an object - the view itself.
type(view_instance) is ResourceView
type(ResourceView) is ViewableResourceTag
Since tags are classes, when we talk about the tags in the context of (for example) a list, we
say that list has type
List[ResourceTag]. Just like a list of type
Wrench, our tag list contains instances of
ResourceTag - each of which happens
to be a class object. It's similar to typing