Skip to content
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

Adding unwinding support for x86_64_fortanix_unknown_sgx target. #56979

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/libpanic_unwind/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ cfg_if! {
if #[cfg(target_os = "emscripten")] {
#[path = "emcc.rs"]
mod imp;
} else if #[cfg(any(target_arch = "wasm32", target_env = "sgx"))] {
} else if #[cfg(target_arch = "wasm32")] {
#[path = "dummy.rs"]
mod imp;
} else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] {
Expand Down
46 changes: 27 additions & 19 deletions src/librustc_target/spec/x86_64_fortanix_unknown_sgx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,29 @@

use std::iter;

use super::{LinkerFlavor, Target, TargetOptions, PanicStrategy};
use super::{LinkerFlavor, PanicStrategy, Target, TargetOptions};

pub fn target() -> Result<Target, String> {
const PRE_LINK_ARGS: &[&str] = &[
"-Wl,--as-needed",
"-Wl,-z,noexecstack",
"-m64",
"-fuse-ld=gold",
"-nostdlib",
"-shared",
"-Wl,-e,sgx_entry",
"-Wl,-Bstatic",
"-Wl,--gc-sections",
"-Wl,-z,text",
"-Wl,-z,norelro",
"-Wl,--rosegment",
"-Wl,--no-undefined",
"-Wl,--error-unresolved-symbols",
"-Wl,--no-undefined-version",
"-Wl,-Bsymbolic",
"-Wl,--export-dynamic",
"-fuse-ld=gold",
"-nostdlib",
"-shared",
"-Wl,-e,sgx_entry",
"-Wl,-Bstatic",
"-Wl,--gc-sections",
"-Wl,-z,text",
"-Wl,-z,norelro",
"-Wl,--rosegment",
"-Wl,--no-undefined",
"-Wl,--error-unresolved-symbols",
"-Wl,--no-undefined-version",
"-Wl,-Bsymbolic",
"-Wl,--export-dynamic",
];

const EXPORT_SYMBOLS: &[&str] = &[
"sgx_entry",
"HEAP_BASE",
Expand All @@ -41,19 +42,26 @@ pub fn target() -> Result<Target, String> {
"ENCLAVE_SIZE",
"CFGDATA_BASE",
"DEBUG",
"EH_FRM_HDR_BASE",
"EH_FRM_HDR_SIZE",
"TEXT_BASE",
"TEXT_SIZE",
];
let opts = TargetOptions {
dynamic_linking: false,
executables: true,
linker_is_gnu: true,
max_atomic_width: Some(64),
panic_strategy: PanicStrategy::Abort,
panic_strategy: PanicStrategy::Unwind,
cpu: "x86-64".into(),
features: "+rdrnd,+rdseed".into(),
position_independent_executables: true,
pre_link_args: iter::once(
(LinkerFlavor::Gcc, PRE_LINK_ARGS.iter().cloned().map(String::from).collect())
).collect(),
pre_link_args: iter::once((
LinkerFlavor::Gcc,
PRE_LINK_ARGS.iter().cloned().map(String::from).collect(),
))
.collect(),
post_link_objects: vec!["libunwind.a".into()],
override_export_symbols: Some(EXPORT_SYMBOLS.iter().cloned().map(String::from).collect()),
..Default::default()
};
Expand Down
8 changes: 8 additions & 0 deletions src/libstd/sys/sgx/abi/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ IMAGE_BASE:
globvar CFGDATA_BASE 8
/* Non-zero if debugging is enabled, zero otherwise */
globvar DEBUG 1
/* The base address (relative to enclave start) of the enclave text section */
globvar TEXT_BASE 8
/* The size in bytes of enclacve text section */
globvar TEXT_SIZE 8
/* The base address (relative to enclave start) of the enclave EH_FRM_HDR section */
globvar EH_FRM_HDR_BASE 8
/* The size in bytes of enclacve EH_FRM_HDR section */
globvar EH_FRM_HDR_SIZE 8

.Lreentry_panic_msg:
.asciz "Re-entered panicked enclave!"
Expand Down
137 changes: 131 additions & 6 deletions src/libstd/sys/sgx/rwlock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,33 @@
// except according to those terms.

use num::NonZeroUsize;
use slice;
use str;

use super::waitqueue::{WaitVariable, WaitQueue, SpinMutex, NotifiedTcs, try_lock_or_false};
use super::waitqueue::{
try_lock_or_false, NotifiedTcs, SpinMutex, SpinMutexGuard, WaitQueue, WaitVariable,
};
use mem;

pub struct RWLock {
readers: SpinMutex<WaitVariable<Option<NonZeroUsize>>>,
writer: SpinMutex<WaitVariable<bool>>,
}

// Below is to check at compile time, that RWLock has size of 128 bytes.
#[allow(dead_code)]
unsafe fn rw_lock_size_assert(r: RWLock) {
mem::transmute::<RWLock, [u8; 128]>(r);
}

//unsafe impl Send for RWLock {}
//unsafe impl Sync for RWLock {} // FIXME

impl RWLock {
pub const fn new() -> RWLock {
RWLock {
readers: SpinMutex::new(WaitVariable::new(None)),
writer: SpinMutex::new(WaitVariable::new(false))
writer: SpinMutex::new(WaitVariable::new(false)),
}
}

Expand Down Expand Up @@ -89,9 +100,11 @@ impl RWLock {
}

#[inline]
pub unsafe fn read_unlock(&self) {
let mut rguard = self.readers.lock();
let wguard = self.writer.lock();
unsafe fn __read_unlock(
&self,
mut rguard: SpinMutexGuard<WaitVariable<Option<NonZeroUsize>>>,
wguard: SpinMutexGuard<WaitVariable<bool>>,
) {
*rguard.lock_var_mut() = NonZeroUsize::new(rguard.lock_var().unwrap().get() - 1);
if rguard.lock_var().is_some() {
// There are other active readers
Expand All @@ -107,9 +120,18 @@ impl RWLock {
}

#[inline]
pub unsafe fn write_unlock(&self) {
pub unsafe fn read_unlock(&self) {
let rguard = self.readers.lock();
let wguard = self.writer.lock();
self.__read_unlock(rguard, wguard);
}

#[inline]
unsafe fn __write_unlock(
&self,
rguard: SpinMutexGuard<WaitVariable<Option<NonZeroUsize>>>,
wguard: SpinMutexGuard<WaitVariable<bool>>,
) {
if let Err(mut wguard) = WaitQueue::notify_one(wguard) {
// No writers waiting, release the write lock
*wguard.lock_var_mut() = false;
Expand All @@ -128,6 +150,109 @@ impl RWLock {
}
}

#[inline]
pub unsafe fn write_unlock(&self) {
let rguard = self.readers.lock();
let wguard = self.writer.lock();
self.__write_unlock(rguard, wguard);
}

#[inline]
unsafe fn unlock(&self) {
let rguard = self.readers.lock();
let wguard = self.writer.lock();
if *wguard.lock_var() == true {
self.__write_unlock(rguard, wguard);
} else {
self.__read_unlock(rguard, wguard);
}
}

#[inline]
pub unsafe fn destroy(&self) {}
}

const EINVAL: i32 = 22;

#[no_mangle]
pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 {
if p.is_null() {
return EINVAL;
}
(*p).read();
return 0;
}

#[no_mangle]
pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RWLock) -> i32 {
if p.is_null() {
return EINVAL;
}
(*p).write();
return 0;
}
#[no_mangle]
pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 {
if p.is_null() {
return EINVAL;
}
(*p).unlock();
return 0;
}

#[no_mangle]
pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) {
if s < 0 {
return;
}
let buf = slice::from_raw_parts(m as *const u8, s as _);
if let Ok(s) = str::from_utf8(&buf[..buf.iter().position(|&b| b == 0).unwrap_or(buf.len())]) {
eprint!("{}", s);
}
}

#[no_mangle]
pub unsafe extern "C" fn __rust_abort() {
::sys::abort_internal();
}

#[cfg(test)]
mod tests {

use super::*;
use core::array::FixedSizeArray;
use mem::MaybeUninit;
use {mem, ptr};

// The below test verifies that the bytes of initialized RWLock are the ones
// we use in libunwind.
// If they change we need to update src/UnwindRustSgx.h in libunwind.
#[test]
fn test_c_rwlock_initializer() {
const RWLOCK_INIT: &[u8] = &[
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
];

let mut init = MaybeUninit::<RWLock>::zeroed();
init.set(RWLock::new());
assert_eq!(
mem::transmute::<_, [u8; 128]>(init.into_inner()).as_slice(),
RWLOCK_INIT
);
}
}
5 changes: 1 addition & 4 deletions src/libunwind/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ mod macros;
cfg_if! {
if #[cfg(target_env = "msvc")] {
// no extra unwinder support needed
} else if #[cfg(any(
all(target_arch = "wasm32", not(target_os = "emscripten")),
target_env = "sgx"
))] {
} else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] {
// no unwinder on the system!
} else {
extern crate libc;
Expand Down