Add x86_64-fortanix-unknown-sgx target to libstd and dependencies

The files src/libstd/sys/sgx/*.rs are mostly copied/adapted from
the wasm target.

This also updates the dlmalloc submodule to the very latest version.
This commit is contained in:
Jethro Beekman 2018-08-27 21:33:26 -07:00
parent c559216ad0
commit 4a3505682e
47 changed files with 2873 additions and 15 deletions

4
.gitmodules vendored
View File

@ -61,10 +61,12 @@
path = src/tools/clang
url = https://github.com/rust-lang-nursery/clang.git
branch = rust-release-80-v2
[submodule "src/doc/rustc-guide"]
path = src/doc/rustc-guide
url = https://github.com/rust-lang/rustc-guide.git
[submodule "src/doc/edition-guide"]
path = src/doc/edition-guide
url = https://github.com/rust-lang-nursery/edition-guide
[submodule "src/rust-sgx"]
path = src/rust-sgx
url = https://github.com/fortanix/rust-sgx

View File

@ -797,6 +797,14 @@ name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "fortanix-sgx-abi"
version = "0.0.0"
dependencies = [
"compiler_builtins 0.0.0",
"core 0.0.0",
]
[[package]]
name = "fs2"
version = "0.4.3"
@ -2773,6 +2781,7 @@ dependencies = [
"compiler_builtins 0.0.0",
"core 0.0.0",
"dlmalloc 0.0.0",
"fortanix-sgx-abi 0.0.0",
"libc 0.0.0",
"panic_abort 0.0.0",
"panic_unwind 0.0.0",

View File

@ -874,6 +874,7 @@ impl Step for Src {
"src/rustc/compiler_builtins_shim",
"src/rustc/libc_shim",
"src/rustc/dlmalloc_shim",
"src/rustc/fortanix-sgx-abi_shim",
"src/libtest",
"src/libterm",
"src/libprofiler_builtins",

@ -1 +1 @@
Subproject commit c99638dc2ecfc750cc1656f6edb2bd062c1e0981
Subproject commit de99f4b0c886f5916cd1a146464276d65bef61b8

@ -1 +1 @@
Subproject commit c75ca6465a139704e00295be355b1f067af2f535
Subproject commit 5b403753da9ec8ff501adf34cb6d63b319b4a3ae

View File

@ -66,6 +66,12 @@ pub unsafe extern fn __rust_start_panic(_payload: usize) -> u32 {
unsafe fn abort() -> ! {
core::intrinsics::abort();
}
#[cfg(target_env="sgx")]
unsafe fn abort() -> ! {
extern "C" { pub fn panic_exit() -> !; }
panic_exit();
}
}
// This... is a bit of an oddity. The tl;dr; is that this is required to link

View File

@ -62,7 +62,7 @@ cfg_if! {
if #[cfg(target_os = "emscripten")] {
#[path = "emcc.rs"]
mod imp;
} else if #[cfg(target_arch = "wasm32")] {
} else if #[cfg(any(target_arch = "wasm32", target_env = "sgx"))] {
#[path = "dummy.rs"]
mod imp;
} else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] {

View File

@ -35,9 +35,12 @@ rustc_lsan = { path = "../librustc_lsan" }
rustc_msan = { path = "../librustc_msan" }
rustc_tsan = { path = "../librustc_tsan" }
[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies]
[target.'cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), target_env = "sgx"))'.dependencies]
dlmalloc = { path = '../rustc/dlmalloc_shim' }
[target.x86_64-fortanix-unknown-sgx.dependencies]
fortanix-sgx-abi = { path = "../rustc/fortanix-sgx-abi_shim" }
[build-dependencies]
cc = "1.0"
build_helper = { path = "../build_helper" }

View File

@ -184,7 +184,7 @@ pub enum ErrorKind {
}
impl ErrorKind {
fn as_str(&self) -> &'static str {
pub(crate) fn as_str(&self) -> &'static str {
match *self {
ErrorKind::NotFound => "entity not found",
ErrorKind::PermissionDenied => "permission denied",

View File

@ -312,6 +312,7 @@
#![feature(non_exhaustive)]
#![feature(alloc_layout_extra)]
#![feature(maybe_uninit)]
#![cfg_attr(target_env = "sgx", feature(global_asm, range_contains))]
#![default_lib_allocator]
@ -354,6 +355,12 @@ extern crate unwind;
// testing gives test-std access to real-std lang items and globals. See #2912
#[cfg(test)] extern crate std as realstd;
#[cfg(target_env = "sgx")]
#[macro_use]
#[allow(unused_imports)] // FIXME: without `#[macro_use]`, get error: “cannot
// determine resolution for the macro `usercalls_asm`”
extern crate fortanix_sgx_abi;
// The standard macros that are not built-in to the compiler.
#[macro_use]
mod macros;

View File

@ -48,6 +48,9 @@ cfg_if! {
} else if #[cfg(target_arch = "wasm32")] {
mod wasm;
pub use self::wasm::*;
} else if #[cfg(target_env = "sgx")] {
mod sgx;
pub use self::sgx::*;
} else {
compile_error!("libstd doesn't compile for this platform yet");
}

View File

@ -0,0 +1,327 @@
/* Copyright 2018 The Rust Project Developers. See the COPYRIGHT */
/* file at the top-level directory of this distribution and at */
/* http://rust-lang.org/COPYRIGHT. */
/* */
/* Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or */
/* http://www.apache.org/licenses/LICENSE-2.0> or the MIT license */
/* <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your */
/* option. This file may not be copied, modified, or distributed */
/* except according to those terms. */
/* This symbol is used at runtime to figure out the virtual address that the */
/* enclave is loaded at. */
.section absolute
.global IMAGE_BASE
IMAGE_BASE:
.section .rodata
/* The XSAVE area needs to be a large chunk of readable memory, but since we are */
/* going to restore everything to its initial state (XSTATE_BV=0), only certain */
/* parts need to have a defined value. In particular: */
/* */
/* * MXCSR in the legacy area. This register is always restored if RFBM[1] or */
/* RFBM[2] is set, regardless of the value of XSTATE_BV */
/* * XSAVE header */
.align 64
.Lxsave_clear:
.org .+24
.Lxsave_mxcsr:
.int 0
/* We can store a bunch of data in the gap between MXCSR and the XSAVE header */
/* The following symbols point at read-only data that will be filled in by the */
/* post-linker. */
/* When using this macro, don't forget to adjust the linker version script! */
.macro globvar name:req size:req
.global \name
.protected \name
.align \size
.size \name , \size
\name :
.org .+\size
.endm
/* The base address (relative to enclave start) of the heap area */
globvar HEAP_BASE 8
/* The heap size in bytes */
globvar HEAP_SIZE 8
/* Value of the RELA entry in the dynamic table */
globvar RELA 8
/* Value of the RELACOUNT entry in the dynamic table */
globvar RELACOUNT 8
/* The enclave size in bytes */
globvar ENCLAVE_SIZE 8
/* The base address (relative to enclave start) of the enclave configuration area */
globvar CFGDATA_BASE 8
/* Non-zero if debugging is enabled, zero otherwise */
globvar DEBUG 1
.Lreentry_panic_msg:
.asciz "Re-entered panicked enclave!"
.Lreentry_panic_msg_end:
.Lusercall_panic_msg:
.asciz "Invalid usercall#!"
.Lusercall_panic_msg_end:
.org .Lxsave_clear+512
.Lxsave_header:
.int 0, 0 /* XSTATE_BV */
.int 0, 0 /* XCOMP_BV */
.org .+48 /* reserved bits */
.data
.Lpanicked:
.byte 0
/* TCS local storage section */
.equ tcsls_tos, 0x00 /* initialized by loader to *offset* from image base to TOS */
.equ tcsls_flags, 0x08 /* initialized by loader */
.equ tcsls_flag_secondary, 0 /* initialized by loader; 0 = standard TCS, 1 = secondary TCS */
.equ tcsls_flag_init_once, 1 /* initialized by loader to 0 */
/* 14 unused bits */
.equ tcsls_user_fcw, 0x0a
.equ tcsls_user_mxcsr, 0x0c
.equ tcsls_last_rsp, 0x10 /* initialized by loader to 0 */
.equ tcsls_panic_last_rsp, 0x18 /* initialized by loader to 0 */
.equ tcsls_debug_panic_buf_ptr, 0x20 /* initialized by loader to 0 */
.equ tcsls_user_rsp, 0x28
.equ tcsls_user_retip, 0x30
.equ tcsls_user_rbp, 0x38
.equ tcsls_user_r12, 0x40
.equ tcsls_user_r13, 0x48
.equ tcsls_user_r14, 0x50
.equ tcsls_user_r15, 0x58
.equ tcsls_tls_ptr, 0x60
.equ tcsls_tcs_addr, 0x68
.macro load_tcsls_flag_secondary_bool reg:req comments:vararg
.ifne tcsls_flag_secondary /* to convert to a bool, must be the first bit */
.abort
.endif
mov $(1<<tcsls_flag_secondary),%e\reg
and %gs:tcsls_flags,%\reg
.endm
.text
.global sgx_entry
.type sgx_entry,function
sgx_entry:
/* save user registers */
mov %rcx,%gs:tcsls_user_retip
mov %rsp,%gs:tcsls_user_rsp
mov %rbp,%gs:tcsls_user_rbp
mov %r12,%gs:tcsls_user_r12
mov %r13,%gs:tcsls_user_r13
mov %r14,%gs:tcsls_user_r14
mov %r15,%gs:tcsls_user_r15
mov %rbx,%gs:tcsls_tcs_addr
stmxcsr %gs:tcsls_user_mxcsr
fnstcw %gs:tcsls_user_fcw
/* reset user state */
cld /* x86-64 ABI requires DF to be unset at function entry/exit */
/* check for debug buffer pointer */
testb $0xff,DEBUG(%rip)
jz .Lskip_debug_init
mov %r10,%gs:tcsls_debug_panic_buf_ptr
.Lskip_debug_init:
/* check if returning from usercall */
mov %gs:tcsls_last_rsp,%r11
test %r11,%r11
jnz .Lusercall_ret
/* setup stack */
mov %gs:tcsls_tos,%rsp /* initially, RSP is not set to the correct value */
/* here. This is fixed below under "adjust stack". */
/* check for thread init */
bts $tcsls_flag_init_once,%gs:tcsls_flags
jc .Lskip_init
/* adjust stack */
lea IMAGE_BASE(%rip),%rax
add %rax,%rsp
mov %rsp,%gs:tcsls_tos
/* call tcs_init */
/* store caller-saved registers in callee-saved registers */
mov %rdi,%rbx
mov %rsi,%r12
mov %rdx,%r13
mov %r8,%r14
mov %r9,%r15
load_tcsls_flag_secondary_bool di /* RDI = tcs_init() argument: secondary: bool */
call tcs_init
/* reload caller-saved registers */
mov %rbx,%rdi
mov %r12,%rsi
mov %r13,%rdx
mov %r14,%r8
mov %r15,%r9
.Lskip_init:
/* check for panic */
bt $0,.Lpanicked(%rip)
jc .Lreentry_panic
/* call into main entry point */
load_tcsls_flag_secondary_bool cx /* RCX = entry() argument: secondary: bool */
call entry /* RDI, RSI, RDX, R8, R9 passed in from userspace */
mov %rax,%rsi /* RSI = return value */
/* NOP: mov %rdx,%rdx */ /* RDX = return value */
xor %rdi,%rdi /* RDI = normal exit */
.Lexit:
/* clear general purpose register state */
/* RAX overwritten by ENCLU */
/* RBX set later */
/* RCX overwritten by ENCLU */
/* RDX contains return value */
/* RSP set later */
/* RBP set later */
/* RDI contains exit mode */
/* RSI contains return value */
xor %r8,%r8
xor %r9,%r9
xor %r10,%r10
xor %r11,%r11
/* R12 ~ R15 set by sgx_exit */
.Lsgx_exit:
/* clear extended register state */
mov %rdx, %rcx /* save RDX */
mov $-1, %rax
mov %rax, %rdx
xrstor .Lxsave_clear(%rip)
mov %rcx, %rdx /* restore RDX */
/* clear flags */
pushq $0
popfq
/* restore user registers */
mov %gs:tcsls_user_r12,%r12
mov %gs:tcsls_user_r13,%r13
mov %gs:tcsls_user_r14,%r14
mov %gs:tcsls_user_r15,%r15
mov %gs:tcsls_user_retip,%rbx
mov %gs:tcsls_user_rsp,%rsp
mov %gs:tcsls_user_rbp,%rbp
fldcw %gs:tcsls_user_fcw
ldmxcsr %gs:tcsls_user_mxcsr
/* exit enclave */
mov $0x4,%eax /* EEXIT */
enclu
/* end sgx_entry */
.Lreentry_panic:
lea .Lreentry_panic_msg(%rip),%rdi
mov $.Lreentry_panic_msg_end-.Lreentry_panic_msg,%esi
orq $8,%rsp
jmp panic_msg
.Lusercall_panic:
lea .Lusercall_panic_msg(%rip),%rdi
mov $.Lusercall_panic_msg_end-.Lusercall_panic_msg,%esi
orq $8,%rsp
jmp panic_msg
.macro push_callee_saved_registers
push %r15
push %r14
push %r13
push %r12
push %rbp
push %rbx
sub $8, %rsp
fstcw 4(%rsp)
stmxcsr (%rsp)
.endm
.global panic_exit
panic_exit:
/* save registers in DEBUG mode, so that debugger can reconstruct the stack */
testb $0xff,DEBUG(%rip)
jz .Lskip_save_registers
push_callee_saved_registers
movq %rsp,%gs:tcsls_panic_last_rsp
.Lskip_save_registers:
/* set panicked bit */
movb $1,.Lpanicked(%rip)
/* call usercall exit(true) */
mov $1,%esi /* RSI = usercall() argument: panic = true */
xor %rdx,%rdx /* RDX cleared */
movq $usercall_nr_exit,%rdi /* RDI = usercall exit */
jmp .Lexit
/* This *MUST* be called with 6 parameters, otherwise register information */
/* might leak! */
.global usercall
usercall:
test %rdi,%rdi
jle .Lusercall_panic
/* save callee-saved state */
push_callee_saved_registers
movq %rsp,%gs:tcsls_last_rsp
/* clear general purpose register state */
/* RAX overwritten by ENCLU */
/* RBX set by sgx_exit */
/* RCX overwritten by ENCLU */
/* RDX contains parameter */
/* RSP set by sgx_exit */
/* RBP set by sgx_exit */
/* RDI contains parameter */
/* RSI contains parameter */
/* R8 contains parameter */
/* R9 contains parameter */
xor %r10,%r10
xor %r11,%r11
/* R12 ~ R15 set by sgx_exit */
/* extended registers/flags cleared by sgx_exit */
/* exit */
jmp .Lsgx_exit
.Lusercall_ret:
movq $0,%gs:tcsls_last_rsp
/* restore callee-saved state, cf. push_callee_saved_registers */
mov %r11,%rsp
ldmxcsr (%rsp)
fldcw 4(%rsp)
add $8, %rsp
pop %rbx
pop %rbp
pop %r12
pop %r13
pop %r14
pop %r15
/* return */
mov %rsi,%rax /* RAX = return value */
/* NOP: mov %rdx,%rdx */ /* RDX = return value */
ret
/*
The following functions need to be defined externally:
```
// Called by entry code when it needs to panic
extern "C" fn panic_msg(msg: &'static str) -> ! {
panic!(msg)
}
// Called once when a TCS is first entered
extern "C" fn tcs_init(secondary: bool);
// Standard TCS entrypoint
extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> (u64, u64);
```
*/
.global get_tcs_addr
get_tcs_addr:
mov %gs:tcsls_tcs_addr,%rax
ret
.global get_tls_ptr
get_tls_ptr:
mov %gs:tcsls_tls_ptr,%rax
ret
.global set_tls_ptr
set_tls_ptr:
mov %rdi,%gs:tcsls_tls_ptr
ret
.global take_debug_panic_buf_ptr
take_debug_panic_buf_ptr:
xor %rax,%rax
xchg %gs:tcsls_debug_panic_buf_ptr,%rax
ret

View File

@ -0,0 +1,31 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Do not remove inline: will result in relocation failure
#[inline(always)]
pub unsafe fn rel_ptr<T>(offset: u64) -> *const T {
(image_base()+offset) as *const T
}
// Do not remove inline: will result in relocation failure
#[inline(always)]
pub unsafe fn rel_ptr_mut<T>(offset: u64) -> *mut T {
(image_base()+offset) as *mut T
}
// Do not remove inline: will result in relocation failure
// For the same reason we use inline ASM here instead of an extern static to
// locate the base
#[inline(always)]
fn image_base() -> u64 {
let base;
unsafe{asm!("lea IMAGE_BASE(%rip),$0":"=r"(base))};
base
}

View File

@ -0,0 +1,94 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::sync::atomic::{AtomicUsize, Ordering};
use io::Write;
// runtime features
mod reloc;
mod mem;
pub(super) mod panic;
// library features
#[macro_use]
mod usercalls;
global_asm!(concat!(usercalls_asm!(), include_str!("entry.S")));
#[no_mangle]
unsafe extern "C" fn tcs_init(secondary: bool) {
// Be very careful when changing this code: it runs before the binary has been
// relocated. Any indirect accesses to symbols will likely fail.
const UNINIT: usize = 0;
const BUSY: usize = 1;
const DONE: usize = 2;
// Three-state spin-lock
static RELOC_STATE: AtomicUsize = AtomicUsize::new(UNINIT);
if secondary && RELOC_STATE.load(Ordering::Relaxed) != DONE {
panic::panic_msg("Entered secondary TCS before main TCS!")
}
// Try to atomically swap UNINIT with BUSY. The returned state can be:
match RELOC_STATE.compare_and_swap(UNINIT, BUSY, Ordering::Acquire) {
// This thread just obtained the lock and other threads will observe BUSY
UNINIT => {
reloc::relocate_elf_rela();
RELOC_STATE.store(DONE, Ordering::Release);
},
// We need to wait until the initialization is done.
BUSY => while RELOC_STATE.load(Ordering::Acquire) == BUSY {
::core::arch::x86_64::_mm_pause()
},
// Initialization is done.
DONE => {},
_ => unreachable!()
}
}
// FIXME: this item should only exist if this is linked into an executable
// (main function exists). If this is a library, the crate author should be
// able to specify this
#[no_mangle]
#[allow(unreachable_code)]
extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> (u64, u64) {
if secondary {
unimplemented!("thread entrypoint");
(0, 0)
} else {
extern "C" {
fn main(argc: isize, argv: *const *const u8) -> isize;
}
// check entry is being called according to ABI
assert_eq!(p3, 0);
assert_eq!(p4, 0);
assert_eq!(p5, 0);
unsafe {
// The actual types of these arguments are `p1: *const Arg, p2:
// usize`. We can't currently customize the argument list of Rust's
// main function, so we pass these in as the standard pointer-sized
// values in `argc` and `argv`.
let ret = main(p2 as _, p1 as _);
exit_with_code(ret)
}
}
}
pub(super) fn exit_with_code(code: isize) -> ! {
if code != 0 {
if let Some(mut out) = panic::SgxPanicOutput::new() {
let _ = write!(out, "Exited with status code {}", code);
}
}
unsafe { usercalls::raw::exit(code != 0) };
}

View File

@ -0,0 +1,58 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use io::{self, Write};
use slice::from_raw_parts_mut;
extern "C" {
fn take_debug_panic_buf_ptr() -> *mut u8;
static DEBUG: u8;
}
pub(crate) struct SgxPanicOutput(Option<&'static mut [u8]>);
impl SgxPanicOutput {
pub(crate) fn new() -> Option<Self> {
if unsafe { DEBUG == 0 } {
None
} else {
Some(SgxPanicOutput(None))
}
}
fn init(&mut self) -> &mut &'static mut [u8] {
self.0.get_or_insert_with(|| unsafe {
let ptr = take_debug_panic_buf_ptr();
if ptr.is_null() {
&mut []
} else {
from_raw_parts_mut(ptr, 1024)
}
})
}
}
impl Write for SgxPanicOutput {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.init().write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.init().flush()
}
}
#[no_mangle]
pub extern "C" fn panic_msg(msg: &str) -> ! {
let _ = SgxPanicOutput::new().map(|mut out| out.write(msg.as_bytes()));
unsafe { panic_exit(); }
}
extern "C" { pub fn panic_exit() -> !; }

View File

@ -0,0 +1,40 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use slice::from_raw_parts;
use super::mem;
const R_X86_64_RELATIVE: u32 = 8;
#[repr(packed)]
struct Rela<T> {
offset: T,
info: T,
addend: T,
}
pub fn relocate_elf_rela() {
extern {
static RELA: u64;
static RELACOUNT: usize;
}
if unsafe { RELACOUNT } == 0 { return } // unsafe ok: link-time constant
let relas = unsafe {
from_raw_parts::<Rela<u64>>(mem::rel_ptr(RELA), RELACOUNT) // unsafe ok: link-time constant
};
for rela in relas {
if rela.info != (/*0 << 32 |*/ R_X86_64_RELATIVE as u64) {
panic!("Invalid relocation");
}
unsafe { *mem::rel_ptr_mut::<*const ()>(rela.offset) = mem::rel_ptr(rela.addend) };
}
}

View File

@ -0,0 +1,12 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[macro_use]
pub mod raw;

View File

@ -0,0 +1,231 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(unused)]
use fortanix_sgx_abi::*;
use ptr::NonNull;
#[repr(C)]
struct UsercallReturn(u64, u64);
extern "C" {
fn usercall(nr: u64, p1: u64, p2: u64, _ignore: u64, p3: u64, p4: u64) -> UsercallReturn;
}
unsafe fn do_usercall(nr: u64, p1: u64, p2: u64, p3: u64, p4: u64) -> (u64, u64) {
if nr==0 { panic!("Invalid usercall number {}",nr) }
let UsercallReturn(a, b) = usercall(nr,p1,p2,0,p3,p4);
(a, b)
}
type Register = u64;
trait RegisterArgument {
fn from_register(Register) -> Self;
fn into_register(self) -> Register;
}
trait ReturnValue {
fn from_registers(call: &'static str, regs: (Register, Register)) -> Self;
}
macro_rules! define_usercalls {
// Using `$r:tt` because `$r:ty` doesn't match ! in `clobber_diverging`
($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:tt)*; )*) => {
#[repr(C)]
#[allow(non_camel_case_types)]
enum Usercalls {
__enclave_usercalls_invalid,
$($f,)*
}
$(enclave_usercalls_internal_define_usercalls!(def fn $f($($n: $t),*) $(-> $r)*);)*
};
}
macro_rules! define_usercalls_asm {
($(fn $f:ident($($n:ident: $t:ty),*) $(-> $r:ty)*; )*) => {
macro_rules! usercalls_asm {
() => {
concat!(
".equ usercall_nr_LAST, 0\n",
$(
".equ usercall_nr_", stringify!($f), ", usercall_nr_LAST+1\n",
".equ usercall_nr_LAST, usercall_nr_", stringify!($f), "\n"
),*
)
}
}
};
}
macro_rules! define_ra {
(< $i:ident > $t:ty) => {
impl<$i> RegisterArgument for $t {
fn from_register(a: Register) -> Self {
a as _
}
fn into_register(self) -> Register {
self as _
}
}
};
($i:ty as $t:ty) => {
impl RegisterArgument for $t {
fn from_register(a: Register) -> Self {
a as $i as _
}
fn into_register(self) -> Register {
self as $i as _
}
}
};
($t:ty) => {
impl RegisterArgument for $t {
fn from_register(a: Register) -> Self {
a as _
}
fn into_register(self) -> Register {
self as _
}
}
};
}
define_ra!(Register);
define_ra!(i64);
define_ra!(u32);
define_ra!(u32 as i32);
define_ra!(u16);
define_ra!(u16 as i16);
define_ra!(u8);
define_ra!(u8 as i8);
define_ra!(usize);
define_ra!(usize as isize);
define_ra!(<T> *const T);
define_ra!(<T> *mut T);
impl RegisterArgument for bool {
fn from_register(a: Register) -> bool {
if a != 0 {
true
} else {
false
}
}
fn into_register(self) -> Register {
self as _
}
}
impl<T: RegisterArgument> RegisterArgument for Option<NonNull<T>> {
fn from_register(a: Register) -> Option<NonNull<T>> {
NonNull::new(a as _)
}
fn into_register(self) -> Register {
self.map_or(0 as _, NonNull::as_ptr) as _
}
}
impl ReturnValue for ! {
fn from_registers(call: &'static str, _regs: (Register, Register)) -> Self {
panic!("Usercall {}: did not expect to be re-entered", call);
}
}
impl ReturnValue for () {
fn from_registers(call: &'static str, regs: (Register, Register)) -> Self {
assert_eq!(regs.0, 0, "Usercall {}: expected {} return value to be 0", call, "1st");
assert_eq!(regs.1, 0, "Usercall {}: expected {} return value to be 0", call, "2nd");
()
}
}
impl<T: RegisterArgument> ReturnValue for T {
fn from_registers(call: &'static str, regs: (Register, Register)) -> Self {
assert_eq!(regs.1, 0, "Usercall {}: expected {} return value to be 0", call, "2nd");
T::from_register(regs.0)
}
}
impl<T: RegisterArgument, U: RegisterArgument> ReturnValue for (T, U) {
fn from_registers(_call: &'static str, regs: (Register, Register)) -> Self {
(
T::from_register(regs.0),
U::from_register(regs.1)
)
}
}
macro_rules! enclave_usercalls_internal_define_usercalls {
(def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty,
$n3:ident: $t3:ty, $n4:ident: $t4:ty) -> $r:ty) => (
#[inline(always)]
pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3, $n4: $t4) -> $r {
ReturnValue::from_registers(stringify!($f), do_usercall(
Usercalls::$f as Register,
RegisterArgument::into_register($n1),
RegisterArgument::into_register($n2),
RegisterArgument::into_register($n3),
RegisterArgument::into_register($n4),
))
}
);
(def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty, $n3:ident: $t3:ty) -> $r:ty) => (
#[inline(always)]
pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3) -> $r {
ReturnValue::from_registers(stringify!($f), do_usercall(
Usercalls::$f as Register,
RegisterArgument::into_register($n1),
RegisterArgument::into_register($n2),
RegisterArgument::into_register($n3),
0
))
}
);
(def fn $f:ident($n1:ident: $t1:ty, $n2:ident: $t2:ty) -> $r:ty) => (
#[inline(always)]
pub unsafe fn $f($n1: $t1, $n2: $t2) -> $r {
ReturnValue::from_registers(stringify!($f), do_usercall(
Usercalls::$f as Register,
RegisterArgument::into_register($n1),
RegisterArgument::into_register($n2),
0,0
))
}
);
(def fn $f:ident($n1:ident: $t1:ty) -> $r:ty) => (
#[inline(always)]
pub unsafe fn $f($n1: $t1) -> $r {
ReturnValue::from_registers(stringify!($f), do_usercall(
Usercalls::$f as Register,
RegisterArgument::into_register($n1),
0,0,0
))
}
);
(def fn $f:ident() -> $r:ty) => (
#[inline(always)]
pub unsafe fn $f() -> $r {
ReturnValue::from_registers(stringify!($f), do_usercall(
Usercalls::$f as Register,
0,0,0,0
))
}
);
(def fn $f:ident($($n:ident: $t:ty),*)) => (
enclave_usercalls_internal_define_usercalls!(def fn $f($($n: $t),*) -> ());
);
}
invoke_with_usercalls!(define_usercalls);
invoke_with_usercalls!(define_usercalls_asm);

View File

@ -0,0 +1,39 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
extern crate dlmalloc;
use alloc::{GlobalAlloc, Layout, System};
// FIXME: protect this value for concurrent access
static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::DLMALLOC_INIT;
#[stable(feature = "alloc_system_type", since = "1.28.0")]
unsafe impl GlobalAlloc for System {
#[inline]
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
DLMALLOC.malloc(layout.size(), layout.align())
}
#[inline]
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
DLMALLOC.calloc(layout.size(), layout.align())
}
#[inline]
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
DLMALLOC.free(ptr, layout.size(), layout.align())
}
#[inline]
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size)
}
}

View File

@ -0,0 +1,57 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ffi::OsString;
use fortanix_sgx_abi::ByteBuffer;
pub unsafe fn init(argc: isize, argv: *const *const u8) {
// See ABI
let _len: usize = argc as _;
let _args: *const ByteBuffer = argv as _;
// TODO
}
pub unsafe fn cleanup() {
}
pub fn args() -> Args {
Args
}
pub struct Args;
impl Args {
pub fn inner_debug(&self) -> &[OsString] {
&[]
}
}
impl Iterator for Args {
type Item = OsString;
fn next(&mut self) -> Option<OsString> {
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(0))
}
}
impl ExactSizeIterator for Args {
fn len(&self) -> usize {
0
}
}
impl DoubleEndedIterator for Args {
fn next_back(&mut self) -> Option<OsString> {
None
}
}

View File

@ -0,0 +1,37 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use io;
use sys::unsupported;
use sys_common::backtrace::Frame;
pub struct BacktraceContext;
pub fn unwind_backtrace(_frames: &mut [Frame])
-> io::Result<(usize, BacktraceContext)>
{
unsupported()
}
pub fn resolve_symname<F>(_frame: Frame,
_callback: F,
_: &BacktraceContext) -> io::Result<()>
where F: FnOnce(Option<&str>) -> io::Result<()>
{
unsupported()
}
pub fn foreach_symbol_fileline<F>(_: Frame,
_: F,
_: &BacktraceContext) -> io::Result<bool>
where F: FnMut(&[u8], u32) -> io::Result<()>
{
unsupported()
}

View File

@ -0,0 +1,41 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![cfg(not(test))]
// These symbols are all defined in `compiler-builtins`
extern {
pub fn acos(n: f64) -> f64;
pub fn acosf(n: f32) -> f32;
pub fn asin(n: f64) -> f64;
pub fn asinf(n: f32) -> f32;
pub fn atan(n: f64) -> f64;
pub fn atan2(a: f64, b: f64) -> f64;
pub fn atan2f(a: f32, b: f32) -> f32;
pub fn atanf(n: f32) -> f32;
pub fn cbrt(n: f64) -> f64;
pub fn cbrtf(n: f32) -> f32;
pub fn cosh(n: f64) -> f64;
pub fn coshf(n: f32) -> f32;
pub fn expm1(n: f64) -> f64;
pub fn expm1f(n: f32) -> f32;
pub fn fdim(a: f64, b: f64) -> f64;
pub fn fdimf(a: f32, b: f32) -> f32;
pub fn hypot(x: f64, y: f64) -> f64;
pub fn hypotf(x: f32, y: f32) -> f32;
pub fn log1p(n: f64) -> f64;
pub fn log1pf(n: f32) -> f32;
pub fn sinh(n: f64) -> f64;
pub fn sinhf(n: f32) -> f32;
pub fn tan(n: f64) -> f64;
pub fn tanf(n: f32) -> f32;
pub fn tanh(n: f64) -> f64;
pub fn tanhf(n: f32) -> f32;
}

View File

@ -0,0 +1,43 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use sys::mutex::Mutex;
use time::Duration;
pub struct Condvar { }
impl Condvar {
pub const fn new() -> Condvar {
Condvar { }
}
#[inline]
pub unsafe fn init(&mut self) {}
#[inline]
pub unsafe fn notify_one(&self) {
}
#[inline]
pub unsafe fn notify_all(&self) {
}
pub unsafe fn wait(&self, _mutex: &Mutex) {
panic!("can't block with web assembly")
}
pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
panic!("can't block with web assembly");
}
#[inline]
pub unsafe fn destroy(&self) {
}
}

19
src/libstd/sys/sgx/env.rs Normal file
View File

@ -0,0 +1,19 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub mod os {
pub const FAMILY: &'static str = "";
pub const OS: &'static str = "";
pub const DLL_PREFIX: &'static str = "";
pub const DLL_SUFFIX: &'static str = ".sgxs";
pub const DLL_EXTENSION: &'static str = "sgxs";
pub const EXE_SUFFIX: &'static str = ".sgxs";
pub const EXE_EXTENSION: &'static str = "sgxs";
}

304
src/libstd/sys/sgx/fs.rs Normal file
View File

@ -0,0 +1,304 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ffi::OsString;
use fmt;
use hash::{Hash, Hasher};
use io::{self, SeekFrom};
use path::{Path, PathBuf};
use sys::time::SystemTime;
use sys::{unsupported, Void};
pub struct File(Void);
pub struct FileAttr(Void);
pub struct ReadDir(Void);
pub struct DirEntry(Void);
#[derive(Clone, Debug)]
pub struct OpenOptions { }
pub struct FilePermissions(Void);
pub struct FileType(Void);
#[derive(Debug)]
pub struct DirBuilder { }
impl FileAttr {
pub fn size(&self) -> u64 {
match self.0 {}
}
pub fn perm(&self) -> FilePermissions {
match self.0 {}
}
pub fn file_type(&self) -> FileType {
match self.0 {}
}
pub fn modified(&self) -> io::Result<SystemTime> {
match self.0 {}
}
pub fn accessed(&self) -> io::Result<SystemTime> {
match self.0 {}
}
pub fn created(&self) -> io::Result<SystemTime> {
match self.0 {}
}
}
impl Clone for FileAttr {
fn clone(&self) -> FileAttr {
match self.0 {}
}
}
impl FilePermissions {
pub fn readonly(&self) -> bool {
match self.0 {}
}
pub fn set_readonly(&mut self, _readonly: bool) {
match self.0 {}
}
}
impl Clone for FilePermissions {
fn clone(&self) -> FilePermissions {
match self.0 {}
}
}
impl PartialEq for FilePermissions {
fn eq(&self, _other: &FilePermissions) -> bool {
match self.0 {}
}
}
impl Eq for FilePermissions {
}
impl fmt::Debug for FilePermissions {
fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {}
}
}
impl FileType {
pub fn is_dir(&self) -> bool {
match self.0 {}
}
pub fn is_file(&self) -> bool {
match self.0 {}
}
pub fn is_symlink(&self) -> bool {
match self.0 {}
}
}
impl Clone for FileType {
fn clone(&self) -> FileType {
match self.0 {}
}
}
impl Copy for FileType {}
impl PartialEq for FileType {
fn eq(&self, _other: &FileType) -> bool {
match self.0 {}
}
}
impl Eq for FileType {
}
impl Hash for FileType {
fn hash<H: Hasher>(&self, _h: &mut H) {
match self.0 {}
}
}
impl fmt::Debug for FileType {
fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {}
}
}
impl fmt::Debug for ReadDir {
fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {}
}
}
impl Iterator for ReadDir {
type Item = io::Result<DirEntry>;
fn next(&mut self) -> Option<io::Result<DirEntry>> {
match self.0 {}
}
}
impl DirEntry {
pub fn path(&self) -> PathBuf {
match self.0 {}
}
pub fn file_name(&self) -> OsString {
match self.0 {}
}
pub fn metadata(&self) -> io::Result<FileAttr> {
match self.0 {}
}
pub fn file_type(&self) -> io::Result<FileType> {
match self.0 {}
}
}
impl OpenOptions {
pub fn new() -> OpenOptions {
OpenOptions { }
}
pub fn read(&mut self, _read: bool) { }
pub fn write(&mut self, _write: bool) { }
pub fn append(&mut self, _append: bool) { }
pub fn truncate(&mut self, _truncate: bool) { }
pub fn create(&mut self, _create: bool) { }
pub fn create_new(&mut self, _create_new: bool) { }
}
impl File {
pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result<File> {
unsupported()
}
pub fn file_attr(&self) -> io::Result<FileAttr> {
match self.0 {}
}
pub fn fsync(&self) -> io::Result<()> {
match self.0 {}
}
pub fn datasync(&self) -> io::Result<()> {
match self.0 {}
}
pub fn truncate(&self, _size: u64) -> io::Result<()> {
match self.0 {}
}
pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
match self.0 {}
}
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
match self.0 {}
}
pub fn flush(&self) -> io::Result<()> {
match self.0 {}
}
pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
match self.0 {}
}
pub fn duplicate(&self) -> io::Result<File> {
match self.0 {}
}
pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
match self.0 {}
}
pub fn diverge(&self) -> ! {
match self.0 {}
}
}
impl DirBuilder {
pub fn new() -> DirBuilder {
DirBuilder { }
}
pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
unsupported()
}
}
impl fmt::Debug for File {
fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {}
}
}
pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
unsupported()
}
pub fn unlink(_p: &Path) -> io::Result<()> {
unsupported()
}
pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
unsupported()
}
pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
match perm.0 {}
}
pub fn rmdir(_p: &Path) -> io::Result<()> {
unsupported()
}
pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
unsupported()
}
pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
unsupported()
}
pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
unsupported()
}
pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
unsupported()
}
pub fn stat(_p: &Path) -> io::Result<FileAttr> {
unsupported()
}
pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
unsupported()
}
pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
unsupported()
}
pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> {
unsupported()
}

View File

@ -0,0 +1,11 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub use core::slice::memchr::{memchr, memrchr};

151
src/libstd/sys/sgx/mod.rs Normal file
View File

@ -0,0 +1,151 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! System bindings for the Fortanix SGX platform
//!
//! This module contains the facade (aka platform-specific) implementations of
//! OS level functionality for Fortanix SGX.
use io;
use os::raw::c_char;
use sync::atomic::{AtomicBool, Ordering};
pub mod abi;
pub mod alloc;
pub mod args;
#[cfg(feature = "backtrace")]
pub mod backtrace;
pub mod cmath;
pub mod condvar;
pub mod env;
pub mod fs;
pub mod memchr;
pub mod mutex;
pub mod net;
pub mod os;
pub mod os_str;
pub mod path;
pub mod pipe;
pub mod process;
pub mod rwlock;
pub mod stack_overflow;
pub mod thread;
pub mod thread_local;
pub mod time;
pub mod stdio;
#[cfg(not(test))]
pub fn init() {
}
/// This function is used to implement functionality that simply doesn't exist.
/// Programs relying on this functionality will need to deal with the error.
pub fn unsupported<T>() -> io::Result<T> {
Err(unsupported_err())
}
pub fn unsupported_err() -> io::Error {
io::Error::new(io::ErrorKind::Other,
"operation not supported on SGX yet")
}
/// This function is used to implement various functions that doesn't exist,
/// but the lack of which might not be reason for error. If no error is
/// returned, the program might very well be able to function normally. This is
/// what happens when `SGX_INEFFECTIVE_ERROR` is set to `true`. If it is
/// `false`, the behavior is the same as `unsupported`.
pub fn sgx_ineffective<T>(v: T) -> io::Result<T> {
static SGX_INEFFECTIVE_ERROR: AtomicBool = AtomicBool::new(false);
if SGX_INEFFECTIVE_ERROR.load(Ordering::Relaxed) {
Err(io::Error::new(io::ErrorKind::Other,
"operation can't be trusted to have any effect on SGX"))
} else {
Ok(v)
}
}
pub fn decode_error_kind(code: i32) -> io::ErrorKind {
use fortanix_sgx_abi::Error;
// FIXME: not sure how to make sure all variants of Error are covered
if code == Error::NotFound as _ {
io::ErrorKind::NotFound
} else if code == Error::PermissionDenied as _ {
io::ErrorKind::PermissionDenied
} else if code == Error::ConnectionRefused as _ {
io::ErrorKind::ConnectionRefused
} else if code == Error::ConnectionReset as _ {
io::ErrorKind::ConnectionReset
} else if code == Error::ConnectionAborted as _ {
io::ErrorKind::ConnectionAborted
} else if code == Error::NotConnected as _ {
io::ErrorKind::NotConnected
} else if code == Error::AddrInUse as _ {
io::ErrorKind::AddrInUse
} else if code == Error::AddrNotAvailable as _ {
io::ErrorKind::AddrNotAvailable
} else if code == Error::BrokenPipe as _ {
io::ErrorKind::BrokenPipe
} else if code == Error::AlreadyExists as _ {
io::ErrorKind::AlreadyExists
} else if code == Error::WouldBlock as _ {
io::ErrorKind::WouldBlock
} else if code == Error::InvalidInput as _ {
io::ErrorKind::InvalidInput
} else if code == Error::InvalidData as _ {
io::ErrorKind::InvalidData
} else if code == Error::TimedOut as _ {
io::ErrorKind::TimedOut
} else if code == Error::WriteZero as _ {
io::ErrorKind::WriteZero
} else if code == Error::Interrupted as _ {
io::ErrorKind::Interrupted
} else if code == Error::Other as _ {
io::ErrorKind::Other
} else if code == Error::UnexpectedEof as _ {
io::ErrorKind::UnexpectedEof
} else {
io::ErrorKind::Other
}
}
// This enum is used as the storage for a bunch of types which can't actually
// exist.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub enum Void {}
pub unsafe fn strlen(mut s: *const c_char) -> usize {
let mut n = 0;
while *s != 0 {
n += 1;
s = s.offset(1);
}
return n
}
pub unsafe fn abort_internal() -> ! {
abi::panic::panic_exit()
}
pub fn hashmap_random_keys() -> (u64, u64) {
fn rdrand64() -> u64 {
unsafe {
let mut ret: u64 = ::mem::uninitialized();
for _ in 0..10 {
if ::arch::x86_64::_rdrand64_step(&mut ret) == 1 {
return ret;
}
}
panic!("Failed to obtain random data");
}
}
(rdrand64(), rdrand64())
}

View File

@ -0,0 +1,78 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use cell::UnsafeCell;
pub struct Mutex {
locked: UnsafeCell<bool>,
}
unsafe impl Send for Mutex {}
unsafe impl Sync for Mutex {} // FIXME
impl Mutex {
pub const fn new() -> Mutex {
Mutex { locked: UnsafeCell::new(false) }
}
#[inline]
pub unsafe fn init(&mut self) {
}
#[inline]
pub unsafe fn lock(&self) {
let locked = self.locked.get();
assert!(!*locked, "cannot recursively acquire mutex");
*locked = true;
}
#[inline]
pub unsafe fn unlock(&self) {
*self.locked.get() = false;
}
#[inline]
pub unsafe fn try_lock(&self) -> bool {
let locked = self.locked.get();
if *locked {
false
} else {
*locked = true;
true
}
}
#[inline]
pub unsafe fn destroy(&self) {
}
}
// FIXME
pub struct ReentrantMutex {
}
impl ReentrantMutex {
pub unsafe fn uninitialized() -> ReentrantMutex {
ReentrantMutex { }
}
pub unsafe fn init(&mut self) {}
pub unsafe fn lock(&self) {}
#[inline]
pub unsafe fn try_lock(&self) -> bool {
true
}
pub unsafe fn unlock(&self) {}
pub unsafe fn destroy(&self) {}
}

356
src/libstd/sys/sgx/net.rs Normal file
View File

@ -0,0 +1,356 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use fmt;
use io;
use net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
use time::Duration;
use sys::{unsupported, Void};
use convert::TryFrom;
pub struct TcpStream(Void);
impl TcpStream {
pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
unsupported()
}
pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
unsupported()
}
pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
match self.0 {}
}
pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
match self.0 {}
}
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
match self.0 {}
}
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
match self.0 {}
}
pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
match self.0 {}
}
pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
match self.0 {}
}
pub fn write(&self, _: &[u8]) -> io::Result<usize> {
match self.0 {}
}
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
match self.0 {}
}
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
match self.0 {}
}
pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
match self.0 {}
}
pub fn duplicate(&self) -> io::Result<TcpStream> {
match self.0 {}
}
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
match self.0 {}
}
pub fn nodelay(&self) -> io::Result<bool> {
match self.0 {}
}
pub fn set_ttl(&self, _: u32) -> io::Result<()> {
match self.0 {}
}
pub fn ttl(&self) -> io::Result<u32> {
match self.0 {}
}
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
match self.0 {}
}
pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
match self.0 {}
}
}
impl fmt::Debug for TcpStream {
fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {}
}
}
pub struct TcpListener(Void);
impl TcpListener {
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
unsupported()
}
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
match self.0 {}
}
pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
match self.0 {}
}
pub fn duplicate(&self) -> io::Result<TcpListener> {
match self.0 {}
}
pub fn set_ttl(&self, _: u32) -> io::Result<()> {
match self.0 {}
}
pub fn ttl(&self) -> io::Result<u32> {
match self.0 {}
}
pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
match self.0 {}
}
pub fn only_v6(&self) -> io::Result<bool> {
match self.0 {}
}
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
match self.0 {}
}
pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
match self.0 {}
}
}
impl fmt::Debug for TcpListener {
fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {}
}
}
pub struct UdpSocket(Void);
impl UdpSocket {
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
unsupported()
}
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
match self.0 {}
}
pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
match self.0 {}
}
pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
match self.0 {}
}
pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
match self.0 {}
}
pub fn duplicate(&self) -> io::Result<UdpSocket> {
match self.0 {}
}
pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
match self.0 {}
}
pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
match self.0 {}
}
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
match self.0 {}
}
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
match self.0 {}
}
pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
match self.0 {}
}
pub fn broadcast(&self) -> io::Result<bool> {
match self.0 {}
}
pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
match self.0 {}
}
pub fn multicast_loop_v4(&self) -> io::Result<bool> {
match self.0 {}
}
pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
match self.0 {}
}
pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
match self.0 {}
}
pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
match self.0 {}
}
pub fn multicast_loop_v6(&self) -> io::Result<bool> {
match self.0 {}
}
pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr)
-> io::Result<()> {
match self.0 {}
}
pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32)
-> io::Result<()> {
match self.0 {}
}
pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr)
-> io::Result<()> {
match self.0 {}
}
pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32)
-> io::Result<()> {
match self.0 {}
}
pub fn set_ttl(&self, _: u32) -> io::Result<()> {
match self.0 {}
}
pub fn ttl(&self) -> io::Result<u32> {
match self.0 {}
}
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
match self.0 {}
}
pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
match self.0 {}
}
pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
match self.0 {}
}
pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
match self.0 {}
}
pub fn send(&self, _: &[u8]) -> io::Result<usize> {
match self.0 {}
}
pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
match self.0 {}
}
}
impl fmt::Debug for UdpSocket {
fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {}
}
}
pub struct LookupHost(Void);
impl LookupHost {
pub fn port(&self) -> u16 {
match self.0 {}
}
}
impl Iterator for LookupHost {
type Item = SocketAddr;
fn next(&mut self) -> Option<SocketAddr> {
match self.0 {}
}
}
impl<'a> TryFrom<&'a str> for LookupHost {
type Error = io::Error;
fn try_from(_v: &'a str) -> io::Result<LookupHost> {
unsupported()
}
}
impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
type Error = io::Error;
fn try_from(_v: (&'a str, u16)) -> io::Result<LookupHost> {
unsupported()
}
}
#[allow(bad_style)]
pub mod netc {
pub const AF_INET: u8 = 0;
pub const AF_INET6: u8 = 1;
pub type sa_family_t = u8;
#[derive(Copy, Clone)]
pub struct in_addr {
pub s_addr: u32,
}
#[derive(Copy, Clone)]
pub struct sockaddr_in {
pub sin_family: sa_family_t,
pub sin_port: u16,
pub sin_addr: in_addr,
}
#[derive(Copy, Clone)]
pub struct in6_addr {
pub s6_addr: [u8; 16],
}
#[derive(Copy, Clone)]
pub struct sockaddr_in6 {
pub sin6_family: sa_family_t,
pub sin6_port: u16,
pub sin6_addr: in6_addr,
pub sin6_flowinfo: u32,
pub sin6_scope_id: u32,
}
#[derive(Copy, Clone)]
pub struct sockaddr {
}
pub type socklen_t = usize;
}

120
src/libstd/sys/sgx/os.rs Normal file
View File

@ -0,0 +1,120 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use fortanix_sgx_abi::{Error, RESULT_SUCCESS};
use error::Error as StdError;
use ffi::{OsString, OsStr};
use fmt;
use io;
use path::{self, PathBuf};
use str;
use sys::{unsupported, Void, sgx_ineffective, decode_error_kind};
pub fn errno() -> i32 {
RESULT_SUCCESS
}
pub fn error_string(errno: i32) -> String {
if errno == RESULT_SUCCESS {
"operation succesful".into()
} else if ((Error::UserRangeStart as _)..=(Error::UserRangeEnd as _)).contains(&errno) {
format!("user-specified error {:08x}", errno)
} else {
decode_error_kind(errno).as_str().into()
}
}
pub fn getcwd() -> io::Result<PathBuf> {
unsupported()
}
pub fn chdir(_: &path::Path) -> io::Result<()> {
sgx_ineffective(())
}
pub struct SplitPaths<'a>(&'a Void);
pub fn split_paths(_unparsed: &OsStr) -> SplitPaths {
panic!("unsupported")
}
impl<'a> Iterator for SplitPaths<'a> {
type Item = PathBuf;
fn next(&mut self) -> Option<PathBuf> {
match *self.0 {}
}
}
#[derive(Debug)]
pub struct JoinPathsError;
pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
where I: Iterator<Item=T>, T: AsRef<OsStr>
{
Err(JoinPathsError)
}
impl fmt::Display for JoinPathsError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
"not supported in SGX yet".fmt(f)
}
}
impl StdError for JoinPathsError {
fn description(&self) -> &str {
"not supported in SGX yet"
}
}
pub fn current_exe() -> io::Result<PathBuf> {
unsupported()
}
pub struct Env;
impl Iterator for Env {
type Item = (OsString, OsString);
fn next(&mut self) -> Option<(OsString, OsString)> {
None
}
}
pub fn env() -> Env {
Env
}
pub fn getenv(_k: &OsStr) -> io::Result<Option<OsString>> {
unsupported()
}
pub fn setenv(_k: &OsStr, _v: &OsStr) -> io::Result<()> {
sgx_ineffective(()) // FIXME: this could trigger a panic higher up the stack
}
pub fn unsetenv(_k: &OsStr) -> io::Result<()> {
sgx_ineffective(()) // FIXME: this could trigger a panic higher up the stack
}
pub fn temp_dir() -> PathBuf {
panic!("no filesystem in SGX")
}
pub fn home_dir() -> Option<PathBuf> {
None
}
pub fn exit(code: i32) -> ! {
super::abi::exit_with_code(code as _)
}
pub fn getpid() -> u32 {
panic!("no pids in SGX")
}

View File

@ -0,0 +1,189 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/// The underlying OsString/OsStr implementation on Unix systems: just
/// a `Vec<u8>`/`[u8]`.
use borrow::Cow;
use fmt;
use str;
use mem;
use rc::Rc;
use sync::Arc;
use sys_common::{AsInner, IntoInner};
use sys_common::bytestring::debug_fmt_bytestring;
use core::str::lossy::Utf8Lossy;
#[derive(Clone, Hash)]
pub struct Buf {
pub inner: Vec<u8>
}
pub struct Slice {
pub inner: [u8]
}
impl fmt::Debug for Slice {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
debug_fmt_bytestring(&self.inner, formatter)
}
}
impl fmt::Display for Slice {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter)
}
}
impl fmt::Debug for Buf {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self.as_slice(), formatter)
}
}
impl fmt::Display for Buf {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self.as_slice(), formatter)
}
}
impl IntoInner<Vec<u8>> for Buf {
fn into_inner(self) -> Vec<u8> {
self.inner
}
}
impl AsInner<[u8]> for Buf {
fn as_inner(&self) -> &[u8] {
&self.inner
}
}
impl Buf {
pub fn from_string(s: String) -> Buf {
Buf { inner: s.into_bytes() }
}
#[inline]
pub fn with_capacity(capacity: usize) -> Buf {
Buf {
inner: Vec::with_capacity(capacity)
}
}
#[inline]
pub fn clear(&mut self) {
self.inner.clear()
}
#[inline]
pub fn capacity(&self) -> usize {
self.inner.capacity()
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.inner.reserve(additional)
}
#[inline]
pub fn reserve_exact(&mut self, additional: usize) {
self.inner.reserve_exact(additional)
}
#[inline]
pub fn shrink_to_fit(&mut self) {
self.inner.shrink_to_fit()
}
#[inline]
pub fn shrink_to(&mut self, min_capacity: usize) {
self.inner.shrink_to(min_capacity)
}
pub fn as_slice(&self) -> &Slice {
unsafe { mem::transmute(&*self.inner) }
}
pub fn into_string(self) -> Result<String, Buf> {
String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() } )
}
pub fn push_slice(&mut self, s: &Slice) {
self.inner.extend_from_slice(&s.inner)
}
#[inline]
pub fn into_box(self) -> Box<Slice> {
unsafe { mem::transmute(self.inner.into_boxed_slice()) }
}
#[inline]
pub fn from_box(boxed: Box<Slice>) -> Buf {
let inner: Box<[u8]> = unsafe { mem::transmute(boxed) };
Buf { inner: inner.into_vec() }
}
#[inline]
pub fn into_arc(&self) -> Arc<Slice> {
self.as_slice().into_arc()
}
#[inline]
pub fn into_rc(&self) -> Rc<Slice> {
self.as_slice().into_rc()
}
}
impl Slice {
fn from_u8_slice(s: &[u8]) -> &Slice {
unsafe { mem::transmute(s) }
}
pub fn from_str(s: &str) -> &Slice {
Slice::from_u8_slice(s.as_bytes())
}
pub fn to_str(&self) -> Option<&str> {
str::from_utf8(&self.inner).ok()
}
pub fn to_string_lossy(&self) -> Cow<str> {
String::from_utf8_lossy(&self.inner)
}
pub fn to_owned(&self) -> Buf {
Buf { inner: self.inner.to_vec() }
}
#[inline]
pub fn into_box(&self) -> Box<Slice> {
let boxed: Box<[u8]> = self.inner.into();
unsafe { mem::transmute(boxed) }
}
pub fn empty_box() -> Box<Slice> {
let boxed: Box<[u8]> = Default::default();
unsafe { mem::transmute(boxed) }
}
#[inline]
pub fn into_arc(&self) -> Arc<Slice> {
let arc: Arc<[u8]> = Arc::from(&self.inner);
unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Slice) }
}
#[inline]
pub fn into_rc(&self) -> Rc<Slice> {
let rc: Rc<[u8]> = Rc::from(&self.inner);
unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Slice) }
}
}

View File

@ -0,0 +1,29 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use path::Prefix;
use ffi::OsStr;
#[inline]
pub fn is_sep_byte(b: u8) -> bool {
b == b'/'
}
#[inline]
pub fn is_verbatim_sep(b: u8) -> bool {
b == b'/'
}
pub fn parse_prefix(_: &OsStr) -> Option<Prefix> {
None
}
pub const MAIN_SEP_STR: &'static str = "/";
pub const MAIN_SEP: char = '/';

View File

@ -0,0 +1,35 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use io;
use sys::Void;
pub struct AnonPipe(Void);
impl AnonPipe {
pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
match self.0 {}
}
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
match self.0 {}
}
pub fn diverge(&self) -> ! {
match self.0 {}
}
}
pub fn read2(p1: AnonPipe,
_v1: &mut Vec<u8>,
_p2: AnonPipe,
_v2: &mut Vec<u8>) -> io::Result<()> {
match p1.0 {}
}

View File

@ -0,0 +1,162 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ffi::OsStr;
use fmt;
use io;
use sys::fs::File;
use sys::pipe::AnonPipe;
use sys::{unsupported, Void};
use sys_common::process::{CommandEnv, DefaultEnvKey};
////////////////////////////////////////////////////////////////////////////////
// Command
////////////////////////////////////////////////////////////////////////////////
pub struct Command {
env: CommandEnv<DefaultEnvKey>
}
// passed back to std::process with the pipes connected to the child, if any
// were requested
pub struct StdioPipes {
pub stdin: Option<AnonPipe>,
pub stdout: Option<AnonPipe>,
pub stderr: Option<AnonPipe>,
}
pub enum Stdio {
Inherit,
Null,
MakePipe,
}
impl Command {
pub fn new(_program: &OsStr) -> Command {
Command {
env: Default::default()
}
}
pub fn arg(&mut self, _arg: &OsStr) {
}
pub fn env_mut(&mut self) -> &mut CommandEnv<DefaultEnvKey> {
&mut self.env
}
pub fn cwd(&mut self, _dir: &OsStr) {
}
pub fn stdin(&mut self, _stdin: Stdio) {
}
pub fn stdout(&mut self, _stdout: Stdio) {
}
pub fn stderr(&mut self, _stderr: Stdio) {
}
pub fn spawn(&mut self, _default: Stdio, _needs_stdin: bool)
-> io::Result<(Process, StdioPipes)> {
unsupported()
}
}
impl From<AnonPipe> for Stdio {
fn from(pipe: AnonPipe) -> Stdio {
pipe.diverge()
}
}
impl From<File> for Stdio {
fn from(file: File) -> Stdio {
file.diverge()
}
}
impl fmt::Debug for Command {
fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
Ok(())
}
}
pub struct ExitStatus(Void);
impl ExitStatus {
pub fn success(&self) -> bool {
match self.0 {}
}
pub fn code(&self) -> Option<i32> {
match self.0 {}
}
}
impl Clone for ExitStatus {
fn clone(&self) -> ExitStatus {
match self.0 {}
}
}
impl Copy for ExitStatus {}
impl PartialEq for ExitStatus {
fn eq(&self, _other: &ExitStatus) -> bool {
match self.0 {}
}
}
impl Eq for ExitStatus {
}
impl fmt::Debug for ExitStatus {
fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {}
}
}
impl fmt::Display for ExitStatus {
fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {}
}
}
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct ExitCode(bool);
impl ExitCode {
pub const SUCCESS: ExitCode = ExitCode(false);
pub const FAILURE: ExitCode = ExitCode(true);
pub fn as_i32(&self) -> i32 {
self.0 as i32
}
}
pub struct Process(Void);
impl Process {
pub fn id(&self) -> u32 {
match self.0 {}
}
pub fn kill(&mut self) -> io::Result<()> {
match self.0 {}
}
pub fn wait(&mut self) -> io::Result<ExitStatus> {
match self.0 {}
}
pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
match self.0 {}
}
}

View File

@ -0,0 +1,82 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use cell::UnsafeCell;
pub struct RWLock {
mode: UnsafeCell<isize>,
}
unsafe impl Send for RWLock {}
unsafe impl Sync for RWLock {} // FIXME
impl RWLock {
pub const fn new() -> RWLock {
RWLock {
mode: UnsafeCell::new(0),
}
}
#[inline]
pub unsafe fn read(&self) {
let mode = self.mode.get();
if *mode >= 0 {
*mode += 1;
} else {
rtabort!("rwlock locked for writing");
}
}
#[inline]
pub unsafe fn try_read(&self) -> bool {
let mode = self.mode.get();
if *mode >= 0 {
*mode += 1;
true
} else {
false
}
}
#[inline]
pub unsafe fn write(&self) {
let mode = self.mode.get();
if *mode == 0 {
*mode = -1;
} else {
rtabort!("rwlock locked for reading")
}
}
#[inline]
pub unsafe fn try_write(&self) -> bool {
let mode = self.mode.get();
if *mode == 0 {
*mode = -1;
true
} else {
false
}
}
#[inline]
pub unsafe fn read_unlock(&self) {
*self.mode.get() -= 1;
}
#[inline]
pub unsafe fn write_unlock(&self) {
*self.mode.get() += 1;
}
#[inline]
pub unsafe fn destroy(&self) {
}
}

View File

@ -0,0 +1,23 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub struct Handler;
impl Handler {
pub unsafe fn new() -> Handler {
Handler
}
}
pub unsafe fn init() {
}
pub unsafe fn cleanup() {
}

View File

@ -0,0 +1,73 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use io;
use sys::unsupported;
pub struct Stdin;
pub struct Stdout;
pub struct Stderr;
impl Stdin {
pub fn new() -> io::Result<Stdin> {
Ok(Stdin)
}
pub fn read(&self, _data: &mut [u8]) -> io::Result<usize> {
unsupported()
}
}
impl Stdout {
pub fn new() -> io::Result<Stdout> {
Ok(Stdout)
}
pub fn write(&self, _data: &[u8]) -> io::Result<usize> {
unsupported()
}
pub fn flush(&self) -> io::Result<()> {
Ok(())
}
}
impl Stderr {
pub fn new() -> io::Result<Stderr> {
Ok(Stderr)
}
pub fn write(&self, _data: &[u8]) -> io::Result<usize> {
unsupported()
}
pub fn flush(&self) -> io::Result<()> {
Ok(())
}
}
impl io::Write for Stderr {
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
(&*self).write(data)
}
fn flush(&mut self) -> io::Result<()> {
(&*self).flush()
}
}
pub const STDIN_BUF_SIZE: usize = 0;
pub fn is_ebadf(_err: &io::Error) -> bool {
true
}
pub fn panic_output() -> Option<impl io::Write> {
super::abi::panic::SgxPanicOutput::new()
}

View File

@ -0,0 +1,51 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use boxed::FnBox;
use ffi::CStr;
use io;
use sys::{unsupported, Void};
use time::Duration;
pub struct Thread(Void);
pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
impl Thread {
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
pub unsafe fn new(_stack: usize, _p: Box<dyn FnBox()>)
-> io::Result<Thread>
{
unsupported()
}
pub fn yield_now() {
// do nothing
}
pub fn set_name(_name: &CStr) {
// nope
}
pub fn sleep(_dur: Duration) {
panic!("can't sleep");
}
pub fn join(self) {
match self.0 {}
}
}
pub mod guard {
pub type Guard = !;
pub unsafe fn current() -> Option<Guard> { None }
pub unsafe fn init() -> Option<Guard> { None }
pub unsafe fn deinit() {}
}

View File

@ -0,0 +1,50 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use boxed::Box;
use ptr;
pub type Key = usize;
struct Allocated {
value: *mut u8,
dtor: Option<unsafe extern fn(*mut u8)>,
}
#[inline]
pub unsafe fn create(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
Box::into_raw(Box::new(Allocated {
value: ptr::null_mut(),
dtor,
})) as usize
}
#[inline]
pub unsafe fn set(key: Key, value: *mut u8) {
(*(key as *mut Allocated)).value = value;
}
#[inline]
pub unsafe fn get(key: Key) -> *mut u8 {
(*(key as *mut Allocated)).value
}
#[inline]
pub unsafe fn destroy(key: Key) {
let key = Box::from_raw(key as *mut Allocated);
if let Some(f) = key.dtor {
f(key.value);
}
}
#[inline]
pub fn requires_synchronized_create() -> bool {
false
}

View File

@ -0,0 +1,61 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use time::Duration;
use sys::unsupported_err;
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct Instant(Duration);
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct SystemTime(Duration);
pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0));
impl Instant {
pub fn now() -> Instant {
panic!("{}", unsupported_err());
}
pub fn sub_instant(&self, other: &Instant) -> Duration {
self.0 - other.0
}
pub fn add_duration(&self, other: &Duration) -> Instant {
Instant(self.0 + *other)
}
pub fn sub_duration(&self, other: &Duration) -> Instant {
Instant(self.0 - *other)
}
}
impl SystemTime {
pub fn now() -> SystemTime {
panic!("{}", unsupported_err());
}
pub fn sub_time(&self, other: &SystemTime)
-> Result<Duration, Duration> {
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
}
pub fn add_duration(&self, other: &Duration) -> SystemTime {
SystemTime(self.0 + *other)
}
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
self.0.checked_add(*other).map(|d| SystemTime(d))
}
pub fn sub_duration(&self, other: &Duration) -> SystemTime {
SystemTime(self.0 - *other)
}
}

View File

@ -57,9 +57,11 @@ pub mod bytestring;
pub mod process;
cfg_if! {
if #[cfg(any(target_os = "cloudabi", target_os = "l4re", target_os = "redox"))] {
pub use sys::net;
} else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] {
if #[cfg(any(target_os = "cloudabi",
target_os = "l4re",
target_os = "redox",
all(target_arch = "wasm32", not(target_os = "emscripten")),
target_env = "sgx"))] {
pub use sys::net;
} else {
pub mod net;

View File

@ -1018,10 +1018,12 @@ fn use_color(opts: &TestOpts) -> bool {
}
}
#[cfg(any(target_os = "cloudabi", target_os = "redox",
all(target_arch = "wasm32", not(target_os = "emscripten"))))]
#[cfg(any(target_os = "cloudabi",
target_os = "redox",
all(target_arch = "wasm32", not(target_os = "emscripten")),
target_env = "sgx"))]
fn stdout_isatty() -> bool {
// FIXME: Implement isatty on Redox
// FIXME: Implement isatty on Redox and SGX
false
}
#[cfg(unix)]
@ -1246,7 +1248,7 @@ fn get_concurrency() -> usize {
1
}
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
#[cfg(any(all(target_arch = "wasm32", not(target_os = "emscripten")), target_env = "sgx"))]
fn num_cpus() -> usize {
1
}

View File

@ -26,7 +26,10 @@ mod macros;
cfg_if! {
if #[cfg(target_env = "msvc")] {
// no extra unwinder support needed
} else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] {
} else if #[cfg(any(
all(target_arch = "wasm32", not(target_os = "emscripten")),
target_env = "sgx"
))] {
// no unwinder on the system!
} else {
extern crate libc;

1
src/rust-sgx Submodule

@ -0,0 +1 @@
Subproject commit 9656260888095f44830641ca7bb3da609a793451

View File

@ -0,0 +1,14 @@
[package]
name = "fortanix-sgx-abi"
version = "0.0.0"
authors = ["The Rust Project Developers"]
[lib]
path = "../../rust-sgx/fortanix-sgx-abi/src/lib.rs"
test = false
bench = false
doc = false
[dependencies]
core = { path = "../../libcore" }
compiler_builtins = { path = "../../rustc/compiler_builtins_shim" }

@ -1 +1 @@
Subproject commit 0309be1ade6bf61066f2c69f77ac3567b7dc31b5
Subproject commit 5e628c5120c619a22799187371f057ec41e06f87

View File

@ -76,6 +76,7 @@ fn filter_dirs(path: &Path) -> bool {
"src/tools/lldb",
"src/target",
"src/stdsimd",
"src/rust-sgx",
"target",
"vendor",
];