Memory v0.1.0
ProtectionNone
pub const ProtectionNone: int32 = 0;
PROT_NONE: the pages may not be touched at all.
ProtectionRead
pub const ProtectionRead: int32 = 1;
PROT_READ: the pages may be read.
ProtectionWrite
pub const ProtectionWrite: int32 = 2;
PROT_WRITE: the pages may be written.
ProtectionExecute
pub const ProtectionExecute: int32 = 4;
PROT_EXEC: the pages may be executed.
MapShared
pub const MapShared: int32 = 1;
MAP_SHARED: writes are visible to other mappings of the same object and reach it.
MapPrivate
pub const MapPrivate: int32 = 2;
MAP_PRIVATE: writes are private to this mapping and never reach the object.
MapFixed
pub const MapFixed: int32 = 16;
MAP_FIXED: place the mapping exactly at the requested address, replacing whatever was there.
Dangerous by design: it silently unmaps anything already at the address, which may be someone else's mapping.
MapAnonymous
pub const MapAnonymous: int32 = 32;
MAP_ANONYMOUS: the mapping is backed by zeroed pages rather than by a file.
The descriptor argument is then unused and is conventionally -1.
Mmap
pub func Mmap(
address: *opaque,
length: uint,
protection: int32,
flags: int32,
fd: int32,
offset: uint64
) -> int64
Creates a mapping and returns its address, or a negative error number.
address is a hint unless MapFixed is set, and null asks the kernel to choose. length is rounded up to a
whole number of pages. fd is the object to map, or -1 with MapAnonymous. offset must be page-aligned.
Returns the mapping's address as an integer. Testing it needs Errors::IsError rather than a sign test: a valid
address may have its top bit set, and only the kernel's reserved -4095 through -1 range is a failure.
The mapping outlives nothing on its own — it stays until Munmap releases it or the process ends.
MapFixed replaces whatever occupies the address, including a mapping this program depends on.
Parameters
| Name | Type | Description |
|---|---|---|
address | *opaque | a hint for where to map, or null to let the kernel choose |
length | uint | how many bytes, rounded up to whole pages |
protection | int32 | what may be done with the pages, as Protection* flags |
flags | int32 | the mapping flags, as Map* values |
fd | int32 | the file to map, or -1 with MapAnonymous |
offset | uint64 | where in the file the mapping starts |
Returns: the mapping's address, or a negative error number
Munmap
pub func Munmap(address: *opaque, length: uint) -> int64
Releases the mapping that begins at address and spans length bytes.
address must be page-aligned; length is rounded up to whole pages. Returns zero, or a negative error number.
Releasing a range that was never mapped succeeds and does nothing, so this cannot be used to discover whether a
range was mapped.
Every pointer into the range becomes invalid, and the address space may be handed to a later mapping at once.
Parameters
| Name | Type | Description |
|---|---|---|
address | *opaque | a page-aligned address to release from |
length | uint | how many bytes to release |
Returns: zero, or a negative error number
Brk
pub func Brk(address: *opaque) -> int64
Sets the program break and returns where it ended up.
address is the requested new break, or null to ask where it is. Returns the resulting break, which is the old
one when the request could not be met — this call reports failure by not moving rather than by an error number.
The break is a single process-wide value. Anything else in the process that uses it, including a C runtime that
was linked in, is using the same one.
Parameters
| Name | Type | Description |
|---|---|---|
address | *opaque | where to move the program break, or null to read it |
Returns: the resulting break, or a negative error number
AdviseDontNeed
pub const AdviseDontNeed: int32 = 4;
MADV_DONTNEED: the pages are not needed, and the kernel may discard them.
An anonymous page discarded this way reads back as zero next time, which is how a range is released without
giving up the address space.
AdviseWillNeed
pub const AdviseWillNeed: int32 = 3;
MADV_WILLNEED: the pages will be read soon, so reading them ahead is worthwhile.
AdviseRandom
pub const AdviseRandom: int32 = 1;
MADV_RANDOM: the pages will be touched in no useful order, so reading ahead is not.
AdviseSequential
pub const AdviseSequential: int32 = 2;
MADV_SEQUENTIAL: the pages will be touched in order.
Mprotect
pub func Mprotect(
address: *opaque,
length: uint,
protection: int32
) -> int64
Changes what may be done with the pages covering address through address + length.
address must be page-aligned; length is rounded up to whole pages. protection is the same set Mmap takes.
Returns zero, or a negative error number.
Removing a permission takes effect at once, so a thread touching the range concurrently faults rather than
finishing what it started.
Nothing here checks that the range was ever mapped, and marking executable memory writable at the same time is
what a hardened system refuses.
Parameters
| Name | Type | Description |
|---|---|---|
address | *opaque | a page-aligned address |
length | uint | how many bytes, rounded up to whole pages |
protection | int32 | what may be done with them afterwards |
Returns: zero, or a negative error number
Madvise
pub func Madvise(
address: *opaque,
length: uint,
advice: int32
) -> int64
Tells the kernel how the pages covering a range are about to be used.
address must be page-aligned. Returns zero, or a negative error number. Advice is advice: the kernel is free to
ignore all of it, with the exception of AdviseDontNeed, which actually discards.
AdviseDontNeed loses whatever the range held. On anonymous memory that is a zeroing; on a private file mapping
it discards the modifications rather than writing them back.
Parameters
| Name | Type | Description |
|---|---|---|
address | *opaque | a page-aligned address |
length | uint | how many bytes the advice covers |
advice | int32 | one of the Advise* values |
Returns: zero, or a negative error number
AuxPageSize
pub const AuxPageSize: uint64 = 6;
AT_PAGESZ: the auxiliary-vector entry holding the page size, in bytes.
AuxNull
pub const AuxNull: uint64 = 0;
AT_NULL: the entry that ends the auxiliary vector.
QueryPageSize
pub func QueryPageSize() -> int64
The size of a page, read out of this process's auxiliary vector.
Linux publishes the page size in the auxiliary vector the kernel hands to a new process, not behind a system
call. libc captures that vector at startup and answers from it, which is what getauxval reads; this package
calls no libc and captures nothing at startup, so it asks the kernel for the same vector through the interface
that exposes it as a file, /proc/self/auxv. The file is a sequence of (type, value) pairs of unsigned
64-bit words, ending at a type of AuxNull.
The cost is an open, a read and a close, so a caller needing the size more than once should keep it rather than
ask again.
Reports the open's or the read's own error number when /proc is not mounted or not readable, which is
ordinary in a container built without it. Reports -ENOENT when the vector was readable but held no
AuxPageSize entry, and -EINVAL when it held one that is not a size the address space could have.
Returns: the page size in bytes, or a negative error number