summary refs log tree commit diff stats
path: root/results/scraper/launchpad-without-comments/1843205
blob: c7792917a9a02c6cca81d134a4b570f9db58feb5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
Inaccurate Fmod on i386

# Qemu Version

```bash
$ qemu-i386 --version
qemu-i386 version 3.0.1 (qemu-3.0.1-4.fc29)
Copyright (c) 2003-2017 Fabrice Bellard and the QEMU Project developers
```

# Failing Source Code (C)

```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;
}
```

The code was compiled with GCC (8.3.1) on x86-64 with the flags `-O3 -m32 -lm -static`.

# Emitted (Annotated) Assembly

In order to facilitate debugging the issue, the following assembly was generated to show nothing unusual occurred during compilation. The assembly was generated with flags `-S -O3 -m32 -lm`, and then annotated to show the operands to fmod.

```asm
	.file	"a.c"
	.text
	.section	.rodata.str1.1,"aMS",@progbits,1
.LC2:
	.string	"%f\n"
	.section	.text.startup,"ax",@progbits
	.p2align 4,,15
	.globl	main
	.type	main, @function
main:
.LFB16:
	.cfi_startproc
	leal	4(%esp), %ecx
	.cfi_def_cfa 1, 0
	andl	$-16, %esp
	pushl	-4(%ecx)
	pushl	%ebp
	.cfi_escape 0x10,0x5,0x2,0x75,0
	movl	%esp, %ebp
	pushl	%ecx
	.cfi_escape 0xf,0x3,0x75,0x7c,0x6
	subl	$4, %esp
	pushl	$1076953088				; high 32-bits of double for y
	pushl	$0 						; low 32-bits of double for y
	pushl	$1130005884				; high 32-bits of double for x
	pushl	$2003187687				; low 32-bits of double for x
	call	fmod
	movl	$.LC2, (%esp)
	fstpl	4(%esp)
	call	printf
	movl	-4(%ebp), %ecx
	.cfi_def_cfa 1, 0
	addl	$16, %esp
	xorl	%eax, %eax
	leave
	.cfi_restore 5
	leal	-4(%ecx), %esp
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
.LFE16:
	.size	main, .-main
	.ident	"GCC: (GNU) 8.3.1 20190223 (Red Hat 8.3.1-2)"
	.section	.note.GNU-stack,"",@progbits
```

# Result

Running the compiled binary on x86_64 produces the expected value of `15.000000`, while using `qemu-i386 <binary>` produces the unexpected result of `-4.000000`.

This was tested against:

1. Qemu 3.0.1 for Fedora 29.
2. Qemu 4.1.0 built from source, downloaded from https://download.qemu.org/qemu-4.1.0.tar.xz
3. Qemu built-from-source against commit 90b1e3afd33226b6078fec6d77a18373712a975c.

# Building Qemu

Qemu built-from-source was compiled as follows:

```bash
mkdir build && cd build
../configure --disable-kvm --target-list="i386-linux-user"
make -j 5
```

# Results

All built versions of Qemu running the 32-bit failed to produce the accurate result. Using qemu-x86_64 against an x86_64 binary built from the same C source code produces correct results. Running the 32-bit binary natively produces the correct result.