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

Cross v0.1.15 Breaks f64 Modulus on i686 #314

Closed
Alexhuszagh opened this issue Sep 8, 2019 · 9 comments · Fixed by #318
Closed

Cross v0.1.15 Breaks f64 Modulus on i686 #314

Alexhuszagh opened this issue Sep 8, 2019 · 9 comments · Fixed by #318
Labels
A-qemu Area: qemu runners A-x86 Area: x86 targets bug

Comments

@Alexhuszagh
Copy link
Contributor

Alexhuszagh commented Sep 8, 2019

The following code worked for cross v0.1.14, so any issues were introduced with the latest release.

Targets

  • i686-unknown-linux-gnu

x86_64 works fine, so the issue only occurs on 32-bit x86.

Failing Code

fn main() {
    let value: f64 = 29860476080414620.0;
    let base: f64 = 17.0;
    println!("value % base = {:?}", value % base);
}

Results

value % base = -4.0

The value is negative for the float modulus, rather than 15.0. Running with target x86_64-unknown-linux-gnu prints the expected result (15.0).

Minimal Steps to Reproduce

  1. Create a repository (cargo new --bin sample).
  2. Copy the failing code into main.rs.
  3. Run the binary on i686 (cross run --target i686-unknown-linux-gnu).

Finally, this code works with cargo run --target i686-unknown-linux-gnu.

@Alexhuszagh Alexhuszagh changed the title Cross v0.1.15 Breaks f32/f64 Modulus on i686 Cross v0.1.15 Breaks f64 Modulus on i686 Sep 8, 2019
@Alexhuszagh
Copy link
Contributor Author

Update: Running the generated binary without qemu produces the desired result, while running it with Qemu fails. This seems to be a bug in Qemu.

$ uname -a
Linux ahuszagh.localdomain 5.2.7-100.fc29.x86_64 #1 SMP Thu Aug 8 05:30:19 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
$ qemu-i386 --version
qemu-i386 version 3.0.1 (qemu-3.0.1-4.fc29)
cross --version
cross 0.1.15
cargo 1.37.0 (9edd08916 2019-08-02)
$ target/i686-unknown-linux-gnu/debug/sample
value % base = 15.0
$ qemu-i386 target/i686-unknown-linux-gnu/debug/sample
value % base = -4.0

Compiling the binary with an older version of cross (v0.1.14) and then executing it with a newer version of Qemu fails:

$ qemu-i386 --version
qemu-i386 version 3.0.1 (qemu-3.0.1-4.fc29)
$ cross --version
cross 0.1.14
cargo 1.37.0 (9edd08916 2019-08-02)
$ cross build --target i686-unknown-linux-gnu
    Finished dev [unoptimized + debuginfo] target(s) in 0.10s
$ target/i686-unknown-linux-gnu/debug/sample
value % base = 15.0
$ qemu-i386 target/i686-unknown-linux-gnu/debug/sample
value % base = -4.0

@Alexhuszagh
Copy link
Contributor Author

Confirmed a Qemu bug. Will file upstream.

Source

a.c

#include <math.h>
#include <stdio.h>

int main()
{
    double x = 29860476080414620.0;
    double y = 17.0;
    double z = fmod(x, y);
    printf("%f\n", z);
    return 0;
}

Compile Command

$ gcc --version
gcc (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2)
$ gcc a.c -o a -m32 -lm

Calling

$ ./a 
15.000000
$ qemu-i386 a
-4.000000

@Alexhuszagh
Copy link
Contributor Author

@reitermarkus This is a separate issue from #314.

First, cross v0.1.14 did not use qemu for i686. No version of qemu works, on i686 (really the i387, since this is all going to be done by the FPU), to my understanding. I've tested 2.10.0, 3.0.1, 4.1.0, and the latest commit as of testing.

I've filed the bug upstream, and is available here:
https://bugs.launchpad.net/qemu/+bug/1843205

As the bug is upstream, and no working versions of qemu seem to exist, I'm not sure if there's anything cross should do, since the alternative is the i686 target only works on x86.

@reitermarkus
Copy link
Member

So it should work running natively inside the Docker container?

@Alexhuszagh
Copy link
Contributor Author

Alexhuszagh commented Sep 9, 2019

Yes, on x86 or x86_64. In practice, I doubt anyone will be running cross on anything other than x86 or ARM (are non-x86 hosts even supported? If not, that maybe should be made clear. If so, then running the i686 binary natively would break non-x86 hosts).

@Alexhuszagh
Copy link
Contributor Author

We could check uname -m, and if the value is i386, i486, i586, i686, or x86_64, then just run the binary natively.

@reitermarkus
Copy link
Member

Non-x86 hosts aren't supported at the moment, and I doubt there is any demand for it, so this should be fine.

Look at the linux-runner script, we can make CROSS_RUNNER default to native with the uname check, otherwise to qemu-user.

@Alexhuszagh
Copy link
Contributor Author

Would something like this work? If we're assuming the host is x86, then we don't need to check the machine hardware name: every host should be able to run an i686 binary (this bug doesn't occur for x86_64).

diff --git a/docker/linux-runner b/docker/linux-runner
index 9e1e1e7..1d58759 100755
--- a/docker/linux-runner
+++ b/docker/linux-runner
@@ -14,7 +14,14 @@ arch=$1
 shift
 
 if [ "$CROSS_RUNNER" = "" ]; then
-    CROSS_RUNNER=qemu-user
+    if [ "$arch" = i686 ]; then
+        # override 32-bit x86 targets to run natively (assume host is x86).
+        # workaround for upstream issue in qemu for the i386 target
+        # https://bugs.launchpad.net/qemu/+bug/1843205
+        CROSS_RUNNER=native
+    else
+        CROSS_RUNNER=qemu-user
+    fi
 fi
 
 # select qemu arch

@reitermarkus
Copy link
Member

Yes, I think that should work. I think we should default to native on all targets where this is possible.

@bors bors bot closed this as completed in 01c7eac Sep 16, 2019
@bors bors bot closed this as completed in #318 Sep 16, 2019
@Alexhuszagh Alexhuszagh added bug A-qemu Area: qemu runners A-x86 Area: x86 targets labels May 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-qemu Area: qemu runners A-x86 Area: x86 targets bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants