2

If I have a struct, for example:

#[derive(Clone, Copy)] #[repr(C, packed)] pub struct SomeData { a: u16, b: u64, c: u32, d: u16, } 

How do I copy it to a specific location in memory, e.g. to a point 0x1000 in memory efficiently? Would something like this work?

let dst_addr: u64 = 0x1000; let src = SomeData {a: 1, b: 2, c: 3, d: 4}; unsafe { let tmp: &[u8; 10] = transmute(src); copy(dst_addr as *mut _, tmp); } 

Please note that the repr(C, packed) part is actually needed here.

The software is running on bare x86_64, ring 0, without operating system or other limitations. Also, I'm programming without the standard library, so this should be achievable with only the core library.

This is, of course, unsafe, but it is not a problem.

Edit: Just clarifying: I'm copying to uninitialized memory.

5
  • 1
    There are a handful of great tutorials about writing your own kernel including Writing an OS in Rust in tiny steps by Julia Evans and Writing an OS in Rust by Philipp Oppermann and at least two larger projects: Intermezzos and Redox. Commented Jul 15, 2016 at 17:22
  • @Shepmaster Yep, I have read both. I was just wondering what is the "proper" way to do this, as tutorials don't always get it right, and if there was some great "tricks" I wasn't aware of. Commented Jul 15, 2016 at 17:25
  • I think those tutorials get read over thoroughly by the community when they are posted to the subreddit or user's forum, or even Hacker News. I'd expect them to be pretty well reviewed. Commented Jul 15, 2016 at 17:36
  • As a pedantic point, I think usize might be slightly better than u64 if it's to hold a pointer. On the other hand it looks like you're doing something very specific to one system! Commented Jul 16, 2016 at 8:15
  • @ChrisEmerson Yep, it's actually converted from usize, just because the pointer is actually used after this for things where it must be exactly 64bits. Commented Jul 16, 2016 at 10:24

1 Answer 1

7

You will want to have a look at the core::ptr module.

Its write function does exactly what you wish:

pub unsafe fn write<T>(dst: *mut T, src: T) 
core::ptr::write(dst_addr as *mut_, src); 

As noted, it does not drop the value current at dst_addr (you can use read to do so).

I advise against using intrinsics::copy_nonoverlapping as intrinsics will never be stabilized.

Sign up to request clarification or add additional context in comments.

1 Comment

It worked => accepted! Had to use ptr::write(dst_addr as *mut SomeData, *self); because I was doing this inside a SomeDatas method.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.