Skip to content

Linking a Rust staticlib unexpectedly changes C math functions from libm to bundled ones from compiler-builtins #142119

Open
@durin42

Description

@durin42
Contributor

Code

Given a staticlib with the source:

#[unsafe(no_mangle)]
pub extern "C" fn demo() -> f32 {
    let x : f32 = 1.1;
    x.ceil()
}

compiled as crate-type = ["staticlib"] and the C program:

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

float demo();

int main(int argc, char** argv) {
    float x = -1.2;
    printf("%f\n", ceilf(x));
    printf("%f\n", demo());
    return 0;
}

When linking the program like this: $(CC) main.o as-crate/target/debug/libas_crate.a -lm -o out/tgt-from-crate the resulting binary ends up using ceilf from compiler-builtins rather than libm.

I expected to see this happen: The binary should still get ceilf from libm, eg

$ nm -uD out/tgt-from-crate | grep ceilf || true
                 U ceilf@GLIBC_2.2.5

Instead, this happened: Instead, the ceilf symbol was satisfied by the matching symbol in compiler-builtins, and so the C call was surprise-migrated to a different implementation.

Version it worked on

1.86
rustc --version --verbose:

rustc 1.86.0 (05f9846f8 2025-03-31)
binary: rustc
commit-hash: 05f9846f893b09a1be1fc8560e33fc3c815cfecb
commit-date: 2025-03-31
host: x86_64-unknown-linux-gnu
release: 1.86.0
LLVM version: 19.1.7

Version with regression

1.87
rustc --version --verbose:

rustc 1.87.0 (17067e9ac 2025-05-09)
binary: rustc
commit-hash: 17067e9ac6d7ecb70e50f92c1944e545188d2359
commit-date: 2025-05-09
host: x86_64-unknown-linux-gnu
release: 1.87.0
LLVM version: 20.1.1

Additional information

I suspect this is related to some work tracked in #137578. I also found out Chromium has already stumbled on this: https://issues.chromium.org/issues/419258012#comment5 and for them it caused observable behavior changes. Apologies for not catching this sooner - we hadn't upgraded compiler-builtins for a while and didn't notice until a couple of weeks ago. :(

Activity

added
C-bugCategory: This is a bug.
regression-untriagedUntriaged performance or correctness regression.
on Jun 6, 2025
added
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
I-prioritizeIssue: Indicates that prioritization has been requested for this issue.
on Jun 6, 2025
jieyouxu

jieyouxu commented on Jun 6, 2025

@jieyouxu
tgross35

tgross35 commented on Jun 6, 2025

@tgross35
added
A-linkageArea: linking into static, shared libraries and binaries
A-compiler-builtinsArea: compiler-builtins (https://github.com/rust-lang/compiler-builtins)
and removed
needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.
on Jun 8, 2025
Noratrieb

Noratrieb commented on Jun 8, 2025

@Noratrieb
Member
bisection script

#!/usr/bin/env bash

set -ex

rustc --crate-type=staticlib a.rs
cc main.c liba.a -lm -o main

not nm -uD main | rg ceilf

searched nightlies: from nightly-2024-05-01 to nightly-2025-05-20
regressed nightly: nightly-2025-03-06
searched commit range: f9e0239...30f168e
regressed commit: ac951d3

bisected with cargo-bisect-rustc v0.6.8

Host triple: x86_64-unknown-linux-gnu
Reproduce with:

cargo bisect-rustc github --start 2024-05-01 --end 2025-05-20 --script repro.sh 

rust-lang/compiler-builtins#763

Noratrieb

Noratrieb commented on Jun 8, 2025

@Noratrieb
Member

It looks like rust-lang/compiler-builtins#763 just doesn't work, even a normal rust main reproducer picks ceilf from compiler-builtins instead of libc.

fn main() {
    let x : f32 = std::hint::black_box(1.1);
    dbg!(x.ceil());
}
nora@nixos /t/scratchBGHE6xUbh> rustc a.rs
nora@nixos /t/scratchBGHE6xUbh> nm -uD a | rg ceil
nora@nixos /t/scratchBGHE6xUbh [0|1]> rustc +1.84.1 a.rs
nora@nixos /t/scratchBGHE6xUbh> nm -uD a | rg ceil
                 U ceilf@GLIBC_2.2.5
Noratrieb

Noratrieb commented on Jun 8, 2025

@Noratrieb
Member

I'm a bit confused, this case for pure-rust programs was reported in #139487 but closed. But rust-lang/compiler-builtins#763 intended to not override anything, so that still seems like a bug? This here is just an extension of it where it will infect FFI as well, instead of just Rust.
@tgross35 is it intended that Rust programs now always call the compiler-builtins version?

added
regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.
and removed
regression-untriagedUntriaged performance or correctness regression.
on Jun 8, 2025
added
T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
on Jun 8, 2025

4 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-compiler-builtinsArea: compiler-builtins (https://github.com/rust-lang/compiler-builtins)A-linkageArea: linking into static, shared libraries and binariesC-bugCategory: This is a bug.P-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-libsRelevant to the library team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @durin42@Amanieu@tgross35@jieyouxu@rustbot

        Issue actions

          Linking a Rust staticlib unexpectedly changes C math functions from libm to bundled ones from compiler-builtins · Issue #142119 · rust-lang/rust