-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wrapper type for memory address #241
Comments
Almost any address can be valid - essentially the only completely forbidden addresses are in the lower 64KB of address space; probably not much point in introducing extra friction and making a newtype just to enforce that.
The address space is always 32-bit, even if the VM instance is 64-bit (in which case the upper 32-bits are simply ignored). (This is done for efficiency, as we have little need for huge amounts of memory, and capping the address space to 32-bit makes memory accesses from within the guest program more efficient.) |
But the pointers are still 64-bit inside VM itself, aren't they? |
Yes, technically they are because the registers are 64-bit, but the upper 32-bits are completely ignored when making memory accesses. |
That is still a bit confusing because when I allocate a few data structures in VM's memory before calling a function, I still have to convert those addresses VM gives me from And it would make code base more type safe if there was a new type instead of anonymous |
Funny anecdote regarding this. The RISC-V ABI demands that even unsigned integers are sign extended in order to fit into a register for calling a function (if they are of smaller size than a register). So if declare you a host function argument as uint32 and expect that it is zero extended to fit into the register you are in for a surprise. @aman4150 and @xermicus had a nice little debugging session to find this out. So tl;dr: It is important to actually ignore the higher bits of a pointer and don't assume they are zero. |
My plan was for host to allocate a data in a VM that looks roughly like this: struct Args {
ptr_1: *mut u8,
size_1: u32,
ptr_2: *mut u8,
size_2: u32,
} And then call a function that looks like this: #[no_mangle]
pub unsafe extern "C" fn foo(args: *mut Args) {
//
} And after return to inspect values behind those |
Right now memory addresses are represented by u32 (though maybe they shouldn't be), but not all addresses are actually usable.
It might be beneficial to create a new type that wraps the address value and enforces some invariants on it, like those mentioned in description of some functions:
polkavm/crates/polkavm/src/api.rs
Lines 1319 to 1326 in fa3478f
For example
sbrk
can return a proper address instance to begin with. Not entirely sure about all sources, but maybe it'll be possible to forbid direct casting ofu32
to address, helping to make invalid addresses impossible to construct.Similarly new type can be used to attach constants, again, like those shown above.
Essentially an type similar to
usize
but for VM's memory. Similarlylength
in many cases has similar constraints and could use a new type likeisize
.If machine supports 64-bit addresses then the instance can be parametrized by
const BITS: u8
and return/accept different address types.The text was updated successfully, but these errors were encountered: