unwind.patch 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. From b3bea7008ece7a5bdf9b5a5dcc95e82febad1854 Mon Sep 17 00:00:00 2001
  2. From: Bjorn Neergaard <bjorn@neersighted.com>
  3. Date: Sat, 9 Feb 2019 19:39:23 +0000
  4. Subject: [PATCH] Fix cross-compiling i686-pc-windows-gnu from Linux
  5. This is still very rough and serves as a proof-of-concept for fixing
  6. Linux -> 32-bit MinGW cross compilation workflow. Currently, clang and
  7. GCC's MinGW targets both only support DW2 (DWARF) or SJLJ (Set Jump Long
  8. Jump) unwinding on 32-bit Windows.
  9. The default for GCC (and the way it is shipped on every major distro) is
  10. to use SJLJ on Windows, as DWARF cannot traverse non-DWARF frames. This
  11. would work fine, except for the fact that libgcc (our C runtime on the
  12. MinGW platform) exports symbols under a different name when configured
  13. to use SJLJ-style unwinding, and uses a preprocessor macro internally to
  14. alias them.
  15. Because of this, we have to detect this scenario and link to the correct
  16. symbols ourselves. Linking has been tested with a full bootstrap on both
  17. x86_64-unknown-linux-gnu and i686-pc-windows-gnu, as well as
  18. cross-compilation of some of my own projects.
  19. Obviously, the detection is a bit unrefined. Right now we
  20. unconditionally use SJLJ when compiling Linux -> MinGW. I'd like to add
  21. feature detection using compiler build flags or autotools-style
  22. compilation and object analysis. Input on the best way to proceed here
  23. is welcome.
  24. Also, currently there is copy-pasted/duplicated code in libunwind.
  25. Ideally, this could be reduced, but this would likely require a
  26. rethinking of how iOS is special-cased above, to avoid further
  27. duplication. Input on how to best structure this file is requested.
  28. diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
  29. index 249a183189..df08d6eb0c 100644
  30. --- a/src/bootstrap/compile.rs
  31. +++ b/src/bootstrap/compile.rs
  32. @@ -162,7 +162,12 @@ pub fn std_cargo(builder: &Builder<'_>,
  33. .arg("--features")
  34. .arg("compiler-builtins-mem");
  35. } else {
  36. - let features = builder.std_features();
  37. + let mut features = builder.std_features();
  38. +
  39. + // FIXME: Temporary detection of SJLJ MinGW compilers.
  40. + if builder.config.build.contains("linux") && target == "i686-pc-windows-gnu" {
  41. + features.push_str(" sjlj_eh");
  42. + }
  43. if compiler.stage != 0 && builder.config.sanitizers {
  44. // This variable is used by the sanitizer runtime crates, e.g.
  45. diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
  46. index 7d60a17042..d876d0b89a 100644
  47. --- a/src/libstd/Cargo.toml
  48. +++ b/src/libstd/Cargo.toml
  49. @@ -71,3 +71,4 @@ wasm-bindgen-threads = []
  50. # https://github.com/rust-lang-nursery/stdsimd/blob/master/crates/std_detect/Cargo.toml
  51. std_detect_file_io = []
  52. std_detect_dlsym_getauxval = []
  53. +sjlj_eh = ["unwind/sjlj_eh"]
  54. diff --git a/src/libunwind/Cargo.toml b/src/libunwind/Cargo.toml
  55. index 2378b0a315..0b5979ed62 100644
  56. --- a/src/libunwind/Cargo.toml
  57. +++ b/src/libunwind/Cargo.toml
  58. @@ -16,3 +16,6 @@ doc = false
  59. core = { path = "../libcore" }
  60. libc = { version = "0.2.43", features = ['rustc-dep-of-std'], default-features = false }
  61. compiler_builtins = "0.1.0"
  62. +
  63. +[features]
  64. +sjlj_eh = []
  65. diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs
  66. index 339b554ed6..ec2f93ed60 100644
  67. --- a/src/libunwind/libunwind.rs
  68. +++ b/src/libunwind/libunwind.rs
  69. @@ -1,10 +1,5 @@
  70. #![allow(nonstandard_style)]
  71. -macro_rules! cfg_if {
  72. - ( $( if #[cfg( $meta:meta )] { $($it1:item)* } else { $($it2:item)* } )* ) =>
  73. - ( $( $( #[cfg($meta)] $it1)* $( #[cfg(not($meta))] $it2)* )* )
  74. -}
  75. -
  76. use libc::{c_int, c_void, uintptr_t};
  77. #[repr(C)]
  78. @@ -73,8 +68,8 @@ pub enum _Unwind_Context {}
  79. pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reason_Code,
  80. exception: *mut _Unwind_Exception);
  81. extern "C" {
  82. - #[unwind(allowed)]
  83. - pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
  84. + #[cfg_attr(stage0, unwind)]
  85. + #[cfg_attr(not(stage0), unwind(allowed))]
  86. pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
  87. pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void;
  88. pub fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
  89. @@ -206,26 +201,52 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm
  90. pc
  91. }
  92. }
  93. +} // cfg_if!
  94. -if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
  95. - // Not 32-bit iOS
  96. +cfg_if! {
  97. +if #[cfg(all(target_os = "ios", target_arch = "arm"))] {
  98. + // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
  99. extern "C" {
  100. - #[unwind(allowed)]
  101. - pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
  102. + #[cfg_attr(stage0, unwind)]
  103. + #[cfg_attr(not(stage0), unwind(allowed))]
  104. + pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
  105. + pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
  106. + }
  107. +
  108. + #[inline]
  109. + pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
  110. + _Unwind_SjLj_RaiseException(exc)
  111. + }
  112. +
  113. +} else if #[cfg(feature = "sjlj_eh")] {
  114. + extern "C" {
  115. + #[cfg_attr(stage0, unwind)]
  116. + #[cfg_attr(not(stage0), unwind(allowed))]
  117. + pub fn _Unwind_SjLj_Resume(e: *mut _Unwind_Exception) -> !;
  118. + pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
  119. pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
  120. trace_argument: *mut c_void)
  121. -> _Unwind_Reason_Code;
  122. }
  123. -} else {
  124. - // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
  125. - extern "C" {
  126. - #[unwind(allowed)]
  127. - pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
  128. +
  129. + #[inline]
  130. + pub unsafe fn _Unwind_Resume(exc: *mut _Unwind_Exception) -> ! {
  131. + _Unwind_SjLj_Resume(exc)
  132. }
  133. #[inline]
  134. pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
  135. _Unwind_SjLj_RaiseException(exc)
  136. }
  137. +} else {
  138. + extern "C" {
  139. + #[cfg_attr(stage0, unwind)]
  140. + #[cfg_attr(not(stage0), unwind(allowed))]
  141. + pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
  142. + pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
  143. + pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
  144. + trace_argument: *mut c_void)
  145. + -> _Unwind_Reason_Code;
  146. + }
  147. }
  148. } // cfg_if!
  149. --
  150. 2.23.0.rc0