Memory API
Memory API
Architectural Stack (ql.arch)
1value = ql.arch.stack_pop() # pop value, adjust SP
2ql.arch.stack_push(value) # push value, adjust SP
3value = ql.arch.stack_read(offset) # peek at offset from top (no SP change)
4ql.arch.stack_write(offset, value) # replace at offset from top (no SP change)
Offset may be positive, negative, or zero (zero = top of stack).
Memory Management (ql.mem)
| Method | Description |
|---|---|
map(addr, size, perms, info) | Map a region; must be page-aligned |
unmap(addr, size) | Reclaim a mapped region (supports partial ranges) |
unmap_all() | Reclaim all mapped regions |
map_anywhere(size) | Map at an unspecified location |
protect(addr, size, perms) | Modify rwx protection bits |
find_free_space(size) | Find available region of given size |
is_available(addr, size) | True if region is entirely unmapped |
is_mapped(addr, size) | True if region is entirely mapped |
Note: is_available and is_mapped are not inverses — a partially mapped region returns False for both.
map
1ql.mem.map(addr: int, size: int, perms: int = UC_PROT_ALL, info: Optional[str] = None) -> None
addr: page-aligned base addresssize: multiple of page sizeperms:UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXECbitmaskinfo: optional label forget_map_info()display
Raises QlMemoryMappedError if range is not entirely available.
unmap
1ql.mem.unmap(addr: int, size: int) -> None
Raises QlMemoryMappedError if range is not entirely mapped.
Reading Memory
Memory protections do not apply to Qiling itself — all mapped memory is readable by the emulator regardless of page permissions.
Read bytes
1ql.mem.read(addr: int, size: int) -> bytearray
Raises UcError if range is not entirely mapped.
Read integer
1ql.mem.read_ptr(addr: int, size: int = 0, *, signed: bool = False) -> int
size: 1, 2, 4, or 8 bytes; defaults to arch native pointer sizesigned: interpret as signed integer
Writing Memory
All mapped memory is writable by the emulator regardless of page permissions.
Write bytes
1ql.mem.write(addr: int, data: bytes) -> None
Write integer
1ql.mem.write_ptr(addr: int, value: int, size: int = 0, *, signed: bool = False) -> None
size: 1, 2, 4, or 8 bytes; defaults to arch native pointer size
Searching Memory
1ql.mem.search(
2 needle: Union[bytes, Pattern[bytes]],
3 begin: Optional[int] = None,
4 end: Optional[int] = None
5) -> List[int]
needle: exact bytes or compiled regex patternbegin/end: search range; defaults to full mapped address space- Returns list of matching addresses (empty if no matches)
- MMIO regions are excluded to avoid side effects
Alignment Utilities
Align down (to page boundary)
1ql.mem.align(value: int, alignment: Optional[int] = None) -> int
Returns value rounded down to alignment (default: native page size). Used to find enclosing page base.
Align up
1ql.mem.align_up(value: int, alignment: Optional[int] = None) -> int
Returns value rounded up to alignment (default: native page size). Used to find enclosing page end.
Both methods require alignment to be a power of 2.