Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding unwinding support for x86_64_fortanix_unknown_sgx target. #56979

Merged

Conversation

VardhanThigle
Copy link

Unwinding support is provided by our port of LLVM's libunwind which is available from https://github.com/fortanix/libunwind/tree/release_50.

libunwind requires support for rwlock and printing to stderr, which is only provided by std for this target. This poses two problems: 1) how to expose the std functionality to C and 2) dependency inversion.

Exposing std

For exposing the functionality we chose to expose the following symbols:

  • __rust_rwlock_rdlock
  • __rust_rwlock_wrlock
  • __rust_rwlock_unlock
  • __rust_print_err
  • __rust_abort

Also, the following are needed from alloc:

  • __rust_alloc
  • __rust_dealloc

Rust RWLock in C

In libunwind, RWLock is initialized as a templated static variable:

pthread_rwlock_t DwarfFDECache<A>::_lock = PTHREAD_RWLOCK_INITIALIZER;

I don't know of a good way to use the Rust sys::rwlock::RWLock type and initializer there. We could have a static global variable in Rust, but that doesn't work with the templating. The variable needs to be initialized statically, since this target doesn't support the .init section. Currently, I just used a byte array and standard C array initialization. The mapping between this C type and the Rust type needs to be manually maintained. There is a compile-time check and a unit test to make sure the Rust versions of these C definitions match the actual Rust type. If any reviewer knows of a better solution, please do tell.

Dependency inversion issue

std depends on panic_unwind which depends on libunwind, and libunwind depends on std. This is not normally supported by Rust's linking system. Therefore we use raw C exports from std and libunwind.a is linked last in the target post_link_objects instead of being built as part of the Rust libunwind. Currently, all C exports are defined in src/libstd/sys/sgx/rwlock.rs to overcome LTO issues. Only the __rust_rwlock_* definitions need to live there for privacy reasons. Once again, if any reviewer knows of a better solution, please do tell.

r? @alexcrichton

@rust-highfive
Copy link
Collaborator

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @alexcrichton (or someone else) soon.

If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes.

Please see the contribution instructions for more information.

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Dec 19, 2018
@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-6.0 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
travis_time:end:04ec8e44:start=1545222668182686871,finish=1545222768251413858,duration=100068726987
$ git checkout -qf FETCH_HEAD
travis_fold:end:git.checkout

Encrypted environment variables have been removed for security reasons.
See https://docs.travis-ci.com/user/pull-requests/#pull-requests-and-security-restrictions
$ export SCCACHE_BUCKET=rust-lang-ci-sccache2
$ export SCCACHE_REGION=us-west-1
Setting environment variables from .travis.yml
$ export IMAGE=x86_64-gnu-llvm-6.0
---

[00:03:01] travis_fold:start:tidy
travis_time:start:tidy
tidy check
[00:03:01] tidy error: /checkout/src/libstd/sys/sgx/rwlock.rs:228: trailing whitespace
[00:03:02] some tidy checks failed
[00:03:02] 
[00:03:02] 
[00:03:02] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/tidy" "/checkout/src" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "--no-vendor" "--quiet"
[00:03:02] 
[00:03:02] 
[00:03:02] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test src/tools/tidy
[00:03:02] Build completed unsuccessfully in 0:00:43
[00:03:02] Build completed unsuccessfully in 0:00:43
[00:03:02] Makefile:79: recipe for target 'tidy' failed
[00:03:02] make: *** [tidy] Error 1
The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:1bc56118
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)
Wed Dec 19 12:35:59 UTC 2018
---
travis_time:end:17350ff4:start=1545222959795432139,finish=1545222959799395270,duration=3963131
travis_fold:end:after_failure.3
travis_fold:start:after_failure.4
travis_time:start:06f78d38
$ ln -s . checkout && for CORE in obj/cores/core.*; do EXE=$(echo $CORE | sed 's|obj/cores/core\.[0-9]*\.!checkout!\(.*\)|\1|;y|!|/|'); if [ -f "$EXE" ]; then printf travis_fold":start:crashlog\n\033[31;1m%s\033[0m\n" "$CORE"; gdb --batch -q -c "$CORE" "$EXE" -iex 'set auto-load off' -iex 'dir src/' -iex 'set sysroot .' -ex bt -ex q; echo travis_fold":"end:crashlog; fi; done || true
travis_fold:end:after_failure.4
travis_fold:start:after_failure.5
travis_time:start:193df331
travis_time:start:193df331
$ cat ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers || true
cat: ./obj/build/x86_64-unknown-linux-gnu/native/asan/build/lib/asan/clang_rt.asan-dynamic-i386.vers: No such file or directory
travis_fold:end:after_failure.5
travis_fold:start:after_failure.6
travis_time:start:06a4dce4
$ dmesg | grep -i kill

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@alexcrichton
Copy link
Member

@bors: r+

@bors
Copy link
Contributor

bors commented Dec 19, 2018

📌 Commit 885cf2a has been approved by alexcrichton

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Dec 19, 2018
@alexcrichton
Copy link
Member

@bors: rollup

pietroalbini added a commit to pietroalbini/rust that referenced this pull request Dec 20, 2018
…nd-support, r=alexcrichton

Adding unwinding support for x86_64_fortanix_unknown_sgx target.

Unwinding support is provided by our port of LLVM's libunwind which is available from https://github.com/fortanix/libunwind/tree/release_50.

libunwind requires support for rwlock and printing to stderr, which is only provided by `std` for this target. This poses two problems: 1) how to expose the `std` functionality to C and 2) dependency inversion.

### Exposing `std`

For exposing the functionality we chose to expose the following symbols:

* __rust_rwlock_rdlock
* __rust_rwlock_wrlock
* __rust_rwlock_unlock
* __rust_print_err
* __rust_abort

Also, the following are needed from `alloc`:

* __rust_alloc
* __rust_dealloc

#### Rust RWLock in C

In `libunwind`, RWLock is initialized as a templated static variable:

```c
pthread_rwlock_t DwarfFDECache<A>::_lock = PTHREAD_RWLOCK_INITIALIZER;
```

I don't know of a good way to use the Rust sys::rwlock::RWLock type and initializer there. We could have a static global variable in Rust, but that doesn't work with the templating. The variable needs to be initialized statically, since this target doesn't support the .init section. Currently, I just used a byte array and standard C array initialization. The mapping between this C type and the Rust type needs to be manually maintained. There is a compile-time check and a unit test to make sure the Rust versions of these C definitions match the actual Rust type. If any reviewer knows of a better solution, please do tell.

### Dependency inversion issue

`std` depends on `panic_unwind` which depends on `libunwind`, and `libunwind` depends on `std`. This is not normally supported by Rust's linking system. Therefore we use raw C exports from `std` *and* `libunwind.a` is linked last in the target `post_link_objects` instead of being built as part of the Rust `libunwind`. Currently, all C exports are defined in `src/libstd/sys/sgx/rwlock.rs` to overcome LTO issues. Only the `__rust_rwlock_*` definitions *need* to live there for privacy reasons. Once again, if any reviewer knows of a better solution, please do tell.

r? @alexcrichton
Mark-Simulacrum added a commit to Mark-Simulacrum/rust that referenced this pull request Dec 21, 2018
…nd-support, r=alexcrichton

Adding unwinding support for x86_64_fortanix_unknown_sgx target.

Unwinding support is provided by our port of LLVM's libunwind which is available from https://github.com/fortanix/libunwind/tree/release_50.

libunwind requires support for rwlock and printing to stderr, which is only provided by `std` for this target. This poses two problems: 1) how to expose the `std` functionality to C and 2) dependency inversion.

### Exposing `std`

For exposing the functionality we chose to expose the following symbols:

* __rust_rwlock_rdlock
* __rust_rwlock_wrlock
* __rust_rwlock_unlock
* __rust_print_err
* __rust_abort

Also, the following are needed from `alloc`:

* __rust_alloc
* __rust_dealloc

#### Rust RWLock in C

In `libunwind`, RWLock is initialized as a templated static variable:

```c
pthread_rwlock_t DwarfFDECache<A>::_lock = PTHREAD_RWLOCK_INITIALIZER;
```

I don't know of a good way to use the Rust sys::rwlock::RWLock type and initializer there. We could have a static global variable in Rust, but that doesn't work with the templating. The variable needs to be initialized statically, since this target doesn't support the .init section. Currently, I just used a byte array and standard C array initialization. The mapping between this C type and the Rust type needs to be manually maintained. There is a compile-time check and a unit test to make sure the Rust versions of these C definitions match the actual Rust type. If any reviewer knows of a better solution, please do tell.

### Dependency inversion issue

`std` depends on `panic_unwind` which depends on `libunwind`, and `libunwind` depends on `std`. This is not normally supported by Rust's linking system. Therefore we use raw C exports from `std` *and* `libunwind.a` is linked last in the target `post_link_objects` instead of being built as part of the Rust `libunwind`. Currently, all C exports are defined in `src/libstd/sys/sgx/rwlock.rs` to overcome LTO issues. Only the `__rust_rwlock_*` definitions *need* to live there for privacy reasons. Once again, if any reviewer knows of a better solution, please do tell.

r? @alexcrichton
pietroalbini added a commit to pietroalbini/rust that referenced this pull request Dec 21, 2018
…nd-support, r=alexcrichton

Adding unwinding support for x86_64_fortanix_unknown_sgx target.

Unwinding support is provided by our port of LLVM's libunwind which is available from https://github.com/fortanix/libunwind/tree/release_50.

libunwind requires support for rwlock and printing to stderr, which is only provided by `std` for this target. This poses two problems: 1) how to expose the `std` functionality to C and 2) dependency inversion.

### Exposing `std`

For exposing the functionality we chose to expose the following symbols:

* __rust_rwlock_rdlock
* __rust_rwlock_wrlock
* __rust_rwlock_unlock
* __rust_print_err
* __rust_abort

Also, the following are needed from `alloc`:

* __rust_alloc
* __rust_dealloc

#### Rust RWLock in C

In `libunwind`, RWLock is initialized as a templated static variable:

```c
pthread_rwlock_t DwarfFDECache<A>::_lock = PTHREAD_RWLOCK_INITIALIZER;
```

I don't know of a good way to use the Rust sys::rwlock::RWLock type and initializer there. We could have a static global variable in Rust, but that doesn't work with the templating. The variable needs to be initialized statically, since this target doesn't support the .init section. Currently, I just used a byte array and standard C array initialization. The mapping between this C type and the Rust type needs to be manually maintained. There is a compile-time check and a unit test to make sure the Rust versions of these C definitions match the actual Rust type. If any reviewer knows of a better solution, please do tell.

### Dependency inversion issue

`std` depends on `panic_unwind` which depends on `libunwind`, and `libunwind` depends on `std`. This is not normally supported by Rust's linking system. Therefore we use raw C exports from `std` *and* `libunwind.a` is linked last in the target `post_link_objects` instead of being built as part of the Rust `libunwind`. Currently, all C exports are defined in `src/libstd/sys/sgx/rwlock.rs` to overcome LTO issues. Only the `__rust_rwlock_*` definitions *need* to live there for privacy reasons. Once again, if any reviewer knows of a better solution, please do tell.

r? @alexcrichton
bors added a commit that referenced this pull request Dec 21, 2018
Rollup of 20 pull requests

Successful merges:

 - #56802 (Add DoubleEndedIterator::nth_back)
 - #56842 (Add unstable VecDeque::rotate_{left|right})
 - #56869 (Reduce search-index.js size)
 - #56887 (Disable field reordering for repr(int).)
 - #56892 (rustc: Update Clang used to build LLVM on Linux)
 - #56909 (static eval: Do not ICE on layout size overflow)
 - #56914 (Ignore ui/target-feature-gate on sparc, sparc64, powerpc, powerpc64 and powerpc64le)
 - #56917 (Simplify MIR generation for logical operations)
 - #56919 (Remove a wrong multiplier on relocation offset computation)
 - #56933 (Add --progress to git submodule commands in x.py)
 - #56941 (deny intra-doc link resolution failures in libstd)
 - #56964 (Remove `TokenStream::JointTree`.)
 - #56970 (Mem uninit doc ptr drop)
 - #56973 (make basic CTFE tracing available on release builds)
 - #56979 (Adding unwinding support for x86_64_fortanix_unknown_sgx target.)
 - #56981 (miri: allocation is infallible)
 - #56984 (A few tweaks to dropck_outlives)
 - #56989 (Fix compiletest `trim` deprecation warnings)
 - #56992 (suggest similar lint names for unknown lints)
 - #57002 (Stabilize Vec(Deque)::resize_with)

Failed merges:

r? @ghost
bors added a commit that referenced this pull request Dec 21, 2018
Rollup of 20 pull requests

Successful merges:

 - #56802 (Add DoubleEndedIterator::nth_back)
 - #56842 (Add unstable VecDeque::rotate_{left|right})
 - #56869 (Reduce search-index.js size)
 - #56887 (Disable field reordering for repr(int).)
 - #56892 (rustc: Update Clang used to build LLVM on Linux)
 - #56909 (static eval: Do not ICE on layout size overflow)
 - #56914 (Ignore ui/target-feature-gate on sparc, sparc64, powerpc, powerpc64 and powerpc64le)
 - #56917 (Simplify MIR generation for logical operations)
 - #56919 (Remove a wrong multiplier on relocation offset computation)
 - #56933 (Add --progress to git submodule commands in x.py)
 - #56941 (deny intra-doc link resolution failures in libstd)
 - #56964 (Remove `TokenStream::JointTree`.)
 - #56970 (Mem uninit doc ptr drop)
 - #56973 (make basic CTFE tracing available on release builds)
 - #56979 (Adding unwinding support for x86_64_fortanix_unknown_sgx target.)
 - #56981 (miri: allocation is infallible)
 - #56984 (A few tweaks to dropck_outlives)
 - #56989 (Fix compiletest `trim` deprecation warnings)
 - #56992 (suggest similar lint names for unknown lints)
 - #57002 (Stabilize Vec(Deque)::resize_with)

Failed merges:

r? @ghost
Centril added a commit to Centril/rust that referenced this pull request Dec 22, 2018
…nd-support, r=alexcrichton

Adding unwinding support for x86_64_fortanix_unknown_sgx target.

Unwinding support is provided by our port of LLVM's libunwind which is available from https://github.com/fortanix/libunwind/tree/release_50.

libunwind requires support for rwlock and printing to stderr, which is only provided by `std` for this target. This poses two problems: 1) how to expose the `std` functionality to C and 2) dependency inversion.

### Exposing `std`

For exposing the functionality we chose to expose the following symbols:

* __rust_rwlock_rdlock
* __rust_rwlock_wrlock
* __rust_rwlock_unlock
* __rust_print_err
* __rust_abort

Also, the following are needed from `alloc`:

* __rust_alloc
* __rust_dealloc

#### Rust RWLock in C

In `libunwind`, RWLock is initialized as a templated static variable:

```c
pthread_rwlock_t DwarfFDECache<A>::_lock = PTHREAD_RWLOCK_INITIALIZER;
```

I don't know of a good way to use the Rust sys::rwlock::RWLock type and initializer there. We could have a static global variable in Rust, but that doesn't work with the templating. The variable needs to be initialized statically, since this target doesn't support the .init section. Currently, I just used a byte array and standard C array initialization. The mapping between this C type and the Rust type needs to be manually maintained. There is a compile-time check and a unit test to make sure the Rust versions of these C definitions match the actual Rust type. If any reviewer knows of a better solution, please do tell.

### Dependency inversion issue

`std` depends on `panic_unwind` which depends on `libunwind`, and `libunwind` depends on `std`. This is not normally supported by Rust's linking system. Therefore we use raw C exports from `std` *and* `libunwind.a` is linked last in the target `post_link_objects` instead of being built as part of the Rust `libunwind`. Currently, all C exports are defined in `src/libstd/sys/sgx/rwlock.rs` to overcome LTO issues. Only the `__rust_rwlock_*` definitions *need* to live there for privacy reasons. Once again, if any reviewer knows of a better solution, please do tell.

r? @alexcrichton
kennytm added a commit to kennytm/rust that referenced this pull request Dec 22, 2018
…nd-support, r=alexcrichton

Adding unwinding support for x86_64_fortanix_unknown_sgx target.

Unwinding support is provided by our port of LLVM's libunwind which is available from https://github.com/fortanix/libunwind/tree/release_50.

libunwind requires support for rwlock and printing to stderr, which is only provided by `std` for this target. This poses two problems: 1) how to expose the `std` functionality to C and 2) dependency inversion.

### Exposing `std`

For exposing the functionality we chose to expose the following symbols:

* __rust_rwlock_rdlock
* __rust_rwlock_wrlock
* __rust_rwlock_unlock
* __rust_print_err
* __rust_abort

Also, the following are needed from `alloc`:

* __rust_alloc
* __rust_dealloc

#### Rust RWLock in C

In `libunwind`, RWLock is initialized as a templated static variable:

```c
pthread_rwlock_t DwarfFDECache<A>::_lock = PTHREAD_RWLOCK_INITIALIZER;
```

I don't know of a good way to use the Rust sys::rwlock::RWLock type and initializer there. We could have a static global variable in Rust, but that doesn't work with the templating. The variable needs to be initialized statically, since this target doesn't support the .init section. Currently, I just used a byte array and standard C array initialization. The mapping between this C type and the Rust type needs to be manually maintained. There is a compile-time check and a unit test to make sure the Rust versions of these C definitions match the actual Rust type. If any reviewer knows of a better solution, please do tell.

### Dependency inversion issue

`std` depends on `panic_unwind` which depends on `libunwind`, and `libunwind` depends on `std`. This is not normally supported by Rust's linking system. Therefore we use raw C exports from `std` *and* `libunwind.a` is linked last in the target `post_link_objects` instead of being built as part of the Rust `libunwind`. Currently, all C exports are defined in `src/libstd/sys/sgx/rwlock.rs` to overcome LTO issues. Only the `__rust_rwlock_*` definitions *need* to live there for privacy reasons. Once again, if any reviewer knows of a better solution, please do tell.

r? @alexcrichton
bors added a commit that referenced this pull request Dec 22, 2018
Rollup of 25 pull requests

Successful merges:

 - #56802 (Add DoubleEndedIterator::nth_back)
 - #56909 (static eval: Do not ICE on layout size overflow)
 - #56914 (Ignore ui/target-feature-gate on sparc, sparc64, powerpc, powerpc64 and powerpc64le)
 - #56919 (Remove a wrong multiplier on relocation offset computation)
 - #56933 (Add --progress to git submodule commands in x.py)
 - #56936 (rename div_euc -> div_euclid, and mod_euc -> rem_euclid)
 - #56941 (deny intra-doc link resolution failures in libstd)
 - #56945 (Fix rustdoc-js tests)
 - #56967 (Replace current crate's searchIndex when regenerating)
 - #56970 (Mem uninit doc ptr drop)
 - #56973 (make basic CTFE tracing available on release builds)
 - #56979 (Adding unwinding support for x86_64_fortanix_unknown_sgx target.)
 - #56981 (miri: allocation is infallible)
 - #56984 (A few tweaks to dropck_outlives)
 - #56989 (Fix compiletest `trim` deprecation warnings)
 - #56992 (suggest similar lint names for unknown lints)
 - #57002 (Stabilize Vec(Deque)::resize_with)
 - #57011 (rustdoc: add new CLI flag to load static files from a different location)
 - #57027 (Optimize away a move)
 - #57034 (Inline tweaks)
 - #57039 (Update migrate warning wording.)
 - #57040 (Fix feature gate to point to 1.32.0 for `path_from_str`)
 - #57049 (Stabilize #[repr(packed(N))])
 - #57050 (Fixed typo in HashMap documentation)
 - #57052 (Fix stabilization version numbers (exhaustive_integer_patterns + macro_literal_matcher))
@bors bors merged commit 885cf2a into rust-lang:master Dec 23, 2018
Centril added a commit to Centril/rust that referenced this pull request Jan 12, 2019
…ix-unknown-sgx-backtrace-support, r=alexcrichton

Supporting backtrace for x86_64-fortanix-unknown-sgx.

# Overview
Implementing following functions required by `libstd/sys_common` to support `backtrace`:
```
1. unwind_backtrace
2. trace_fn
3. resolve_symname
```
# Description:
The changes here are quite similar to the Cloudabi target `src/libstd/sys/cloudabi/backtrace.rs`
The first 2 functions are implemented via calls to libunwind.a that is linked to the `x86_64-fortanix-unknown-sgx` (rust-lang#56979),  we have not implemented functionality needed by `resolve_symname`  (or `dladdr`) to reduce SGX TCB. Rather, we print the function address (relative to enclave image base) in `resolve_symname` which can be later translated to correct symbol name (say, via `addr2line`).

# Note:
For `x86_64-fortanix-unknown-sgx`, the `RUST_BACKTRACE` environment has to be set from within the program running in an enclave.
cc: @jethrogb
r? @alexcrichton
bors added a commit that referenced this pull request Jan 15, 2019
…sgx-tier2_support, r=alexcrichton

Upgrade x86_64-fortanix-unknown-sgx platform support to tier 2

## Overview
1. This PR upgrades x86_64-fortanix-unknown-sgx platform support to tier 2 (std only) by setting up build automation for this target.
1. For supporting unwinding, this target needs to link to a port of LLVM's libunwind (more details could be found in #56979), which will be distributed along with the Rust binaries (similar to the extra musl objects)

### Building and copying libunwind:
We have added a new build script  (`build-x86_64-fortanix-unknown-sgx-toolchain.sh`) that will run while the container is built. This will build `libunwind.a` from git source.
While the container is built, the persistent volumes where obj/ gets created aren't yet mapped. As a workaround, we copy the built `libunwind.a` to  `obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-fortanix-unknown-sgx/lib/` after x.py runs.
 If any reviewer knows of a better solution, please do tell.

r? @Mark-Simulacrum
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants