xref: /drstd/src/std/sys/sgx/abi/mem.rs (revision 86982c5e9b2eaa583327251616ee822c36288824)
1 use core::arch::asm;
2 
3 // Do not remove inline: will result in relocation failure
4 #[inline(always)]
5 pub(crate) unsafe fn rel_ptr<T>(offset: u64) -> *const T {
6     (image_base() + offset) as *const T
7 }
8 
9 // Do not remove inline: will result in relocation failure
10 #[inline(always)]
11 pub(crate) unsafe fn rel_ptr_mut<T>(offset: u64) -> *mut T {
12     (image_base() + offset) as *mut T
13 }
14 
15 extern "C" {
16     static ENCLAVE_SIZE: usize;
17     static HEAP_BASE: u64;
18     static HEAP_SIZE: usize;
19 }
20 
21 /// Returns the base memory address of the heap
22 pub(crate) fn heap_base() -> *const u8 {
23     unsafe { rel_ptr_mut(HEAP_BASE) }
24 }
25 
26 /// Returns the size of the heap
27 pub(crate) fn heap_size() -> usize {
28     unsafe { HEAP_SIZE }
29 }
30 
31 // Do not remove inline: will result in relocation failure
32 // For the same reason we use inline ASM here instead of an extern static to
33 // locate the base
34 /// Returns address at which current enclave is loaded.
35 #[inline(always)]
36 pub fn image_base() -> u64 {
37     let base: u64;
38     unsafe {
39         asm!(
40             "lea IMAGE_BASE(%rip), {}",
41             lateout(reg) base,
42             options(att_syntax, nostack, preserves_flags, nomem, pure),
43         )
44     };
45     base
46 }
47 
48 /// Returns `true` if the specified memory range is in the enclave.
49 ///
50 /// For safety, this function also checks whether the range given overflows,
51 /// returning `false` if so.
52 pub fn is_enclave_range(p: *const u8, len: usize) -> bool {
53     let start = p as usize;
54 
55     // Subtract one from `len` when calculating `end` in case `p + len` is
56     // exactly at the end of addressable memory (`p + len` would overflow, but
57     // the range is still valid).
58     let end = if len == 0 {
59         start
60     } else if let Some(end) = start.checked_add(len - 1) {
61         end
62     } else {
63         return false;
64     };
65 
66     let base = image_base() as usize;
67     start >= base && end <= base + (unsafe { ENCLAVE_SIZE } - 1) // unsafe ok: link-time constant
68 }
69 
70 /// Returns `true` if the specified memory range is in userspace.
71 ///
72 /// For safety, this function also checks whether the range given overflows,
73 /// returning `false` if so.
74 pub fn is_user_range(p: *const u8, len: usize) -> bool {
75     let start = p as usize;
76 
77     // Subtract one from `len` when calculating `end` in case `p + len` is
78     // exactly at the end of addressable memory (`p + len` would overflow, but
79     // the range is still valid).
80     let end = if len == 0 {
81         start
82     } else if let Some(end) = start.checked_add(len - 1) {
83         end
84     } else {
85         return false;
86     };
87 
88     let base = image_base() as usize;
89     end < base || start > base + (unsafe { ENCLAVE_SIZE } - 1) // unsafe ok: link-time constant
90 }
91