Skip to content

memory_region.py

ofrak.core.memory_region

MemoryOverlapError (RuntimeError)

Error raised when a memory region overlaps with an existing child memory region.

MemoryRegion (Addressable) dataclass

Binary bytes that are addressable.

Attributes:

Name Type Description
virtual_address int

the virtual address of the start of the memory region

size int

the size of the memory region

end_vaddr(self)

Get the virtual address of the end of the memory region.

Returns:

Type Description
int

the virtual address directly after the memory region

Source code in ofrak/core/memory_region.py
def end_vaddr(self) -> int:
    """
    Get the virtual address of the end of the memory region.

    :returns: the virtual address directly after the memory region
    """
    return self.virtual_address + self.size

contains(self, vaddr)

Does the memory region contain the given virtual address?

Parameters:

Name Type Description Default
vaddr int

a virtual address

required

Returns:

Type Description
bool

True if the memory region contains the given virtual address

Source code in ofrak/core/memory_region.py
def contains(self, vaddr: int) -> bool:
    """
    Does the memory region contain the given virtual address?

    :param vaddr: a virtual address

    :return: True if the memory region contains the given virtual address
    """
    return self.virtual_address <= vaddr < self.end_vaddr()

get_offset_in_self(self, vaddr)

Get the physical offset within the memory region that corresponds to the given virtual address.

Parameters:

Name Type Description Default
vaddr int

a virtual address

required

Returns:

Type Description
int

an offset within the memory region

Source code in ofrak/core/memory_region.py
def get_offset_in_self(self, vaddr: int) -> int:
    """
    Get the physical offset within the memory region that corresponds to the given virtual
    address.

    :param vaddr: a virtual address

    :return: an offset within the memory region
    """
    if not self.contains(vaddr):
        raise ValueError(
            f"Memory region {hex(self.virtual_address)}-{hex(self.end_vaddr())} "
            f"does not contain vaddr {hex(vaddr)}"
        )
    return vaddr - self.virtual_address

create_child_region(self, child_mr, additional_attributes=()) async

Create a child memory region that is mapped into this memory region.

Parameters:

Name Type Description Default
child_mr MemoryRegion

the child memory region

required
additional_attributes Iterable[ofrak.model.resource_model.ResourceAttributes]

additional attributes passed to the child memory region

()

Returns:

Type Description
Resource

the created child resource

Exceptions:

Type Description
OverlapError

if the child to be created overlaps with an existing child node

ValueError

if the child's end offset is larger than the memory region's size

Source code in ofrak/core/memory_region.py
async def create_child_region(
    self,
    child_mr: "MemoryRegion",
    additional_attributes: Iterable[ResourceAttributes] = (),
) -> Resource:
    """
    Create a child memory region that is mapped into this memory region.

    :param child_mr: the child memory region
    :param additional_attributes: additional attributes passed to the child memory region

    :raises OverlapError: if the child to be created overlaps with an existing child node
    :raises ValueError: if the child's end offset is larger than the memory region's size
    :return: the created child resource
    """
    start_offset = self.get_offset_in_self(child_mr.virtual_address)
    end_offset = start_offset + child_mr.size
    if start_offset < 0:
        raise ValueError(
            f"New child has vaddr {hex(child_mr.virtual_address)} which is before"
            f" the proposed parent's vaddr {hex(self.virtual_address)}"
        )
    if end_offset > self.size:
        raise ValueError(
            f"New child at {hex(child_mr.virtual_address)} is too large to fit in the proposed "
            f"parent - end vaddr {hex(child_mr.end_vaddr())} goes past the parent's end vaddr "
            f"{hex(self.end_vaddr())}."
        )

    try:
        return await self.resource.create_child_from_view(
            child_mr,
            data_range=Range(start_offset, end_offset),
            additional_attributes=additional_attributes,
        )
    except OverlapError as e:
        existing_child_vaddr = e.existing_child_node.model.range.start + self.virtual_address
        existing_child_size = e.existing_child_node.model.range.length()
        raise MemoryOverlapError(
            child_mr, MemoryRegion(existing_child_vaddr, existing_child_size)
        ) from e

get_mem_region_with_vaddr_from_sorted(vaddr, sorted_regions) staticmethod

Return the first memory region in the input iterable that contains vaddr.

Parameters:

Name Type Description Default
vaddr int

Virtual address

required
sorted_regions Iterable[MemoryRegion]

Sorted iterable of memory regions to check in order for vaddr

required

Returns:

Type Description

The first memory region in the sorted iterable containing vaddr

Exceptions:

Type Description
NotFoundError

If vaddr is not in any element of the iterable

Source code in ofrak/core/memory_region.py
@staticmethod
def get_mem_region_with_vaddr_from_sorted(vaddr: int, sorted_regions: Iterable["MemoryRegion"]):
    """
    Return the first [memory region][ofrak.core.memory_region.MemoryRegion] in the input
    iterable that contains vaddr.

    :param vaddr: Virtual address
    :param sorted_regions: Sorted iterable of memory regions to check in order for vaddr

    :raises NotFoundError: If vaddr is not in any element of the iterable

    :return: The first memory region in the sorted iterable containing vaddr
    """
    for mem_view in sorted_regions:
        # the first region we find should be the largest
        mem_region_vaddr_range = Range(
            mem_view.virtual_address,
            mem_view.virtual_address + mem_view.size,
        )
        if vaddr in mem_region_vaddr_range:
            return mem_view

    raise NotFoundError(f"Cannot find memory region matching {hex(vaddr)}")

__hash__(self) special

Return the hash of the virtual address and size.

Warning

Two memory regions may have the same hash, even if they refer to different data! As long as the address and size are the same, two regions will have the same hash, since the resource is not part of the data that is hashed. Be careful about comparing memory regions that refer to different data!

Source code in ofrak/core/memory_region.py
def __hash__(self):
    """
    Return the hash of the virtual address and size.

    !!! warning

        Two memory regions may have the same hash, even if they refer to different data! As
        long as the address and size are the same, two regions will have the same hash,
        since the resource is not part of the data that is hashed. Be careful about comparing
        memory regions that refer to different data!
    """
    return hash((self.virtual_address, self.size))