Module refinery.lib.scripts.xlm.memory
The emulated state the system commands of the macro language touch: the files FOPEN opens and
FWRITE appends to, and the memory regions the Kernel32 pseudo-commands reserve and write.
Expand source code Browse git
"""
The emulated state the system commands of the macro language touch: the files `FOPEN` opens and
`FWRITE` appends to, and the memory regions the Kernel32 pseudo-commands reserve and write.
"""
from __future__ import annotations
from dataclasses import dataclass, field
_PAGE = 4096
@dataclass
class XlmFile:
"""
One file the program opened: the access it was opened with and the content the program
has written into it.
"""
access: str
content: str = ''
@dataclass
class XlmRegion:
"""
One region of the memory of the emulated process, as a flat byte array an address names a
cell of.
"""
base: int
size: int
data: bytearray = field(init=False)
def __post_init__(self):
self.data = bytearray(self.size)
class XlmFiles:
"""
The files a program opens: the name each was opened under, the access it was opened with,
and the content the program has written into it. A file the program never opened refuses
every write, the way a handle that does not exist refuses one.
"""
def __init__(self):
self._files: dict[str, XlmFile] = {}
def opened(self, name: str) -> bool:
"""
Whether the name answers a file the program opened.
"""
return name in self._files
def open(self, name: str, access: str = '1') -> None:
"""
Open the name, or leave the file that already answers it alone.
"""
self._files.setdefault(name, XlmFile(access))
def close(self, name: str) -> None:
"""
Remove a file the program opened, as the undo of an open performs.
"""
self._files.pop(name, None)
def first(self) -> str:
"""
The name of the first file the program opened, for a write that names none: the name of
the only file a program that opened one means, and a placeholder when it opened none.
"""
for name in self._files:
return name
return 'default_filename'
def size(self, name: str) -> int | None:
"""
The length of the content of a file, or `None` for a name the program never opened.
"""
file = self._files.get(name)
if file is None:
return None
return len(file.content)
def write(self, name: str, text: str) -> bool:
"""
Append to a file the program opened, reporting whether it took the write.
"""
file = self._files.get(name)
if file is None:
return False
file.content += text
return True
def truncate(self, name: str, length: int) -> None:
"""
Cut the content of a file back to the length it had, as the undo of a write performs.
"""
file = self._files.get(name)
if file is not None:
file.content = file.content[:length]
def snapshot(self) -> tuple[tuple[str, str], ...]:
"""
The content of every file the program opened, by the name each answers to, as the state
a comparison of the run observes.
"""
return tuple(
(name, self._files[name].content)
for name in sorted(self._files)
)
class XlmMemory:
"""
The memory of the emulated process: the regions `Kernel32.VirtualAlloc` reserves, as flat
byte arrays an address names a cell of.
"""
def __init__(self):
self._regions: list[XlmRegion] = []
def allocate(self, base: int, size: int) -> int:
"""
Reserve a region at an address, and answer the address it starts at: an address that
falls inside a reserved region moves the reservation past the end of every reserved
region, one page above the highest end.
"""
for region in self._regions:
if region.base <= base <= region.base + region.size:
base = max(
region.base + region.size
for region in self._regions
) + _PAGE
break
self._regions.append(XlmRegion(base, size))
return base
def release(self) -> None:
"""
Drop the region the latest allocation reserved, as the undo of an allocation performs.
"""
if self._regions:
self._regions.pop()
def write(self, base: int, data: bytes | bytearray, size: int) -> bool:
"""
Write at most the given count of bytes at an address, reporting whether the whole slice
fits inside one reserved region; a slice that straddles a region boundary or counts
fewer than zero bytes is not written at all, and a region keeps its length.
"""
if size < 0:
return False
for region in self._regions:
if not region.base <= base <= region.base + region.size:
continue
if not region.base <= base + size <= region.base + region.size:
return False
offset = base - region.base
chunk = data[:size]
region.data[offset:offset + len(chunk)] = chunk
return True
return False
def peek(self, base: int, size: int) -> bytes | None:
"""
The bytes a region holds at an address, or `None` when the slice counts fewer than zero
bytes or does not fit inside one reserved region.
"""
if size < 0:
return None
for region in self._regions:
if not region.base <= base <= region.base + region.size:
continue
if not region.base <= base + size <= region.base + region.size:
return None
offset = base - region.base
return bytes(region.data[offset:offset + size])
return None
def restore(self, base: int, data: bytes) -> None:
"""
Write earlier content back at an address, as the undo of a write performs.
"""
for region in self._regions:
if region.base <= base <= region.base + region.size:
offset = base - region.base
region.data[offset:offset + len(data)] = data
return
def snapshot(self) -> tuple[tuple[int, bytes], ...]:
"""
The bytes of every region the program reserved, by the address each starts at, as the
state a comparison of the run observes.
"""
return tuple(
(region.base, bytes(region.data))
for region in sorted(self._regions, key=lambda region: region.base)
)
Classes
class XlmFile (access, content='')-
One file the program opened: the access it was opened with and the content the program has written into it.
Expand source code Browse git
@dataclass class XlmFile: """ One file the program opened: the access it was opened with and the content the program has written into it. """ access: str content: str = ''Instance variables
var access-
The type of the None singleton.
var content-
The type of the None singleton.
class XlmRegion (base, size)-
One region of the memory of the emulated process, as a flat byte array an address names a cell of.
Expand source code Browse git
@dataclass class XlmRegion: """ One region of the memory of the emulated process, as a flat byte array an address names a cell of. """ base: int size: int data: bytearray = field(init=False) def __post_init__(self): self.data = bytearray(self.size)Instance variables
var base-
The type of the None singleton.
var size-
The type of the None singleton.
var data-
The type of the None singleton.
class XlmFiles-
The files a program opens: the name each was opened under, the access it was opened with, and the content the program has written into it. A file the program never opened refuses every write, the way a handle that does not exist refuses one.
Expand source code Browse git
class XlmFiles: """ The files a program opens: the name each was opened under, the access it was opened with, and the content the program has written into it. A file the program never opened refuses every write, the way a handle that does not exist refuses one. """ def __init__(self): self._files: dict[str, XlmFile] = {} def opened(self, name: str) -> bool: """ Whether the name answers a file the program opened. """ return name in self._files def open(self, name: str, access: str = '1') -> None: """ Open the name, or leave the file that already answers it alone. """ self._files.setdefault(name, XlmFile(access)) def close(self, name: str) -> None: """ Remove a file the program opened, as the undo of an open performs. """ self._files.pop(name, None) def first(self) -> str: """ The name of the first file the program opened, for a write that names none: the name of the only file a program that opened one means, and a placeholder when it opened none. """ for name in self._files: return name return 'default_filename' def size(self, name: str) -> int | None: """ The length of the content of a file, or `None` for a name the program never opened. """ file = self._files.get(name) if file is None: return None return len(file.content) def write(self, name: str, text: str) -> bool: """ Append to a file the program opened, reporting whether it took the write. """ file = self._files.get(name) if file is None: return False file.content += text return True def truncate(self, name: str, length: int) -> None: """ Cut the content of a file back to the length it had, as the undo of a write performs. """ file = self._files.get(name) if file is not None: file.content = file.content[:length] def snapshot(self) -> tuple[tuple[str, str], ...]: """ The content of every file the program opened, by the name each answers to, as the state a comparison of the run observes. """ return tuple( (name, self._files[name].content) for name in sorted(self._files) )Methods
def opened(self, name)-
Whether the name answers a file the program opened.
Expand source code Browse git
def opened(self, name: str) -> bool: """ Whether the name answers a file the program opened. """ return name in self._files def open(self, name, access='1')-
Open the name, or leave the file that already answers it alone.
Expand source code Browse git
def open(self, name: str, access: str = '1') -> None: """ Open the name, or leave the file that already answers it alone. """ self._files.setdefault(name, XlmFile(access)) def close(self, name)-
Remove a file the program opened, as the undo of an open performs.
Expand source code Browse git
def close(self, name: str) -> None: """ Remove a file the program opened, as the undo of an open performs. """ self._files.pop(name, None) def first(self)-
The name of the first file the program opened, for a write that names none: the name of the only file a program that opened one means, and a placeholder when it opened none.
Expand source code Browse git
def first(self) -> str: """ The name of the first file the program opened, for a write that names none: the name of the only file a program that opened one means, and a placeholder when it opened none. """ for name in self._files: return name return 'default_filename' def size(self, name)-
The length of the content of a file, or
Nonefor a name the program never opened.Expand source code Browse git
def size(self, name: str) -> int | None: """ The length of the content of a file, or `None` for a name the program never opened. """ file = self._files.get(name) if file is None: return None return len(file.content) def write(self, name, text)-
Append to a file the program opened, reporting whether it took the write.
Expand source code Browse git
def write(self, name: str, text: str) -> bool: """ Append to a file the program opened, reporting whether it took the write. """ file = self._files.get(name) if file is None: return False file.content += text return True def truncate(self, name, length)-
Cut the content of a file back to the length it had, as the undo of a write performs.
Expand source code Browse git
def truncate(self, name: str, length: int) -> None: """ Cut the content of a file back to the length it had, as the undo of a write performs. """ file = self._files.get(name) if file is not None: file.content = file.content[:length] def snapshot(self)-
The content of every file the program opened, by the name each answers to, as the state a comparison of the run observes.
Expand source code Browse git
def snapshot(self) -> tuple[tuple[str, str], ...]: """ The content of every file the program opened, by the name each answers to, as the state a comparison of the run observes. """ return tuple( (name, self._files[name].content) for name in sorted(self._files) )
class XlmMemory-
The memory of the emulated process: the regions
Kernel32.VirtualAllocreserves, as flat byte arrays an address names a cell of.Expand source code Browse git
class XlmMemory: """ The memory of the emulated process: the regions `Kernel32.VirtualAlloc` reserves, as flat byte arrays an address names a cell of. """ def __init__(self): self._regions: list[XlmRegion] = [] def allocate(self, base: int, size: int) -> int: """ Reserve a region at an address, and answer the address it starts at: an address that falls inside a reserved region moves the reservation past the end of every reserved region, one page above the highest end. """ for region in self._regions: if region.base <= base <= region.base + region.size: base = max( region.base + region.size for region in self._regions ) + _PAGE break self._regions.append(XlmRegion(base, size)) return base def release(self) -> None: """ Drop the region the latest allocation reserved, as the undo of an allocation performs. """ if self._regions: self._regions.pop() def write(self, base: int, data: bytes | bytearray, size: int) -> bool: """ Write at most the given count of bytes at an address, reporting whether the whole slice fits inside one reserved region; a slice that straddles a region boundary or counts fewer than zero bytes is not written at all, and a region keeps its length. """ if size < 0: return False for region in self._regions: if not region.base <= base <= region.base + region.size: continue if not region.base <= base + size <= region.base + region.size: return False offset = base - region.base chunk = data[:size] region.data[offset:offset + len(chunk)] = chunk return True return False def peek(self, base: int, size: int) -> bytes | None: """ The bytes a region holds at an address, or `None` when the slice counts fewer than zero bytes or does not fit inside one reserved region. """ if size < 0: return None for region in self._regions: if not region.base <= base <= region.base + region.size: continue if not region.base <= base + size <= region.base + region.size: return None offset = base - region.base return bytes(region.data[offset:offset + size]) return None def restore(self, base: int, data: bytes) -> None: """ Write earlier content back at an address, as the undo of a write performs. """ for region in self._regions: if region.base <= base <= region.base + region.size: offset = base - region.base region.data[offset:offset + len(data)] = data return def snapshot(self) -> tuple[tuple[int, bytes], ...]: """ The bytes of every region the program reserved, by the address each starts at, as the state a comparison of the run observes. """ return tuple( (region.base, bytes(region.data)) for region in sorted(self._regions, key=lambda region: region.base) )Methods
def allocate(self, base, size)-
Reserve a region at an address, and answer the address it starts at: an address that falls inside a reserved region moves the reservation past the end of every reserved region, one page above the highest end.
Expand source code Browse git
def allocate(self, base: int, size: int) -> int: """ Reserve a region at an address, and answer the address it starts at: an address that falls inside a reserved region moves the reservation past the end of every reserved region, one page above the highest end. """ for region in self._regions: if region.base <= base <= region.base + region.size: base = max( region.base + region.size for region in self._regions ) + _PAGE break self._regions.append(XlmRegion(base, size)) return base def release(self)-
Drop the region the latest allocation reserved, as the undo of an allocation performs.
Expand source code Browse git
def release(self) -> None: """ Drop the region the latest allocation reserved, as the undo of an allocation performs. """ if self._regions: self._regions.pop() def write(self, base, data, size)-
Write at most the given count of bytes at an address, reporting whether the whole slice fits inside one reserved region; a slice that straddles a region boundary or counts fewer than zero bytes is not written at all, and a region keeps its length.
Expand source code Browse git
def write(self, base: int, data: bytes | bytearray, size: int) -> bool: """ Write at most the given count of bytes at an address, reporting whether the whole slice fits inside one reserved region; a slice that straddles a region boundary or counts fewer than zero bytes is not written at all, and a region keeps its length. """ if size < 0: return False for region in self._regions: if not region.base <= base <= region.base + region.size: continue if not region.base <= base + size <= region.base + region.size: return False offset = base - region.base chunk = data[:size] region.data[offset:offset + len(chunk)] = chunk return True return False def peek(self, base, size)-
The bytes a region holds at an address, or
Nonewhen the slice counts fewer than zero bytes or does not fit inside one reserved region.Expand source code Browse git
def peek(self, base: int, size: int) -> bytes | None: """ The bytes a region holds at an address, or `None` when the slice counts fewer than zero bytes or does not fit inside one reserved region. """ if size < 0: return None for region in self._regions: if not region.base <= base <= region.base + region.size: continue if not region.base <= base + size <= region.base + region.size: return None offset = base - region.base return bytes(region.data[offset:offset + size]) return None def restore(self, base, data)-
Write earlier content back at an address, as the undo of a write performs.
Expand source code Browse git
def restore(self, base: int, data: bytes) -> None: """ Write earlier content back at an address, as the undo of a write performs. """ for region in self._regions: if region.base <= base <= region.base + region.size: offset = base - region.base region.data[offset:offset + len(data)] = data return def snapshot(self)-
The bytes of every region the program reserved, by the address each starts at, as the state a comparison of the run observes.
Expand source code Browse git
def snapshot(self) -> tuple[tuple[int, bytes], ...]: """ The bytes of every region the program reserved, by the address each starts at, as the state a comparison of the run observes. """ return tuple( (region.base, bytes(region.data)) for region in sorted(self._regions, key=lambda region: region.base) )