Skip to content

ResourceView

A 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.

Motivation

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 necessarily decoupled. 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 simple container.

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.

Design

The ResourceView class is merely the base class to inherit from in order to create a new viewable tag. A 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 particular 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 the view.

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 v.resource which returns 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 ResourceView) instead of a simple ResourceTag? * 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

ResourceTag and ViewableResourceTag are both metaclasses. This means that an instance of either one is a class. ResourceView is a class, which is an instance of ViewableResourceTag. 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 List[Wrench] contains instances of Wrench, our tag list contains instances of ResourceTag - each of which happens to be a class object. It's similar to typing List[Type[SomeClassWithMetaclassResourceTag]].