about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/bootstrap/native.rs10
-rw-r--r--src/test/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs17
-rw-r--r--src/test/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs12
-rw-r--r--src/test/assembly/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs41
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile23
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_asm.checks8
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c.checks6
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c_asm.checks15
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx.checks6
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx_asm.checks16
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_asm.checks7
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c.checks6
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_asm.checks16
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_global_asm.checks2
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx.checks6
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_asm.checks16
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks2
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/Cargo.toml13
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs30
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo.c18
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_asm.s7
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_cxx.cpp21
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/CMakeLists.txt33
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo.c26
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_asm.s7
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_cxx.cpp29
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs48
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/jumpto.checks8
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/print.checks7
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/rust_plus_one_global_asm.checks2
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh57
-rw-r--r--src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/unw_getcontext.checks6
32 files changed, 519 insertions, 2 deletions
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index bdc58bfbb75..6bba00ee85e 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -630,7 +630,14 @@ impl Step for TestHelpers {
         if builder.config.dry_run {
             return;
         }
-        let target = self.target;
+        // The x86_64-fortanix-unknown-sgx target doesn't have a working C
+        // toolchain. However, some x86_64 ELF objects can be linked
+        // without issues. Use this hack to compile the test helpers.
+        let target = if self.target == "x86_64-fortanix-unknown-sgx" {
+            TargetSelection::from_user("x86_64-unknown-linux-gnu")
+        } else {
+            self.target
+        };
         let dst = builder.test_helpers_out(target);
         let src = builder.src.join("src/test/auxiliary/rust_test_helpers.c");
         if up_to_date(&src, &dst.join("librust_test_helpers.a")) {
@@ -654,7 +661,6 @@ impl Step for TestHelpers {
             }
             cfg.compiler(builder.cc(target));
         }
-
         cfg.cargo_metadata(false)
             .out_dir(&dst)
             .target(&target.triple)
diff --git a/src/test/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs b/src/test/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs
new file mode 100644
index 00000000000..79d82cf70d3
--- /dev/null
+++ b/src/test/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-load.rs
@@ -0,0 +1,17 @@
+// Test LVI load hardening on SGX enclave code
+
+// assembly-output: emit-asm
+// compile-flags: --crate-type staticlib
+// only-x86_64-fortanix-unknown-sgx
+
+#[no_mangle]
+pub extern fn plus_one(r: &mut u64) {
+    *r = *r + 1;
+}
+
+// CHECK: plus_one
+// CHECK: lfence
+// CHECK-NEXT: addq
+// CHECK: popq [[REGISTER:%[a-z]+]]
+// CHECK-NEXT: lfence
+// CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/src/test/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs b/src/test/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs
new file mode 100644
index 00000000000..a21ef6b7589
--- /dev/null
+++ b/src/test/assembly/x86_64-fortanix-unknown-sgx-lvi-generic-ret.rs
@@ -0,0 +1,12 @@
+// Test LVI ret hardening on generic rust code
+
+// assembly-output: emit-asm
+// compile-flags: --crate-type staticlib
+// only-x86_64-fortanix-unknown-sgx
+
+#[no_mangle]
+pub extern fn myret() {}
+// CHECK: myret:
+// CHECK: popq [[REGISTER:%[a-z]+]]
+// CHECK-NEXT: lfence
+// CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/src/test/assembly/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs b/src/test/assembly/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs
new file mode 100644
index 00000000000..7e440169edb
--- /dev/null
+++ b/src/test/assembly/x86_64-fortanix-unknown-sgx-lvi-inline-assembly.rs
@@ -0,0 +1,41 @@
+// Test LVI load hardening on SGX inline assembly code
+
+// assembly-output: emit-asm
+// compile-flags: --crate-type staticlib
+// only-x86_64-fortanix-unknown-sgx
+
+#![feature(asm)]
+
+#[no_mangle]
+pub extern fn get(ptr: *const u64) -> u64 {
+    let value : u64;
+    unsafe {
+        asm!(".start_inline_asm:",
+            "mov {}, [{}]",
+            ".end_inline_asm:",
+            out(reg) value,
+            in(reg) ptr);
+    }
+    value
+}
+
+// CHECK: get
+// CHECK: .start_inline_asm
+// CHECK-NEXT: movq
+// CHECK-NEXT: lfence
+// CHECK-NEXT: .end_inline_asm
+
+#[no_mangle]
+pub extern fn myret() {
+    unsafe {
+        asm!(".start_myret_inline_asm:
+            ret
+            .end_myret_inline_asm:");
+    }
+}
+
+// CHECK: myret
+// CHECK: .start_myret_inline_asm
+// CHECK-NEXT: shlq $0, (%rsp)
+// CHECK-NEXT: lfence
+// CHECK-NEXT: retq
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile
new file mode 100644
index 00000000000..6a04d343910
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/Makefile
@@ -0,0 +1,23 @@
+-include ../../run-make-fulldeps/tools.mk
+
+#only-x86_64-fortanix-unknown-sgx
+
+# For cargo setting
+export RUSTC := $(RUSTC_ORIGINAL)
+export LD_LIBRARY_PATH := $(HOST_RPATH_DIR)
+# We need to be outside of 'src' dir in order to run cargo
+export WORK_DIR := $(TMPDIR)
+export TEST_DIR := $(shell pwd)
+
+## clean up unused env variables which might cause harm.
+unexport RUSTC_LINKER
+unexport RUSTC_BOOTSTRAP
+unexport RUST_BUILD_STAGE
+unexport RUST_TEST_THREADS
+unexport RUST_TEST_TMPDIR
+unexport AR
+unexport CC
+unexport CXX
+
+all:
+	bash script.sh
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_asm.checks
new file mode 100644
index 00000000000..e839c200bbb
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_asm.checks
@@ -0,0 +1,8 @@
+CHECK: cc_plus_one_asm
+CHECK-NEXT: movl
+CHECK-NEXT: lfence
+CHECK-NEXT: inc
+CHECK-NEXT: notq (%rsp)
+CHECK-NEXT: notq (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c.checks
new file mode 100644
index 00000000000..b93b33afb3f
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c.checks
@@ -0,0 +1,6 @@
+CHECK: cc_plus_one_c
+CHECK:      lfence
+CHECK:      popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c_asm.checks
new file mode 100644
index 00000000000..d1fae3d495f
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_c_asm.checks
@@ -0,0 +1,15 @@
+CHECK: cc_plus_one_c_asm
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK-NEXT: incl
+CHECK-NEXT: jmp
+CHECK-NEXT: shlq    $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
+CHECK:      popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx.checks
new file mode 100644
index 00000000000..f96f152c02f
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx.checks
@@ -0,0 +1,6 @@
+CHECK: cc_plus_one_cxx
+CHECK:      lfence
+CHECK:      popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx_asm.checks
new file mode 100644
index 00000000000..e704bf41724
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cc_plus_one_cxx_asm.checks
@@ -0,0 +1,16 @@
+CHECK: cc_plus_one_cxx_asm
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      movl
+CHECK:      lfence
+CHECK:      lfence
+CHECK-NEXT: incl
+CHECK-NEXT: jmp     0x{{[[:xdigit:]]+}} <cc_plus_one_cxx_asm+0x{{[[:xdigit:]]+}}>
+CHECK-NEXT: shlq    $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
+CHECK:      popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_asm.checks
new file mode 100644
index 00000000000..78b18ccbfcb
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_asm.checks
@@ -0,0 +1,7 @@
+CHECK: cmake_plus_one_asm
+CHECK-NEXT: movl
+CHECK-NEXT: lfence
+CHECK-NEXT: incl
+CHECK-NEXT: shlq    $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c.checks
new file mode 100644
index 00000000000..f551356b2ff
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c.checks
@@ -0,0 +1,6 @@
+CHECK: cmake_plus_one_c
+CHECK:      lfence
+CHECK:      popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_asm.checks
new file mode 100644
index 00000000000..87c806f137a
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_asm.checks
@@ -0,0 +1,16 @@
+CHECK: cmake_plus_one_c_asm
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      movl
+CHECK:      lfence
+CHECK-NEXT: incl
+CHECK-NEXT: jmp     0x{{[[:xdigit:]]+}} <cmake_plus_one_c_asm+0x{{[[:xdigit:]]+}}>
+CHECK-NEXT: shlq    $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
+CHECK:      popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_global_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_global_asm.checks
new file mode 100644
index 00000000000..4b66cc5bc83
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_c_global_asm.checks
@@ -0,0 +1,2 @@
+CHECK: cmake_plus_one_c_global_asm
+CHECK: lfence
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx.checks
new file mode 100644
index 00000000000..0f403e0203c
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx.checks
@@ -0,0 +1,6 @@
+CHECK: cmake_plus_one_cxx
+CHECK:      lfence
+CHECK:      popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_asm.checks
new file mode 100644
index 00000000000..9cac8711ea8
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_asm.checks
@@ -0,0 +1,16 @@
+CHECK: cmake_plus_one_cxx_asm
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      movl
+CHECK:      lfence
+CHECK-NEXT: incl
+CHECK-NEXT: jmp     0x{{[[:xdigit:]]+}} <cmake_plus_one_cxx_asm+0x{{[[:xdigit:]]+}}>
+CHECK-NEXT: shlq    $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
+CHECK:      popq
+CHECK-NEXT: popq [[REGISTER:%[a-z]+]]
+CHECK-NEXT: lfence
+CHECK-NEXT: jmpq *[[REGISTER]]
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks
new file mode 100644
index 00000000000..d4a3d447901
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/cmake_plus_one_cxx_global_asm.checks
@@ -0,0 +1,2 @@
+CHECK: cmake_plus_one_cxx_global_asm
+CHECK: lfence
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/Cargo.toml b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/Cargo.toml
new file mode 100644
index 00000000000..89490686584
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/Cargo.toml
@@ -0,0 +1,13 @@
+[package]
+name = "enclave"
+version = "0.1.0"
+authors = ["Raoul Strackx <raoul.strackx@fortanix.com>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+
+[build-dependencies]
+cc = "1.0"
+cmake = "0.1"
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs
new file mode 100644
index 00000000000..3a7aa1be868
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/build.rs
@@ -0,0 +1,30 @@
+fn main() {
+    cc::Build::new()
+        .file("foo.c")
+        .compile("foo_c");
+
+    cc::Build::new()
+        .file("foo_asm.s")
+        .compile("foo_asm");
+
+    cc::Build::new()
+        .cpp(true)
+        .cpp_set_stdlib(None)
+        .file("foo_cxx.cpp")
+        .compile("foo_cxx");
+
+    // When the cmake crate detects the clang compiler, it passes the
+    //  "--target" argument to the linker which subsequently fails. The
+    //  `CMAKE_C_COMPILER_FORCED` option makes sure that `cmake` does not
+    //  tries to test the compiler. From version 3.6 the option
+    //  `CMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY` can be used
+    //  https://cmake.org/cmake/help/v3.5/module/CMakeForceCompiler.html
+    let dst = cmake::Config::new("libcmake_foo")
+                .build_target("cmake_foo")
+                .define("CMAKE_C_COMPILER_FORCED", "1")
+                .define("CMAKE_CXX_COMPILER_FORCED", "1")
+                .define("CMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY", "1")
+                .build();
+    println!("cargo:rustc-link-search=native={}/build/", dst.display());
+    println!("cargo:rustc-link-lib=static=cmake_foo");
+}
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo.c b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo.c
new file mode 100644
index 00000000000..dd76d4f303a
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo.c
@@ -0,0 +1,18 @@
+int cc_plus_one_c(int *arg) {
+    return *arg + 1;
+}
+
+int cc_plus_one_c_asm(int *arg) {
+    int value = 0;
+
+    asm volatile ( "    movl (%1), %0\n"
+                   "    inc %0\n"
+                   "    jmp 1f\n"
+                   "    retq\n"  // never executed, but a shortcut to determine how
+                                 // the assembler deals with `ret` instructions
+                   "1:\n"
+                   : "=r"(value)
+                   : "r"(arg) );
+
+    return value;
+}
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_asm.s b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_asm.s
new file mode 100644
index 00000000000..6d56214e87e
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_asm.s
@@ -0,0 +1,7 @@
+    .text
+    .global cc_plus_one_asm
+    .type cc_plus_one_asm, @function
+cc_plus_one_asm:
+    movl (%rdi), %eax
+    inc %eax
+    retq
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_cxx.cpp b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_cxx.cpp
new file mode 100644
index 00000000000..ac6f64ac413
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/foo_cxx.cpp
@@ -0,0 +1,21 @@
+extern "C" int cc_plus_one_cxx(int *arg);
+extern "C" int cc_plus_one_cxx_asm(int *arg);
+
+int cc_plus_one_cxx(int *arg) {
+    return *arg + 1;
+}
+
+int cc_plus_one_cxx_asm(int *arg) {
+    int value = 0;
+
+    asm volatile ( "    movl (%1), %0\n"
+                   "    inc %0\n"
+                   "    jmp 1f\n"
+                   "    retq\n"  // never executed, but a shortcut to determine how
+                                 // the assembler deals with `ret` instructions
+                   "1:\n"
+                   : "=r"(value)
+                   : "r"(arg) );
+
+    return value;
+}
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/CMakeLists.txt b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/CMakeLists.txt
new file mode 100644
index 00000000000..27cdf2ecf82
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/CMakeLists.txt
@@ -0,0 +1,33 @@
+enable_language(C CXX ASM)
+
+set(C_SOURCES
+    src/foo.c
+    )
+
+set_source_files_properties(${C_SOURCES}
+                            PROPERTIES
+                            LANGUAGE C)
+
+set(CXX_SOURCES
+    src/foo_cxx.cpp
+    )
+
+set_source_files_properties(${CXX_SOURCES}
+                            PROPERTIES
+                            LANGUAGE CXX)
+
+set(ASM_SOURCES
+    src/foo_asm.s
+    )
+
+set_source_files_properties(${ASM_SOURCES}
+                            PROPERTIES
+                            LANGUAGE ASM)
+
+set(SOURCES
+    ${C_SOURCES}
+    ${CXX_SOURCES}
+    ${ASM_SOURCES})
+        
+add_library(cmake_foo STATIC
+    ${SOURCES})
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo.c b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo.c
new file mode 100644
index 00000000000..c3b731a2d50
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo.c
@@ -0,0 +1,26 @@
+int cmake_plus_one_c(int *arg) {
+    return *arg + 1;
+}
+
+int cmake_plus_one_c_asm(int *arg) {
+    int value = 0;
+
+    asm volatile ( "    movl (%1), %0\n"
+                   "    inc %0\n"
+                   "    jmp 1f\n"
+                   "    retq\n"  // never executed, but a shortcut to determine how
+                                 // the assembler deals with `ret` instructions
+                   "1:\n"
+                   : "=r"(value)
+                   : "r"(arg) );
+
+    return value;
+}
+
+asm(".text\n"
+"    .global cmake_plus_one_c_global_asm\n"
+"    .type cmake_plus_one_c_global_asm, @function\n"
+"cmake_plus_one_c_global_asm:\n"
+"    movl (%rdi), %eax\n"
+"    inc %eax\n"
+"    retq\n" );
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_asm.s b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_asm.s
new file mode 100644
index 00000000000..64b6b430eea
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_asm.s
@@ -0,0 +1,7 @@
+    .text
+    .global cmake_plus_one_asm
+    .type cmake_plus_one_asm, @function
+cmake_plus_one_asm:
+    movl (%rdi), %eax
+    inc %eax
+    retq
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_cxx.cpp b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_cxx.cpp
new file mode 100644
index 00000000000..824e2afebcc
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/libcmake_foo/src/foo_cxx.cpp
@@ -0,0 +1,29 @@
+extern "C" int cmake_plus_one_cxx(int *arg);
+extern "C" int cmake_plus_one_cxx_asm(int *arg);
+
+int cmake_plus_one_cxx(int *arg) {
+    return *arg + 1;
+}
+
+int cmake_plus_one_cxx_asm(int *arg) {
+    int value = 0;
+
+    asm volatile ( "    movl (%1), %0\n"
+                   "    inc %0\n"
+                   "    jmp 1f\n"
+                   "    retq\n"  // never executed, but a shortcut to determine how
+                                 // the assembler deals with `ret` instructions
+                   "1:\n"
+                   : "=r"(value)
+                   : "r"(arg) );
+
+    return value;
+}
+
+asm(".text\n"
+"    .global cmake_plus_one_cxx_global_asm\n"
+"    .type cmake_plus_one_cxx_global_asm, @function\n"
+"cmake_plus_one_cxx_global_asm:\n"
+"    movl (%rdi), %eax\n"
+"    inc %eax\n"
+"    retq\n" );
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs
new file mode 100644
index 00000000000..8e91a8d842c
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/enclave/src/main.rs
@@ -0,0 +1,48 @@
+#![feature(global_asm)]
+
+global_asm!( r#"
+    .text
+    .global rust_plus_one_global_asm
+    .type rust_plus_one_global_asm, @function
+rust_plus_one_global_asm:
+    movl (%rdi), %eax
+    inc %eax
+    retq
+"# );
+
+extern {
+    fn cc_plus_one_c(arg : &u32) -> u32;
+    fn cc_plus_one_c_asm(arg : &u32) -> u32;
+    fn cc_plus_one_cxx(arg : &u32) -> u32;
+    fn cc_plus_one_cxx_asm(arg : &u32) -> u32;
+    fn cc_plus_one_asm(arg : &u32) -> u32;
+    fn cmake_plus_one_c(arg : &u32) -> u32;
+    fn cmake_plus_one_c_asm(arg : &u32) -> u32;
+    fn cmake_plus_one_cxx(arg : &u32) -> u32;
+    fn cmake_plus_one_cxx_asm(arg : &u32) -> u32;
+    fn cmake_plus_one_c_global_asm(arg : &u32) -> u32;
+    fn cmake_plus_one_cxx_global_asm(arg : &u32) -> u32;
+    fn cmake_plus_one_asm(arg : &u32) -> u32;
+    fn rust_plus_one_global_asm(arg : &u32) -> u32;
+}
+
+fn main() {
+    let value : u32 = 41;
+    let question = "Answer to the Ultimate Question of Life, the Universe, and Everything:";
+
+    unsafe{
+        println!("{}: {}!", question,rust_plus_one_global_asm(&value));
+        println!("{}: {}!", question,cc_plus_one_c(&value));
+        println!("{}: {}!", question,cc_plus_one_c_asm(&value));
+        println!("{}: {}!", question,cc_plus_one_cxx(&value));
+        println!("{}: {}!", question,cc_plus_one_cxx_asm(&value));
+        println!("{}: {}!", question,cc_plus_one_asm(&value));
+        println!("{}: {}!", question,cmake_plus_one_c(&value));
+        println!("{}: {}!", question,cmake_plus_one_c_asm(&value));
+        println!("{}: {}!", question,cmake_plus_one_cxx(&value));
+        println!("{}: {}!", question,cmake_plus_one_cxx_asm(&value));
+        println!("{}: {}!", question,cmake_plus_one_c_global_asm(&value));
+        println!("{}: {}!", question,cmake_plus_one_cxx_global_asm(&value));
+        println!("{}: {}!", question,cmake_plus_one_asm(&value));
+    }
+}
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/jumpto.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/jumpto.checks
new file mode 100644
index 00000000000..15211e3ade7
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/jumpto.checks
@@ -0,0 +1,8 @@
+CHECK: libunwind::Registers_x86_64::jumpto
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      shlq    $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/print.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/print.checks
new file mode 100644
index 00000000000..0fe88141b24
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/print.checks
@@ -0,0 +1,7 @@
+CHECK: print
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      popq
+CHECK:      callq 0x{{[[:xdigit:]]*}} <_Unwind_Resume>
+CHECK-NEXT: ud2
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/rust_plus_one_global_asm.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/rust_plus_one_global_asm.checks
new file mode 100644
index 00000000000..fe6777537fb
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/rust_plus_one_global_asm.checks
@@ -0,0 +1,2 @@
+CHECK: rust_plus_one_global_asm
+CHECK: lfence
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh
new file mode 100644
index 00000000000..ec93c980160
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh
@@ -0,0 +1,57 @@
+set -exuo pipefail
+
+function build {
+    CRATE=enclave
+
+    mkdir -p $WORK_DIR
+    pushd $WORK_DIR
+        rm -rf $CRATE
+        cp -a $TEST_DIR/enclave .
+        pushd $CRATE
+            echo ${WORK_DIR}
+            # HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features.
+            # These come from the top-level Rust workspace, that this crate is not a
+            # member of, but Cargo tries to load the workspace `Cargo.toml` anyway.
+            env RUSTC_BOOTSTRAP=1
+                cargo -v run --target $TARGET
+        popd
+    popd
+}
+
+function check {
+    local func=$1
+    local checks="${TEST_DIR}/$2"
+    local asm=$(mktemp)
+    local objdump="${BUILD_DIR}/x86_64-unknown-linux-gnu/llvm/build/bin/llvm-objdump"
+    local filecheck="${BUILD_DIR}/x86_64-unknown-linux-gnu/llvm/build/bin/FileCheck"
+
+    ${objdump} --disassemble-symbols=${func} --demangle \
+      ${WORK_DIR}/enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave > ${asm}
+    ${filecheck} --input-file ${asm} ${checks}
+}
+
+build
+
+check unw_getcontext unw_getcontext.checks
+check "libunwind::Registers_x86_64::jumpto()" jumpto.checks
+check "std::io::stdio::_print::h87f0c238421c45bc" print.checks
+check rust_plus_one_global_asm rust_plus_one_global_asm.checks \
+  || echo "warning: module level assembly currently not hardened"
+
+check cc_plus_one_c cc_plus_one_c.checks
+check cc_plus_one_c_asm cc_plus_one_c_asm.checks
+check cc_plus_one_cxx cc_plus_one_cxx.checks
+check cc_plus_one_cxx_asm cc_plus_one_cxx_asm.checks
+check cc_plus_one_asm cc_plus_one_asm.checks \
+  || echo "warning: the cc crate forwards assembly files to the CC compiler." \
+           "Clang uses its own intergrated assembler, which does not include the LVI passes."
+
+check cmake_plus_one_c cmake_plus_one_c.checks
+check cmake_plus_one_c_asm cmake_plus_one_c_asm.checks
+check cmake_plus_one_c_global_asm cmake_plus_one_c_global_asm.checks \
+  || echo "warning: module level assembly currently not hardened"
+check cmake_plus_one_cxx cmake_plus_one_cxx.checks
+check cmake_plus_one_cxx_asm cmake_plus_one_cxx_asm.checks
+check cmake_plus_one_cxx_global_asm cmake_plus_one_cxx_global_asm.checks \
+  || echo "warning: module level assembly currently not hardened"
+check cmake_plus_one_asm cmake_plus_one_asm.checks
diff --git a/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/unw_getcontext.checks b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/unw_getcontext.checks
new file mode 100644
index 00000000000..4b7615b115d
--- /dev/null
+++ b/src/test/run-make/x86_64-fortanix-unknown-sgx-lvi/unw_getcontext.checks
@@ -0,0 +1,6 @@
+CHECK: unw_getcontext
+CHECK:      lfence
+CHECK:      lfence
+CHECK:      shlq    $0, (%rsp)
+CHECK-NEXT: lfence
+CHECK-NEXT: retq