Unpackers are responsible for logically partitioning a single binary target into constituent children. This often involves partitioning data in some way, but there is no limitation on what constitutes a valid child in respect to the parent's data.
Unpackers (and all components) target specific resource tags and typically unpack children with specific resource tags. For example, consider the following unpacker:
from abc import ABC, abstractmethod from ofrak.resource import Resource from ofrak.component.unpacker import Unpacker class IElfUnpacker(Unpacker[None], ABC): id = b"ElfUnpacker" targets = (Elf,) children = ( ElfBasicHeader, ElfHeader, ElfProgramHeader, ElfSectionHeader, ElfSection, ElfStringSection, ElfSymbolSection, CodeRegion, ) @abstractmethod async def unpack(self, resource: Resource, config=None): raise NotImplementedError()
This unpacker targets
Elf. Its children must be one of:
Unpackers may at some point call other unpackers, or unpack descendants (children of children). For example, compressed file system unpackers can unpack a tree of children and descendants from one resource. These nested calls are fine.
There are several ways in which unpackers can be invoked in OFRAK.
The most direct way to run a specific unpacker is to run it directly against a resource. For example:
from ofrak.resource import Resource from ofrak_components.elf.unpacker import ElfUnpacker ... resource: Resource await resource.run(ElfUnpacker)
Unpackers can also be run automatically against resources with valid resource tags. For example, consider the following code:
from ofrak.resource import Resource ... resource: Resource await resource.unpack()
resource is an ELF, OFRAK will run the
IElfUnpacker when this code is run. The reason for this is that
Resource.unpack first runs all registered identifiers. Since the file is an ELF, it will be given the
Elf tag, and OFRAK will then run the
It is also possible to chain
unpack calls together recursively using the
Resource.unpack_recursively method. See Resource for more details.