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

Miscompilation when building firefox on debug mode. #46239

Closed
emilio opened this issue Nov 24, 2017 · 10 comments
Closed

Miscompilation when building firefox on debug mode. #46239

emilio opened this issue Nov 24, 2017 · 10 comments
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. regression-from-stable-to-beta Performance or correctness regression from stable to beta. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@emilio
Copy link
Contributor

emilio commented Nov 24, 2017

We've come across a memory corruption issue that happens during the Gecko build process on debug builds, see https://bugzilla.mozilla.org/show_bug.cgi?id=1420301.

After a bit of fiddling, the fix is KyleMayes/clang-sys@2226f78, so something looks fishy on rustcs side.

I'm bisecting now.

@emilio
Copy link
Contributor Author

emilio commented Nov 24, 2017

Beta is affected fwiw.

@kennytm kennytm added the C-bug Category: This is a bug. label Nov 24, 2017
@kennytm
Copy link
Member

kennytm commented Nov 24, 2017

(Aside: symbol.map(|s| *s) is the same as symbol.cloned() assuming s is Copy, though I'm not sure if that will reintroduce the mis-compilation)

@emilio
Copy link
Contributor Author

emilio commented Nov 24, 2017

First bad:

rustc 1.23.0-nightly (33374fa 2017-11-20)

Last good:

rustc 1.23.0-nightly (5041b3b 2017-11-19)

Regression range: 5041b3b...33374fa

@SimonSapin points out that the workaround is not exactly the same (the inferred type for the bogus case is Symbol<extern fn> while in mine is Symbol<Option<extern fn>>. None of the functions are null though, doing some more experimentation now.

@jdm jdm added the regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. label Nov 24, 2017
@SimonSapin
Copy link
Contributor

@kennytm This option contains a libloading::Symbol<_> which is Deref, not a &_.

@kennytm
Copy link
Member

kennytm commented Nov 24, 2017

@SimonSapin huh okay. cc @eddyb #45225 the most likely target in the range.

@kennytm kennytm added regression-from-stable-to-beta Performance or correctness regression from stable to beta. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. labels Nov 24, 2017
@emilio
Copy link
Contributor Author

emilio commented Nov 24, 2017

Just to make clear what's happening and making type inference easier to follow:

Crashes (this is equivalent to the current code):

diff --git a/src/link.rs b/src/link.rs
index 543a5a5..bc81d96 100644
--- a/src/link.rs
+++ b/src/link.rs
@@ -23,7 +23,10 @@ macro_rules! link {
     (@LOAD: #[cfg($cfg:meta)] fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*) => (
         #[cfg($cfg)]
         pub fn $name(library: &mut super::SharedLibrary) {
-            let symbol = unsafe { library.library.get(stringify!($name).as_bytes()) }.ok();
+            use libloading::Symbol;
+            use super::*;
+            let symbol: Option<Symbol<unsafe extern fn($($pty,)*) -> _>> =
+                unsafe { library.library.get(stringify!($name).as_bytes()) }.ok();
             library.functions.$name = symbol.map(|s| *s);
         }

Doesn't crash:

diff --git a/src/link.rs b/src/link.rs
index 543a5a5..bdf7962 100644
--- a/src/link.rs
+++ b/src/link.rs
@@ -23,7 +23,16 @@ macro_rules! link {
     (@LOAD: #[cfg($cfg:meta)] fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*) => (
         #[cfg($cfg)]
         pub fn $name(library: &mut super::SharedLibrary) {
-            let symbol = unsafe { library.library.get(stringify!($name).as_bytes()) }.ok();
+            use libloading::Symbol;
+            use super::*;
+
+            fn gimme_a_ref<T>(_: &T) {}
+
+            let symbol: Option<Symbol<unsafe extern fn($($pty,)*) -> _>> =
+                unsafe { library.library.get(stringify!($name).as_bytes()) }.ok();
+
+            gimme_a_ref(&symbol);
+
             library.functions.$name = symbol.map(|s| *s);
         }

Also doesn't crash:

diff --git a/src/link.rs b/src/link.rs
index 543a5a5..03f37b6 100644
--- a/src/link.rs
+++ b/src/link.rs
@@ -23,8 +23,11 @@ macro_rules! link {
     (@LOAD: #[cfg($cfg:meta)] fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*) => (
         #[cfg($cfg)]
         pub fn $name(library: &mut super::SharedLibrary) {
-            let symbol = unsafe { library.library.get(stringify!($name).as_bytes()) }.ok();
-            library.functions.$name = symbol.map(|s| *s);
+            use libloading::Symbol;
+            use super::*;
+            let symbol: Option<Symbol<Option<unsafe extern fn($($pty,)*) -> _>>> =
+                unsafe { library.library.get(stringify!($name).as_bytes()) }.ok();
+            library.functions.$name = symbol.and_then(|s| *s);
         }
 
         #[cfg(not($cfg))]

@emilio
Copy link
Contributor Author

emilio commented Nov 25, 2017

Turns out that FF compiles some dependencies with -C opt-level=1.

I put a more minimal repro here: https://github.com/emilio/rustc-46239-repro

You can repro with RUSTFLAGS="-C opt-level=1" cargo run

@eddyb
Copy link
Member

eddyb commented Nov 25, 2017

Minimal (still only at opt-level=1) reproduction without taking apart libloading:

extern crate libloading;

fn main() {
    unsafe {
        let library = libloading::Library::new("libc.so.6").unwrap();
        let symbol: Option<libloading::Symbol<extern fn(i32) -> !>> =
            library.get("exit".as_bytes()).ok();
        symbol.map(|s| *s).unwrap()(0);
    }
}

@nagisa
Copy link
Member

nagisa commented Nov 25, 2017

Following is the LLVM-IR that when optimised with -O1 results in IR that passes uninitialised alloca to a call. Can be reproduced by running opt -dse unoptimised.ll.

Unoptimised
; ModuleID = '<stdin>'
source_filename = "test0-6309762d5a7d9b368daa0ebe527434c3.rs"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; Function Attrs: norecurse readnone uwtable
define internal noalias nonnull align 8 dereferenceable(8) void (i32)** @0(i8** noalias readonly dereferenceable(8)) unnamed_addr #0 {
  %2 = bitcast i8** %0 to void (i32)**
  ret void (i32)** %2
}

; Function Attrs: norecurse readonly uwtable
define nonnull void (i32)* @"_ZN4test4main28_$u7b$$u7b$closure$u7d$$u7d$17hc0fea9cc3707b635E"(i8*) unnamed_addr #1 {
  %2 = alloca i8*, align 8
  store i8* %0, i8** %2
  %3 = call noalias align 8 dereferenceable(8) void (i32)** @0(i8** noalias readonly dereferenceable(8) %2)
  %4 = load void (i32)*, void (i32)** %3, !nonnull !1
  ret void (i32)* %4
}

attributes #0 = { norecurse readnone uwtable "probe-stack"="__rust_probestack" }
attributes #1 = { norecurse readonly uwtable "probe-stack"="__rust_probestack" }

!llvm.module.flags = !{!0}

!0 = !{i32 7, !"PIE Level", i32 2}
!1 = !{}
Optimised
; ModuleID = '<stdin>'
source_filename = "test0-6309762d5a7d9b368daa0ebe527434c3.rs"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

; Function Attrs: norecurse readnone uwtable
define internal noalias nonnull align 8 dereferenceable(8) void (i32)** @0(i8** noalias readonly dereferenceable(8)) unnamed_addr #0 {
  %2 = bitcast i8** %0 to void (i32)**
  ret void (i32)** %2
}

; Function Attrs: norecurse readonly uwtable
define nonnull void (i32)* @"_ZN4test4main28_$u7b$$u7b$closure$u7d$$u7d$17hc0fea9cc3707b635E"(i8*) unnamed_addr #1 {
  %2 = alloca i8*, align 8
  %3 = call noalias align 8 dereferenceable(8) void (i32)** @0(i8** noalias readonly dereferenceable(8) %2)
  %4 = load void (i32)*, void (i32)** %3, !nonnull !1
  ret void (i32)* %4
}

attributes #0 = { norecurse readnone uwtable "probe-stack"="__rust_probestack" }
attributes #1 = { norecurse readonly uwtable "probe-stack"="__rust_probestack" }

!llvm.module.flags = !{!0}

!0 = !{i32 7, !"PIE Level", i32 2}
!1 = !{}

@eddyb
Copy link
Member

eddyb commented Nov 25, 2017

Reduction to builtin types and safe code only, compile with rustc -C opt-level=1:

fn project<T>(x: &(T,)) -> &T { &x.0 }

fn dummy() {}

fn main() {
    let f = (dummy as fn(),);
    (*project(&f))();
}

@kennytm kennytm added the A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. label Nov 25, 2017
emilio added a commit to emilio/servo that referenced this issue Nov 25, 2017
bors-servo pushed a commit to servo/servo that referenced this issue Nov 25, 2017
Bump clang-sys to work around a Rust miscompilation.

Works around: rust-lang/rust#46239

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/19372)
<!-- Reviewable:end -->
bors-servo pushed a commit to servo/servo that referenced this issue Nov 25, 2017
Bump clang-sys to work around a Rust miscompilation.

Works around: rust-lang/rust#46239

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/19372)
<!-- Reviewable:end -->
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this issue Nov 25, 2017
xeonchen pushed a commit to xeonchen/gecko-cinnabar that referenced this issue Nov 26, 2017
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this issue Nov 26, 2017
…tion (from emilio:bump-clang-sys); r=rillian

Works around: rust-lang/rust#46239

Source-Repo: https://github.com/servo/servo
Source-Revision: 49658860d12186b9ccc45fcdb0394886f00afe37

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 3837b58c04f3b30d34d9abef95fdaf9e96372908
xeonchen pushed a commit to xeonchen/gecko-cinnabar that referenced this issue Nov 26, 2017
…tion (from emilio:bump-clang-sys); r=rillian

Works around: rust-lang/rust#46239

Source-Repo: https://github.com/servo/servo
Source-Revision: 49658860d12186b9ccc45fcdb0394886f00afe37
bors added a commit that referenced this issue Nov 26, 2017
rustc_trans: don't apply noalias on returned references.

In #45225 frozen returned `&T` were accidentally maked `noalias`, unlike `&mut T`.
Return value `noalias` is only sound for functions that return dynamic allocations, e.g. `Box`, and using it on anything else can lead to miscompilation, as LLVM assumes certain usage patterns.
Fixes #46239.
JerryShih pushed a commit to JerryShih/gecko-dev that referenced this issue Nov 28, 2017
…tion (from emilio:bump-clang-sys); r=rillian

Works around: rust-lang/rust#46239

Source-Repo: https://github.com/servo/servo
Source-Revision: 49658860d12186b9ccc45fcdb0394886f00afe37
JerryShih pushed a commit to JerryShih/gecko-dev that referenced this issue Nov 28, 2017
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified-and-comments-removed that referenced this issue Oct 2, 2019
See: rust-lang/rust#46239

MozReview-Commit-ID: EiHsSK0xJ5c

UltraBlame original commit: cb600422ac4db06532c8ef93b40793651afd7355
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified-and-comments-removed that referenced this issue Oct 2, 2019
…tion (from emilio:bump-clang-sys); r=rillian

Works around: rust-lang/rust#46239

Source-Repo: https://github.com/servo/servo
Source-Revision: 49658860d12186b9ccc45fcdb0394886f00afe37

UltraBlame original commit: 07a6e3f9c53c1f80cd4fb537383609334947a6cb
gecko-dev-updater pushed a commit to marco-c/gecko-dev-comments-removed that referenced this issue Oct 2, 2019
See: rust-lang/rust#46239

MozReview-Commit-ID: EiHsSK0xJ5c

UltraBlame original commit: cb600422ac4db06532c8ef93b40793651afd7355
gecko-dev-updater pushed a commit to marco-c/gecko-dev-comments-removed that referenced this issue Oct 2, 2019
…tion (from emilio:bump-clang-sys); r=rillian

Works around: rust-lang/rust#46239

Source-Repo: https://github.com/servo/servo
Source-Revision: 49658860d12186b9ccc45fcdb0394886f00afe37

UltraBlame original commit: 07a6e3f9c53c1f80cd4fb537383609334947a6cb
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified that referenced this issue Oct 2, 2019
See: rust-lang/rust#46239

MozReview-Commit-ID: EiHsSK0xJ5c

UltraBlame original commit: cb600422ac4db06532c8ef93b40793651afd7355
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified that referenced this issue Oct 2, 2019
…tion (from emilio:bump-clang-sys); r=rillian

Works around: rust-lang/rust#46239

Source-Repo: https://github.com/servo/servo
Source-Revision: 49658860d12186b9ccc45fcdb0394886f00afe37

UltraBlame original commit: 07a6e3f9c53c1f80cd4fb537383609334947a6cb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. C-bug Category: This is a bug. regression-from-stable-to-beta Performance or correctness regression from stable to beta. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants