rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
98.04k stars 12.69k forks source link

fmodf symbol missing on i686-unknown-uefi since nightly-2024-07-30 #128533

Open YtvwlD opened 2 months ago

YtvwlD commented 2 months ago

I'm using (a library that uses) floating point math on UEFI targets. For quite some time, fmodf was missing on i686-unknown-uefi (but available on x86_64-unknown-uefi). Since https://github.com/rust-lang/compiler-builtins/issues/490, https://github.com/rust-lang/compiler-builtins/pull/553, https://github.com/rust-lang/rust/issues/119019, this was available, but it's gone missing a few days ago. I suspect it's due to this update to compiler-builtins, but I have not confirmed it.

Code

This is a minimal (but nonsensical) example code that compiles:

#![no_std]
#![no_main]

extern "C" { fn fmodf(); }

use core::panic::PanicInfo;

#[panic_handler]
fn panic(_: &PanicInfo) -> ! {
        loop {}
}

#[no_mangle]
pub fn efi_main() {
        unsafe { fmodf(); }
}

I expected to see this happen: The code should should compile.

Instead, this happened:

$ cargo build --target i686-unknown-uefi
   Compiling foo v0.1.0 (/tmp/tmp.4CIirv1HGb/foo)
error: linking with `rust-lld` failed: exit status: 1
  |
  = note: LC_ALL="C" PATH="/home/niklas/.rustup/toolchains/nightly-2024-07-30-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin:/home/niklas/.rustup/toolchains/nightly-2024-07-30-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin:/home/niklas/.rustup/toolchains/nightly-2024-07-30-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/niklas/.local/bin:/home/niklas/.cargo/bin:/home/niklas/.gopath/bin:/home/niklas/bin:/snap/bin:/home/niklas/.local/bin:/home/niklas/.cargo/bin:/home/niklas/.gopath/bin:/home/niklas/bin:/snap/bin" VSLANG="1033" "rust-lld" "-flavor" "link" "/NOLOGO" "/entry:efi_main" "/subsystem:efi_application" "/tmp/rustckZUbYQ/symbols.o" "/tmp/tmp.4CIirv1HGb/foo/target/i686-unknown-uefi/debug/deps/foo-b50eac0687aac12d.21wnwtpp1uzembi52ejbydrsb.rcgu.o" "/LIBPATH:/tmp/tmp.4CIirv1HGb/foo/target/i686-unknown-uefi/debug/deps" "/LIBPATH:/tmp/tmp.4CIirv1HGb/foo/target/debug/deps" "/LIBPATH:/home/niklas/.rustup/toolchains/nightly-2024-07-30-x86_64-unknown-linux-gnu/lib/rustlib/i686-unknown-uefi/lib" "/home/niklas/.rustup/toolchains/nightly-2024-07-30-x86_64-unknown-linux-gnu/lib/rustlib/i686-unknown-uefi/lib/librustc_std_workspace_core-26a6383b0ec19675.rlib" "/home/niklas/.rustup/toolchains/nightly-2024-07-30-x86_64-unknown-linux-gnu/lib/rustlib/i686-unknown-uefi/lib/libcore-70427371e67f0ba1.rlib" "/home/niklas/.rustup/toolchains/nightly-2024-07-30-x86_64-unknown-linux-gnu/lib/rustlib/i686-unknown-uefi/lib/libcompiler_builtins-f2416250465866e5.rlib" "/NXCOMPAT" "/LIBPATH:/home/niklas/.rustup/toolchains/nightly-2024-07-30-x86_64-unknown-linux-gnu/lib/rustlib/i686-unknown-uefi/lib" "/OUT:/tmp/tmp.4CIirv1HGb/foo/target/i686-unknown-uefi/debug/deps/foo-b50eac0687aac12d.efi" "/OPT:REF,NOICF" "/DEBUG" "/PDBALTPATH:%_PDB%" "/NODEFAULTLIB"
  = note: rust-lld: error: undefined symbol: _fmodf
          >>> referenced by /tmp/tmp.4CIirv1HGb/foo/src/main.rs:15
          >>>               /tmp/tmp.4CIirv1HGb/foo/target/i686-unknown-uefi/debug/deps/foo-b50eac0687aac12d.21wnwtpp1uzembi52ejbydrsb.rcgu.o:(_efi_main)

error: could not compile `foo` (bin "foo") due to 1 previous error

Version it worked on

It most recently worked on:

$ rustc --version --verbose
rustc 1.82.0-nightly (2cbbe8b8b 2024-07-28)
binary: rustc
commit-hash: 2cbbe8b8bb2be672b14cf741a2f0ec24a49f3f0b
commit-date: 2024-07-28
host: x86_64-unknown-linux-gnu
release: 1.82.0-nightly
LLVM version: 18.1.7

Version with regression

$ rustc --version --verbose
rustc 1.82.0-nightly (612a33f20 2024-07-29)
binary: rustc
commit-hash: 612a33f20b9b2c27380edbc4b26a01433ed114bc
commit-date: 2024-07-29
host: x86_64-unknown-linux-gnu
release: 1.82.0-nightly
LLVM version: 18.1.7

Backtrace

There's no crash.

tgross35 commented 2 months ago

Could you run nm -Cg /home/niklas/.rustup/toolchains/nightly-2024-07-30-x86_64-unknown-linux-gnu/lib/rustlib/i686-unknown-uefi/lib/libcompiler_builtins-f2416250465866e5.rlib | grep fmodf and post the output? The symbols should still be available, just as weak, so this should help confirm.

YtvwlD commented 2 months ago
$ LANG=C nm -Cg /home/niklas/.rustup/toolchains/nightly-2024-07-30-x86_64-unknown-linux-gnu/lib/rustlib/i686-unknown-uefi/lib/libcompiler_builtins-f2416250465866e5.rlib | grep fmodf
nm: compiler_builtins-f2416250465866e5.compiler_builtins.326ac9b642684df2-cgu.000.rcgu.o: no symbols
nm: compiler_builtins-f2416250465866e5.compiler_builtins.326ac9b642684df2-cgu.001.rcgu.o: no symbols
...
tgross35 commented 2 months ago

Does it show up on the working version?

YtvwlD commented 2 months ago

No, I guess.

$ LANG=C nm -Cg /home/niklas/.rustup/toolchains/nightly-2024-07-29-x86_64-unknown-linux-gnu/lib/rustlib/i686-unknown-uefi/lib/libcompiler_builtins-b5d296eafb84defb.rlib | grep fmodf
nm: compiler_builtins-b5d296eafb84defb.compiler_builtins.b7ee1e4ea5a8642f-cgu.000.rcgu.o: no symbols
nm: compiler_builtins-b5d296eafb84defb.compiler_builtins.b7ee1e4ea5a8642f-cgu.001.rcgu.o: no symbols
...
YtvwlD commented 2 months ago

But it seems to be there, somehow:

$ LANG=C grep -r fmodf /home/niklas/.rustup/toolchains/nightly-2024-07-29-x86_64-unknown-linux-gnu/lib/rustlib/i686-unknown-uefi/lib/
grep: /home/niklas/.rustup/toolchains/nightly-2024-07-29-x86_64-unknown-linux-gnu/lib/rustlib/i686-unknown-uefi/lib/libcompiler_builtins-b5d296eafb84defb.rlib: binary file matches
$ LANG=C grep -r fmodf /home/niklas/.rustup/toolchains/nightly-2024-07-30-x86_64-unknown-linux-gnu/lib/rustlib/i686-unknown-uefi/lib/
$
tgross35 commented 2 months ago

(edited the above comments to remove output noise)

tgross35 commented 2 months ago

Thanks for looking into it. compiler_builtins recently had an update that should have made math symbols available on platforms that support it (Linux), but maybe in doing so it disabled the symbols completely on platforms that don't support it.

YtvwlD commented 2 months ago

It's still available on x86_64-unknown-uefi though:

$ LANG=C grep -r fmodf /home/niklas/.rustup/toolchains/nightly-2024-07-30-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-uefi/lib/
grep: /home/niklas/.rustup/toolchains/nightly-2024-07-30-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-uefi/lib/libcompiler_builtins-b761541e09399289.rlib: binary file matches
$ LANG=C grep -r fmodf /home/niklas/.rustup/toolchains/nightly-2024-07-29-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-uefi/lib/
grep: /home/niklas/.rustup/toolchains/nightly-2024-07-29-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-uefi/lib/libcompiler_builtins-3c95a63685c02bd4.rlib: binary file matches
apiraino commented 2 weeks ago

@YtvwlD I'm visiting this issue again. On current stable I cannot reproduce (unless I'm doing it wrong)

$ cargo build --target i686-unknown-uefi
   Compiling issue-128533 v0.1.0 (/home/me/tmp/issue-128533)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.67s

$ rustc --version --verbose
rustc 1.81.0 (eeb90cda1 2024-09-04)
binary: rustc
commit-hash: eeb90cda1969383f56a2637cbd3037bdf598841c
commit-date: 2024-09-04
host: x86_64-unknown-linux-gnu
release: 1.81.0
LLVM version: 18.1.7

can you confirm if it's fixed for you or you can still reproduce?

thanks

YtvwlD commented 2 weeks ago

You're right: It compiles on current stable.

> rustc --version --verbose
rustc 1.81.0 (eeb90cda1 2024-09-04)
binary: rustc
commit-hash: eeb90cda1969383f56a2637cbd3037bdf598841c
commit-date: 2024-09-04
host: x86_64-unknown-linux-gnu
release: 1.81.0
LLVM version: 18.1.7

It's still broken on nightly, though:

> rustc --version --verbose
rustc 1.83.0-nightly (6f4ae0f34 2024-10-08)
binary: rustc
commit-hash: 6f4ae0f34503601e54680a137c1db0b81b56cc3d
commit-date: 2024-10-08
host: x86_64-unknown-linux-gnu
release: 1.83.0-nightly
LLVM version: 19.1.1

Weird.

tgross35 commented 2 weeks ago

We changed compiler_builtins to provide these math symbols weakly on all platforms (including platforms that actually provide them) but wound up changing it back before it hit stable. It wasn’t an exact revert though, the config changed slightly - so my guess is uefi just isn’t getting them enabled still.

I can’t look at this right now but if anyone wants to take a peek, check the config in the math module of the compiler-builtins repo

YtvwlD commented 2 weeks ago

Could you point me to the changed configuration? I've tried git log -p origin/master..origin/stable but I didn't see any change to compiler-builtins?

tgross35 commented 2 weeks ago

This is where we control whether math symbols are available https://github.com/Amjad50/compiler-builtins/blob/0fab77e8d72cf232af4977642b52544f0e4ab521/src/lib.rs#L50-L61, I think something around https://github.com/Amjad50/compiler-builtins/blob/127bbc53b5a8986abff28b3af1524342427bf38f/src/lib.rs#L48-L56 would have been the state before the mentioned nightly (2024-07-30). Does our i686 UEFI target not require sse2 or something? I'm not sure why it would not be getting the symbols in the current config.

tgross35 commented 2 weeks ago

Ah, no sse2 is indeed the case

$ rustc --print cfg --target i686-unknown-uefi | grep sse
debug_assertions
$ rustc --print cfg --target i686-unknown-linux-gnu | grep sse
debug_assertions
target_feature="sse"
target_feature="sse2"

Were you using fmodf symbols successfully before 2024-07-30, i.e. with correct results? Because of https://github.com/rust-lang/rust/issues/114479 (linked in the module config) the results are probably unreliable.

I think maybe what we should do here is provide fallback math symbols on non-unix x86 platforms that don't have SSE and just call unimplemented!, so we avoid linking errors but don't give useless results.

beetrees commented 2 weeks ago

The math symbols should work fine on i686-unknown-uefi as it's a soft-float target (the miscompilations only affect hard-float targets). Although there's no cfg for soft-float, as there's no hard-float i686 UEFI target always enabling the math symbols when target_os = "uefi" should work fine.

YtvwlD commented 2 weeks ago

I haven't actually used the float functions, no. As far as I'm aware they're being pulled in because I'm reading a configuration file and it could contain floats, but it doesn't.

tgross35 commented 2 weeks ago

I think the cfg that I linked in compiler-builtins just needs to update all(target_arch = "x86", not(target_feature = "sse2")), to all(target_arch = "x86", not(target_feature = "sse2"), not(target_os = "uefi")), to be in line with what beetrees said. Would you be able to put up a PR @YtvwlD?