rust-lang / rust-lang/rust

global_asm-implemented extern "C" functions are not exported from dylib crates

Open
#128,071 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-linkage C-bug T-compiler
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

I tried this code, which is a minimized reproduction of https://github.com/EmbarkStudios/crash-handling/blob/main/crash-context/src/linux/getcontext.rs#L3-L12 and https://github.com/EmbarkStudios/crash-handling/blob/main/crash-context/src/linux/getcontext/x86_64.rs#L48:

std::arch::global_asm! {
    ".global foo",
"foo:",
    "ret",
}

extern "C" {
    pub fn foo();
}

With lib.crate-type set to ["dylib"] or ["cdylib"].

I expected to see this happen: When building the example code here as an rdylib or cdylib, I expected to see foo present in the output dylib's symbols.

Instead, this happened: The output dylib has no symbols. It seems that for some reason, despite foo being a pub fn, the function is omitted from the list of extern symbols passed into the version-script. The symbol list file in my local case is completely empty. My guess here is that because foo is an extern "C" function, it's expected that the symbol is exported in some other object file / archive that would be statically linked in and then (maybe) caught by this https://github.com/rust-lang/rust/blob/20f23abbecd7ac5e04dd7ccadc29c3824e28a269/compiler/rustc_codegen_ssa/src/back/symbol_export.rs#L82-L83 ? But I am no rustc expert to say for sure.

$ cargo build
$ nm  target/debug/libdylib_global_asm.dylib | grep foo
target/debug/libdylib_global_asm.dylib: no symbols

One way to force the symbol here, as I'm running on an M1 mac, is to do the following:

$ RUSTFLAGS="-Clink-arg=-Wl,-exported_symbol,foo" cargo build
$ nm  target/debug/libdylib_global_asm.dylib | grep foo
0000000000003fa4 T foo
Meta

Tested on both stable + nightly.

rustc --version --verbose:

rustc 1.79.0 (129f3b996 2024-06-10)
binary: rustc
commit-hash: 129f3b9964af4d4a709d1383930ade12dfe7c081
commit-date: 2024-06-10
host: aarch64-apple-darwin
release: 1.79.0
LLVM version: 18.1.7

and 

rustc 1.82.0-nightly (92c6c0380 2024-07-21)
binary: rustc
commit-hash: 92c6c03805408a1a261b98013304e9bbf59ee428
commit-date: 2024-07-21
host: aarch64-apple-darwin
release: 1.82.0-nightly
LLVM version: 18.1.7

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the minimized global_asm! reproduction and compare dylib and cdylib builds using cargo build and nm. Read compiler/rustc_codegen_ssa/src/back/symbol_export.rs, especially the referenced lines, to trace why the extern "C" symbol list is empty. Done means foo is exported from the generated dylib without the manual linker flag.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.