Heaps

A Heap is a specialized Memory object that represents a dynamically-allocated region of memory.

A Heap can be manipulated by allocation. It can take a raw Value using Heap.allocate(), or a primitive type using Heap.allocate_integer(), Heap.allocate_bytes(), or Heap.allocate_ctype().

The interface also supports freeing an allocation using Heap.free(), although this doesn’t have an impact on all implementations.

Heap itself is an abstract class. SmallWorld currently provides BumpAllocator, which is a simple linear allocator with no free support, and CheckedBumpAllocator, which adds invalid access detection.

The following is an example of using a Heap to store data passed into the harness by reference:

from smallworld.platforms import Architecture, Byteorder, Platform
from smallworld.state import Machine
from smallworld.state.cpus import CPU
from smallworld.state.memory.code import Executable
from smallworld.state.memory.heap import BumpAllocator
from smallworld.state.memory.heap import Stack

# Define the platform
platform = Platform(Architecture.X86_64, Byteorder.LITTLE)

# Create the machine
machine = Machine()

# Create the CPU
cpu = CPU.for_platform(platform)
machine.add(cpu)

# Load some code.
# Assume this is an ELF that defines a function
# void needs_memory(int -arg);
bin_path = "/path/to/fake.elf"
with open(filename, "rb") as f:
    code = Executable.from_elf(bin_path, address=0x40000000, platform=platform)
    machine.add(code)

# Transfer bounds from code to machine.
for bound in code.bounds:
    machine.add_bound(bound[0], bound[1])

# Set the entrypoint to needs_memory()
entrypoint = code.get_symbol_value('needs_memory')
cpu.rip.set(entrypoint)

# Create a heap
heap = BumpAllocator(0x2000, 0x1000)
machine.add(heap)

# Allocate an integer argument on the heap
arg_address = heap.allocate_integer(42, 4, None, smallworld.platforms.Byteorder.LITTLE)

# Create a stack
stack = Stack.for_platform(platform)
machine.add(stack)

# Push a fake return address onto the stack
stack.push_integer(0x10101010, 8, None)
machine.add_exit_point(0x10101010)

# Configure the stack pointer
sp = stack.get_pointer()
cpu.rsp.set(sp)

# Configure the argument to the target function
cpu.rdi.set(arg_address)

# Emulate
emulator = UnicornEmulator(platform)
final_machine = machine.emulate(emulator)