The CPU Object

SmallWorld’s CPU objects are responsible for storing register state. Harnesses specify an initial CPU when building out a Machine, and can access the CPU in an extracted Machine to read back the current register state.

CPUs are platform-specific, as each platform has its own set of registers.

Registers are exposed as properties of a CPU object for ease of access.

Note

Currently, SmallWorld only allows a single CPU object per machine. Currently, only Ghidra has meaningful multi-threaded support, and it’s not exposed through SmallWorld.

Registers

A Register represents a specific CPU register, such as rdi, and specifies its name and its width in bytes.

A Register’s contents can be accessed using Register.get() or Register.set().

A Register starts with no contents. Concrete emulators will interpret this as a value of zero, while symbolic executors will interpret this as uninitialized data.

A Register’s contents can be an integer, or a Claripy symbolic expression if it will be used with a symbolic executor.

Caution

Using a harness with symbolic values to populate a concrete emulator will raise an exception.

A Register’s label can be accessed using Register.get_label() and Register.set_label(). See Values in Smallworld for more about how labels work.

The following is an example of setting the contents on a Register

from smallworld.state import CPU
from smallworld.platforms import Architecture, Byteorder, Platform

platform = Platform(Architecture.X86_64, Byteorder.LITTLE)
cpu = CPU.for_platform(platform)

cpu.rax.set(0x1337d00d)
print(cpu.rax)  # (rax,8)=0x1337d00d

Register Aliases

A RegisterAlias represents a named portion of a register. For example, edi is an alias for the low four bytes of rdi.

A RegisterAlias specifies its name, its parent Register, its offset in bytes into the parent register, and its size.

Accessing the contents of a RegisterAlias will transparently access the parent Register object.

Accessing a label on a RegisterAlias will access the label for the entire parent Register; there is no way to specify a partial label on a Register.

The following is an example of setting the contents on a Register and an associated RegisterAlias

from smallworld.state import CPU
from smallworld.platforms import Architecture, Byteorder, Platform

# Create a CPU
platform = Platform(Architecture.X86_64, Byteorder.LITTLE)
cpu = CPU.for_platform(platform)

# Set and check the parent register
cpu.rax.set(0x1337d00d)
print(cpu.rax)  # (rax,8)=0x1337d00d

# Set the register alias
# The parent should be partially rewritten
cpu.ax.set(0xcafe)
print(cpu.rax)  # (rax,8)=0x1337cafe
print(cpu.ax)   # (ax,2)=0xcafe

# Set the parent
# The register alias should change
cpu.rax.set(0xdeadbeef)
print(cpu.rax)  # (rax,8)=0xdeadbeef
print(cpu.ax)   # (ax,2)=0xbeef

Fixed Registers

A FixedRegister represents a register that’s fixed to a specific value. This helps model platforms with “zero” registers, or platforms where certain registers must be initialized to specific values.

A FixedRegister works exactly like a Register, except it can only contain a single value. It can be aliased as normal.

Attempts to set the register’s contents or label will fail.