Memory v0.1.0

Source
Mapping, protecting and advising on pages of memory.

ProtectionNone

pub const ProtectionNone: int32 = 0;

PROT_NONE: the pages may not be touched at all.

Source

ProtectionRead

pub const ProtectionRead: int32 = 1;

PROT_READ: the pages may be read.

Source

ProtectionWrite

pub const ProtectionWrite: int32 = 2;

PROT_WRITE: the pages may be written.

Source

ProtectionExecute

pub const ProtectionExecute: int32 = 4;

PROT_EXEC: the pages may be executed.

Source

MapShared

pub const MapShared: int32 = 1;

MAP_SHARED: writes are visible to other mappings of the same object and reach it.

Source

MapPrivate

pub const MapPrivate: int32 = 2;

MAP_PRIVATE: writes are private to this mapping and never reach the object.

Source

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.

Source

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.

Source

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.

Source

Parameters

NameTypeDescription
address*opaquea hint for where to map, or null to let the kernel choose
lengthuinthow many bytes, rounded up to whole pages
protectionint32what may be done with the pages, as Protection* flags
flagsint32the mapping flags, as Map* values
fdint32the file to map, or -1 with MapAnonymous
offsetuint64where 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.

Source

Parameters

NameTypeDescription
address*opaquea page-aligned address to release from
lengthuinthow 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.

Source

Parameters

NameTypeDescription
address*opaquewhere 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.

Source

AdviseWillNeed

pub const AdviseWillNeed: int32 = 3;

MADV_WILLNEED: the pages will be read soon, so reading them ahead is worthwhile.

Source

AdviseRandom

pub const AdviseRandom: int32 = 1;

MADV_RANDOM: the pages will be touched in no useful order, so reading ahead is not.

Source

AdviseSequential

pub const AdviseSequential: int32 = 2;

MADV_SEQUENTIAL: the pages will be touched in order.

Source

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.

Source

Parameters

NameTypeDescription
address*opaquea page-aligned address
lengthuinthow many bytes, rounded up to whole pages
protectionint32what 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.

Source

Parameters

NameTypeDescription
address*opaquea page-aligned address
lengthuinthow many bytes the advice covers
adviceint32one 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.

Source

AuxNull

pub const AuxNull: uint64 = 0;

AT_NULL: the entry that ends the auxiliary vector.

Source

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.

Source

Returns: the page size in bytes, or a negative error number