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
+u12
is 2 byteslittle-endian
u15
+u17
is 4 byteslittle-endian
u26
+u22
+u16
is 8 byteslittle-endian
u6
+u11
+u17
is 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.