Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
capickett opened this issue Jul 22, 2024 · 5 comments
Labels
A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@capickett
Copy link

capickett commented Jul 22, 2024

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

let library = tcx.native_library(def_id)?;
return library.kind.is_statically_included().then_some(def_id);
? 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
@capickett capickett added the C-bug Category: This is a bug. label Jul 22, 2024
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Jul 22, 2024
@capickett capickett changed the title global_asm-implement extern "C" functions are not exported from cdylib crates global_asm-implemented extern "C" functions are not exported from dylib crates Jul 22, 2024
@bjorn3
Copy link
Member

bjorn3 commented Jul 23, 2024

The same happens if you implement the function in a static library you link into the dylib. Rustc doesn't know that the function is defined within the dylib, so it doesn't mark it as exported in the version script.

@bjorn3 bjorn3 added the A-linkage Area: linking into static, shared libraries and binaries label Jul 23, 2024
@folkertdev
Copy link
Contributor

I think that behavior is fine in theory: there is no way for rust to know that the symbol is defined. but I believe there is currently a way to force the exporting of the symbol. E.g. this does not work

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

extern "C" {
    #[export_name = "foo"]
    pub fn foo();
}

because

8 |     #[export_name = "foo"]
  |     ^^^^^^^^^^^^^^^^^^^^^^
9 |     pub fn foo();
  |     ------------- not a free function, impl method or static

So could it be a solution to provide a way to explicitly export the symbol?

@bjorn3
Copy link
Member

bjorn3 commented Jul 23, 2024

global_asm and static libraries should probably be handled the same for symbol export. You could look at the issue for the staticlib version of this behavior if such an option is already suggested.

@capickett
Copy link
Author

@bjorn3 would you mind linking the staticlib issue? I could not find it, unless you meant #104707 although that looks like the opposite problem to this one (too many exported symbols vs not enough).

@bjorn3
Copy link
Member

bjorn3 commented Jul 23, 2024

@saethlin saethlin added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. and removed needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. labels Aug 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants