[tor-commits] [tor-browser-build/master] Bug 25849: Enable Rust in Tor for Windows nightlies

boklm at torproject.org boklm at torproject.org
Thu Feb 21 15:18:13 UTC 2019


commit 3de8afa44fa4a7078f917263147f6e19107e3141
Author: Georg Koppen <gk at torproject.org>
Date:   Sun Feb 10 20:30:19 2019 +0000

    Bug 25849: Enable Rust in Tor for Windows nightlies
---
 projects/rust/build            |   6 +-
 projects/rust/config           |   4 +-
 projects/rust/unwind_128.patch | 161 +++++++++++++++++++++++++++++++++++++++++
 projects/tor/build             |  10 ++-
 projects/tor/config            |   3 +-
 5 files changed, 178 insertions(+), 6 deletions(-)

diff --git a/projects/rust/build b/projects/rust/build
index 12f012a..3c1d130 100644
--- a/projects/rust/build
+++ b/projects/rust/build
@@ -59,7 +59,11 @@ cd /var/tmp/build/rustc-[% c('version') %]-src
   # See: https://github.com/rust-lang/rust/issues/12859 for discussion about
   # that and https://github.com/rust-lang/rust/pull/49633 for a newer attempt to
   # fix this problem. We apply the patch from neersighted.
-  patch -p1 < $rootdir/unwind.patch
+  [% IF !c("input_file_var/unwind_128") %]
+    patch -p1 < $rootdir/unwind.patch
+  [% ELSE %]
+    patch -p1 < $rootdir/unwind_128.patch
+  [% END %]
 [% END %]
 
 [% IF c("var/android") %]
diff --git a/projects/rust/config b/projects/rust/config
index 99d1177..48912ab 100644
--- a/projects/rust/config
+++ b/projects/rust/config
@@ -89,7 +89,9 @@ input_files:
     file_gpg_id: 1
     gpg_keyring: rust.gpg
   - filename: unwind.patch
-    enable: '[% c("var/windows-i686") %]'
+    enable: '[% c("var/windows-i686") && !c("input_file_var/unwind_128") %]'
+  - filename: unwind_128.patch
+    enable: '[% c("input_file_var/unwind_128") %]'
   - filename: 0001-Make-sure-dl_iterate_phdr-is-undefined-on-Android.patch
     enable: '[% c("var/android") %]'
   - filename: replace_pagesize_in_mmap.patch
diff --git a/projects/rust/unwind_128.patch b/projects/rust/unwind_128.patch
new file mode 100644
index 0000000..93528c9
--- /dev/null
+++ b/projects/rust/unwind_128.patch
@@ -0,0 +1,161 @@
+From 0a186eafebf26ca01879827a4cc95cc274791334 Mon Sep 17 00:00:00 2001
+From: Bjorn Neergaard <bjorn at neersighted.com>
+Date: Sat, 9 Feb 2019 19:39:23 +0000
+Subject: [PATCH] Fix cross-compiling i686-pc-windows-gnu from Linux
+
+This is still very rough and serves as a proof-of-concept for fixing
+Linux -> 32-bit MinGW cross compilation workflow. Currently, clang and
+GCC's MinGW targets both only support DW2 (DWARF) or SJLJ (Set Jump Long
+Jump) unwinding on 32-bit Windows.
+
+The default for GCC (and the way it is shipped on every major distro) is
+to use SJLJ on Windows, as DWARF cannot traverse non-DWARF frames. This
+would work fine, except for the fact that libgcc (our C runtime on the
+MinGW platform) exports symbols under a different name when configured
+to use SJLJ-style unwinding, and uses a preprocessor macro internally to
+alias them.
+
+Because of this, we have to detect this scenario and link to the correct
+symbols ourselves. Linking has been tested with a full bootstrap on both
+x86_64-unknown-linux-gnu and i686-pc-windows-gnu, as well as
+cross-compilation of some of my own projects.
+
+Obviously, the detection is a bit unrefined. Right now we
+unconditionally use SJLJ when compiling Linux -> MinGW. I'd like to add
+feature detection using compiler build flags or autotools-style
+compilation and object analysis. Input on the best way to proceed here
+is welcome.
+
+Also, currently there is copy-pasted/duplicated code in libunwind.
+Ideally, this could be reduced, but this would likely require a
+rethinking of how iOS is special-cased above, to avoid further
+duplication. Input on how to best structure this file is requested.
+
+diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
+index 11d9154ba6..bd8ff844f7 100644
+--- a/src/bootstrap/compile.rs
++++ b/src/bootstrap/compile.rs
+@@ -154,6 +154,11 @@ pub fn std_cargo(builder: &Builder,
+     } else {
+         let mut features = builder.std_features();
+ 
++        // FIXME: Temporary detection of SJLJ MinGW compilers.
++        if builder.config.build.contains("linux") && target == "i686-pc-windows-gnu" {
++            features.push_str(" sjlj_eh");
++        }
++
+         // When doing a local rebuild we tell cargo that we're stage1 rather than
+         // stage0. This works fine if the local rust and being-built rust have the
+         // same view of what the default allocator is, but fails otherwise. Since
+diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
+index 5a2dce5930..e1c876f503 100644
+--- a/src/libstd/Cargo.toml
++++ b/src/libstd/Cargo.toml
+@@ -50,3 +50,4 @@ force_alloc_system = []
+ panic-unwind = ["panic_unwind"]
+ profiler = ["profiler_builtins"]
+ wasm_syscall = []
++sjlj_eh = ["unwind/sjlj_eh"]
+diff --git a/src/libunwind/Cargo.toml b/src/libunwind/Cargo.toml
+index 4760461df6..27c7303604 100644
+--- a/src/libunwind/Cargo.toml
++++ b/src/libunwind/Cargo.toml
+@@ -15,3 +15,6 @@ doc = false
+ core = { path = "../libcore" }
+ libc = { path = "../rustc/libc_shim" }
+ compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
++
++[features]
++sjlj_eh = []
+diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs
+index 73a259bd44..ff3404864f 100644
+--- a/src/libunwind/libunwind.rs
++++ b/src/libunwind/libunwind.rs
+@@ -10,11 +10,6 @@
+ 
+ #![allow(bad_style)]
+ 
+-macro_rules! cfg_if {
+-    ( $( if #[cfg( $meta:meta )] { $($it1:item)* } else { $($it2:item)* } )* ) =>
+-        ( $( $( #[cfg($meta)] $it1)* $( #[cfg(not($meta))] $it2)* )* )
+-}
+-
+ use libc::{c_int, c_void, uintptr_t};
+ 
+ #[repr(C)]
+@@ -83,8 +78,8 @@ pub enum _Unwind_Context {}
+ pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reason_Code,
+                                                       exception: *mut _Unwind_Exception);
+ extern "C" {
+-    #[unwind(allowed)]
+-    pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
++    #[cfg_attr(stage0, unwind)]
++    #[cfg_attr(not(stage0), unwind(allowed))]
+     pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
+     pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void;
+     pub fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
+@@ -216,26 +211,52 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm
+         pc
+     }
+ }
++} // cfg_if!
+ 
+-if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
+-    // Not 32-bit iOS
++cfg_if! {
++if #[cfg(all(target_os = "ios", target_arch = "arm"))] {
++    // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
+     extern "C" {
+-        #[unwind(allowed)]
+-        pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
++        #[cfg_attr(stage0, unwind)]
++        #[cfg_attr(not(stage0), unwind(allowed))]
++        pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
++        pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
++    }
++
++    #[inline]
++    pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
++        _Unwind_SjLj_RaiseException(exc)
++    }
++
++} else if #[cfg(feature = "sjlj_eh")] {
++    extern "C" {
++        #[cfg_attr(stage0, unwind)]
++        #[cfg_attr(not(stage0), unwind(allowed))]
++        pub fn _Unwind_SjLj_Resume(e: *mut _Unwind_Exception) -> !;
++        pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
+         pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
+                                  trace_argument: *mut c_void)
+                                  -> _Unwind_Reason_Code;
+     }
+-} else {
+-    // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
+-    extern "C" {
+-        #[unwind(allowed)]
+-        pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
++
++    #[inline]
++    pub unsafe fn _Unwind_Resume(exc: *mut _Unwind_Exception) -> ! {
++        _Unwind_SjLj_Resume(exc)
+     }
+ 
+     #[inline]
+     pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
+         _Unwind_SjLj_RaiseException(exc)
+     }
++} else {
++    extern "C" {
++        #[cfg_attr(stage0, unwind)]
++        #[cfg_attr(not(stage0), unwind(allowed))]
++        pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
++        pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
++        pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
++                                 trace_argument: *mut c_void)
++                                 -> _Unwind_Reason_Code;
++    }
+ }
+ } // cfg_if!
+-- 
+2.20.1
+
diff --git a/projects/tor/build b/projects/tor/build
index e9bd326..f063693 100644
--- a/projects/tor/build
+++ b/projects/tor/build
@@ -24,7 +24,7 @@ mkdir -p /var/tmp/build
 
 tar -C /var/tmp/dist -xf [% c('input_files_by_name/openssl') %]
 tar -C /var/tmp/dist -xf [% c('input_files_by_name/libevent') %]
-[% IF (c("var/linux") || c("var/osx")) && c("var/nightly") %]
+[% IF !c("var/android") && c("var/nightly") %]
   tar -C /var/tmp/dist -xf [% c('input_files_by_name/rust') %]
   export PATH=/var/tmp/dist/rust/bin:$PATH
 [% END %]
@@ -33,6 +33,10 @@ libeventdir=/var/tmp/dist/libevent
 openssldir=/var/tmp/dist/openssl
 
 [% IF c("var/windows") %]
+  [% IF ("var/nightly") %]
+    # We are compiling Tor with Rust enabled for nightlies.
+    export TOR_RUST_TARGET=[% c("arch") %]-pc-windows-gnu
+  [% END %]
   tar -C /var/tmp/build -xf [% c('input_files_by_name/zlib') %]
   zlibdir=/var/tmp/build/zlib
   mingwlibs=/var/tmp/dist/mingw-w64/[% c("arch") %]-w64-mingw32/bin/
@@ -74,11 +78,11 @@ cd /var/tmp/build/[% project %]-[% c('version') %]
 echo '"[% c("abbrev", { abbrev_length => 16 }) %]"' > micro-revision.i
 ./autogen.sh
 find -type f -print0 | xargs -0 [% c("var/touch") %]
-[% IF (c("var/linux") || c("var/osx")) && c("var/nightly") %]TOR_RUST_DEPENDENCIES=`pwd`/src/ext/rust/crates[% END %] ./configure --disable-asciidoc --with-libevent-dir="$libeventdir" --with-openssl-dir="$openssldir" \
+[% IF !c("var/android") && c("var/nightly") %]TOR_RUST_DEPENDENCIES=`pwd`/src/ext/rust/crates[% END %] ./configure --disable-asciidoc --with-libevent-dir="$libeventdir" --with-openssl-dir="$openssldir" \
     [% IF c("var/asan") %]--enable-fragile-hardening[% END %] \
     [% IF c("var/windows") %]--with-zlib-dir="$zlibdir"[% END %] \
     [% IF c("var/osx") %]--enable-static-openssl[% END %] \
-    [% IF (c("var/linux") || c("var/osx")) && c("var/nightly") %]--enable-rust[% END %] \
+    [% IF !c("var/android") && c("var/nightly") %]--enable-rust[% END %] \
     --prefix="$distdir" [% c("var/configure_opt") %]
 [% IF c("var/osx") || c("var/windows") -%]
   export LD_PRELOAD=[% c("var/faketime_path") %]
diff --git a/projects/tor/config b/projects/tor/config
index e6e923b..af90885 100644
--- a/projects/tor/config
+++ b/projects/tor/config
@@ -65,4 +65,5 @@ input_files:
     input_file_var:
       rust_version: 1.28.0
       prev_version: 1.27.2
-    enable: '[% (c("var/linux") || c("var/osx")) && c("var/nightly") %]'
+      unwind_128: '[% c("var/windows-i686") %]'
+    enable: '[% !c("var/android") && c("var/nightly") %]'





More information about the tor-commits mailing list