unwind.patch 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. From 90ddcca6235b5f24c57df6a648e8d489c7e3eae5 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 65a00db3394..e821507c341 100644
  30. --- a/src/bootstrap/compile.rs
  31. +++ b/src/bootstrap/compile.rs
  32. @@ -207,6 +207,11 @@ pub fn std_cargo(builder: &Builder<'_>, target: Interned<String>, cargo: &mut Ca
  33. let mut features = builder.std_features();
  34. features.push_str(&compiler_builtins_c_feature);
  35. + // FIXME: Temporary detection of SJLJ MinGW compilers.
  36. + if builder.config.build.contains("linux") && target == "i686-pc-windows-gnu" {
  37. + features.push_str(" sjlj_eh");
  38. + }
  39. +
  40. cargo
  41. .arg("--features")
  42. .arg(features)
  43. diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
  44. index b147aa55b2a..cad4d88caa2 100644
  45. --- a/src/libstd/Cargo.toml
  46. +++ b/src/libstd/Cargo.toml
  47. @@ -68,6 +68,7 @@ panic_immediate_abort = ["core/panic_immediate_abort"]
  48. # https://github.com/rust-lang/stdarch/blob/master/crates/std_detect/Cargo.toml
  49. std_detect_file_io = []
  50. std_detect_dlsym_getauxval = []
  51. +sjlj_eh = ["unwind/sjlj_eh"]
  52. [package.metadata.fortanix-sgx]
  53. # Maximum possible number of threads when testing
  54. diff --git a/src/libtest/Cargo.toml b/src/libtest/Cargo.toml
  55. index 170fbb984cf..b1b0be71067 100644
  56. --- a/src/libtest/Cargo.toml
  57. +++ b/src/libtest/Cargo.toml
  58. @@ -29,3 +29,4 @@ llvm-libunwind = ["std/llvm-libunwind"]
  59. panic-unwind = ["std/panic_unwind"]
  60. panic_immediate_abort = ["std/panic_immediate_abort"]
  61. profiler = ["std/profiler"]
  62. +sjlj_eh = ["std/sjlj_eh"]
  63. diff --git a/src/libunwind/Cargo.toml b/src/libunwind/Cargo.toml
  64. index 77bcfffd506..9d9fc5fbff5 100644
  65. --- a/src/libunwind/Cargo.toml
  66. +++ b/src/libunwind/Cargo.toml
  67. @@ -26,3 +26,4 @@ cc = { version = "1.0.1" }
  68. [features]
  69. llvm-libunwind = []
  70. +sjlj_eh = []
  71. diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs
  72. index 0c57861f70a..44c767ebfc5 100644
  73. --- a/src/libunwind/libunwind.rs
  74. +++ b/src/libunwind/libunwind.rs
  75. @@ -79,8 +79,8 @@ pub type _Unwind_Exception_Cleanup_Fn =
  76. link(name = "unwind", kind = "static")
  77. )]
  78. extern "C" {
  79. - #[unwind(allowed)]
  80. - pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
  81. + #[cfg_attr(stage0, unwind)]
  82. + #[cfg_attr(not(stage0), unwind(allowed))]
  83. pub fn _Unwind_DeleteException(exception: *mut _Unwind_Exception);
  84. pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> *mut c_void;
  85. pub fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
  86. @@ -222,32 +222,50 @@ if #[cfg(all(any(target_os = "ios", target_os = "netbsd", not(target_arch = "arm
  87. } // cfg_if!
  88. cfg_if::cfg_if! {
  89. -if #[cfg(not(all(target_os = "ios", target_arch = "arm")))] {
  90. - // Not 32-bit iOS
  91. - #[cfg_attr(all(feature = "llvm-libunwind",
  92. - any(target_os = "fuchsia", target_os = "linux")),
  93. - link(name = "unwind", kind = "static"))]
  94. +if #[cfg(all(target_os = "ios", target_arch = "arm"))] {
  95. + // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
  96. extern "C" {
  97. - #[unwind(allowed)]
  98. - pub fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
  99. + #[cfg_attr(stage0, unwind)]
  100. + #[cfg_attr(not(stage0), unwind(allowed))]
  101. + pub fn _Unwind_Resume(exception: *mut _Unwind_Exception) -> !;
  102. + pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
  103. + }
  104. +
  105. + #[inline]
  106. + pub unsafe fn _Unwind_RaiseException(exc: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
  107. + _Unwind_SjLj_RaiseException(exc)
  108. + }
  109. +
  110. +} else if #[cfg(feature = "sjlj_eh")] {
  111. + extern "C" {
  112. + #[cfg_attr(stage0, unwind)]
  113. + #[cfg_attr(not(stage0), unwind(allowed))]
  114. + pub fn _Unwind_SjLj_Resume(e: *mut _Unwind_Exception) -> !;
  115. + pub fn _Unwind_SjLj_RaiseException(e: *mut _Unwind_Exception) -> _Unwind_Reason_Code;
  116. pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
  117. trace_argument: *mut c_void)
  118. -> _Unwind_Reason_Code;
  119. }
  120. -} else {
  121. - // 32-bit iOS uses SjLj and does not provide _Unwind_Backtrace()
  122. - #[cfg_attr(all(feature = "llvm-libunwind",
  123. - any(target_os = "fuchsia", target_os = "linux")),
  124. - link(name = "unwind", kind = "static"))]
  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.28.0