Buffers Specification
Version 1.0.0 (Library Version 3.0.0+)
Reloaded.Memory.Buffers is a library for allocating memory between a given minimum and maximum memory address
With the following properties:
- Memory Efficient: No wasted memory.
- Shared: Can be found and read/written to by multiple users.
- Static: Allocated data never moves, or is overwritten.
- Permanent: Allocated data lasts the lifetime of the process.
- Concurrent: Multiple users can access at the same time.
- Large Address Aware: On Windows, the library can correctly leverage all 4GB in 32-bit processes.
Use Cases
These are just examples.
- Hooks: Hooking libraries like Reloaded.Hooks can reduce amount of bytes stolen from functions.
- Libraries: Libraries like Reloaded.Assembler require memory be allocated in first 2GB.
And some other useful functionality.
Field Sizes
Field sizes used used in this spec are based on Rust notation; with some custom types e.g.
u8: Unsigned 8 bits.i8: Signed 8 bits.u4: 4 bits.u32/u64: 4 Bytes or 8 Bytes (depending on variant).
Assume any bit packed values are sequential, i.e. if u4 then u4 is specified, first u4 is the upper 4 bits.
All packed fields are little-endian; and written out when total number of bits aligns with a power of 2.
u6+u12is 2 byteslittle-endianu15+u17is 4 byteslittle-endianu26+u22+u16is 8 byteslittle-endianu6+u11+u17is 4 byteslittle-endian, not 2+2
General Access Pattern
Names below are not final API, only for illustration purposes.
flowchart TB
User["User"] --> GetOrAllocateBuffer(["Buffers.GetBuffer"])
GetOrAllocateBuffer --> BufferLocatorFind(["LocatorHeaderFinder.Find"])
BufferLocatorFind -- "(Via Memory Mapped Files)" --> GetAvailableItem(["LocatorHeader.GetFirstAvailableItem(locator)"])
GetAvailableItem --> BufferMatch{Buffer Match Found?}
BufferMatch -- Yes --> ReturnBufferToUser["Lock & Return Buffer to User"]
BufferMatch -- "No (Make New Buffer)" --> CanRegisterBuffer{Locator Has Space for New Entry?}
CanRegisterBuffer -- "No (Alloc New Locator, Link via Pointer & Try Again)" --> GetAvailableItem
CanRegisterBuffer -- "Yes (Allocate Memory and Register)" --> BufferAllocator(["BufferAllocator.Allocate"])
BufferAllocator -- "Lock & Register Returned Buffer" --> BufferLocatorRegister(["LocatorHeader.Register"])
BufferLocatorRegister --> ReturnNewBufferToUser["Return New Buffer to User"]
In the flowchart above, the user calls GetBuffer, which in turn calls LocatorHeaderFinder.Find to get address of the
locator structure.
If a match is found (Yes path), the buffer is locked and then returned to the user.
If no match is found (No path), a new buffer is allocated, and locked. If this buffer can fit into the current locator, it is appended. Otherwise a new locator is allocated (linked via pointer), and the buffer is registered into the new locator. Buffer is then returned to the user.