Skip to content

Switch to lld makes difficult cdylib that is both a so and an executable #146780

@izissise

Description

@izissise

Code

I tried this code:

// Cargo.toml
[lib]
crate-type = ["cdylib"]

// build.rs
if os == "linux" {
    println!("cargo:rustc-link-arg=-Wl,-pie");
    println!("cargo:rustc-link-arg=/usr/lib/x86_64-linux-gnu/Scrt1.o");
    println!("cargo:rustc-link-arg=-Wl,--dynamic-linker=/lib64/ld-linux-x86-64.so.2");
    println!("cargo:rustc-link-arg=-Wl,--allow-multiple-definition"); // when compiling for tests
} else if os == "macos" {
    println!("cargo:rustc-link-arg=-Wl,-execute");
    println!("cargo:rustc-link-arg=-Wl,-e,_main");
    println!("cargo:rustc-link-arg=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/crt1.o");
}


// lib.rs
/// 🪄 dynlib become an executable!
/// Entrypoint linux
#[cfg(not(test))]
#[allow(clippy::similar_names, clippy::panic, reason = "standard")]
#[expect(unsafe_code, reason = "ffi")]
#[unsafe(no_mangle)]
pub extern "C" fn main(_argc: i32, _argv: *const *const i8, _env: *const *const i8) -> i32 {
    // optional: parse argv if you need them
    match exec_async() {
        Ok(()) => 0,
        Err(e) => panic!("{e}"),
    }
}

/// 🪄 dynlib become an executable!
/// Entrypoint macosx
#[cfg(not(test))]
#[allow(clippy::similar_names, reason = "standard")]
#[expect(unsafe_code, reason = "ffi")]
#[unsafe(no_mangle)]
pub extern "C" fn _main(argc: i32, argv: *const *const i8, env: *const *const i8) -> i32 {
    main(argc, argv, env)
}

I expected to see this happen:
In rust 1.89 with BFD linker this works great, I can do ./target/*/*.so and the .so behave like a normal executabe.

Instead, this happened:
In rust 1.90 with LLD linker this doesn't work anymore,
note: rust-lld: error: -shared and -pie may not be used together
after removing -pie flag it compiles, the .so has a _start symbol but it call to a null value

Version it worked on

It most recently worked on: 1.89

Version with regression

rustc --version --verbose:

rustc 1.90.0 (1159e78c4 2025-09-14)
binary: rustc
commit-hash: 1159e78c4747b02ef996e55082b704c09b970588
commit-date: 2025-09-14
host: x86_64-unknown-linux-gnu
release: 1.90.0
LLVM version: 20.1.8

@rustbot modify labels: +regression-from-stable-to-stable -regression-untriaged

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-lldArea: Linkage issues specific to rust-lldC-bugCategory: This is a bug.C-external-bugCategory: issue that is caused by bugs in software beyond our controlE-needs-mcveCall for participation: This issue has a repro, but needs a Minimal Complete and Verifiable ExampleT-compilerRelevant to the compiler 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

    Issue actions