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

Public "stdcall" symbol not exported on cdylib on i686-pc-windows-gnu #50176

Open
YaLTeR opened this issue Apr 23, 2018 · 29 comments
Open

Public "stdcall" symbol not exported on cdylib on i686-pc-windows-gnu #50176

YaLTeR opened this issue Apr 23, 2018 · 29 comments
Labels
A-FFI Area: Foreign function interface (FFI) A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. O-windows-gnu Toolchain: GNU, Operating system: Windows O-x86_32 Target: x86 processors, 32 bit (like i686-*) T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@YaLTeR
Copy link
Contributor

YaLTeR commented Apr 23, 2018

I'm making a cdylib crate which exports a function in the following manner:

#[no_mangle]
pub extern "system" fn SomeFunction() {}

The library is then supposed to be loaded by another program at runtime and the function dlsym'd from it.

This works everywhere (32/64-bit Linux, macOS, 32/64-bit Windows MSVC, 64-bit Windows GNU) except the i686-pc-windows-gnu target where the function isn't being exported from the resulting DLL for some reason.

Minimal example is the code above in a clean crate with crate-type = ["cdylib"].

Possibly related: #50007, although for me the bug occurrs in both debug and release.

Rust: stable (1.25.0), beta, nightly.

@retep998 retep998 added the O-windows-gnu Toolchain: GNU, Operating system: Windows label Apr 23, 2018
YaLTeR added a commit to YaLTeR/vapoursynth-rs that referenced this issue May 10, 2018
@dpelevin
Copy link

dpelevin commented Aug 9, 2018

Here is a sample project to reproduce the bug:
https://github.com/dpelevin/bug_with_dll_exports

I can reproduce it using 'x86_64-pc-windows-gnu' target, but not 'x86_64-pc-windows-msvc'.

The other interesting thing, is that in 'release' mode with

[profile.release]
lto = true

it is not reproduced. It happens only while 'debug' builds and 'release' builds with LTO turned off.

rustc 1.28.0 (9634041 2018-07-30)
gcc.exe (Rev1, Built by MSYS2 project) 8.2.0

@ancwrd1
Copy link

ancwrd1 commented Aug 20, 2018

I can reproduce this for "system" calling convention. When using "C" calling convention the symbols are exported correctly.

Happens for i686-pc-windows-gnu target, both debug and release. The x86_64-pc-windows-gnu target works. Tried it with different MinGW versions including cross-platform build (under Linux host).

@XAMPPRocky XAMPPRocky added A-FFI Area: Foreign function interface (FFI) C-bug Category: This is a bug. labels Sep 25, 2018
@Prior99
Copy link

Prior99 commented Oct 29, 2018

Did you ever find a workaround for this? I have a similar problem with the opus-sys crate where the compiler removes all other symbols except for the opus ones.

@ancwrd1
Copy link

ancwrd1 commented Oct 29, 2018

No solution with just cargo build. I do it with custom RUSTFLAGS and running build script for x86 target.

RUSTFLAGS="-C link-arg=exports.def"

exports.def contains symbols to be exported.

@Prior99
Copy link

Prior99 commented Oct 29, 2018

@Dremon I am struggling with this for days. Thank you for your help. Do you happen to have an example project with an example .def file somewhere?

@ancwrd1
Copy link

ancwrd1 commented Oct 29, 2018

It's pretty simple:

LIBRARY yourlibname
EXPORTS
    ExportedRustFunction1
    ExportedRustFunction2

And the Rust code is:

#[no_mangle]
pub unsafe extern "system" fn ExportedRustFunction1() {
}

@Prior99
Copy link

Prior99 commented Oct 29, 2018

@Dremon With x86_64-pc-windows-gnu?

For me it still cannot find the symbols:

  = note: Cannot export MAIN: symbol not defined
          Cannot export VSTPluginMain: symbol not defined

Perhaps they vanish or are optimized out before getting exported?

@ancwrd1
Copy link

ancwrd1 commented Oct 29, 2018

It works with both x86_64- and i686-pc-windows-gnu (I only had this issue with i686 though).

@ancwrd1
Copy link

ancwrd1 commented Oct 29, 2018

I think it will only work for the symbols from your crate, not for symbols from any dependencies.

@Prior99
Copy link

Prior99 commented Oct 30, 2018

Yeah, that was what I was trying to accomplish. Thanks for your time.

@mati865
Copy link
Contributor

mati865 commented Dec 27, 2019

Triage: seems to work fine.

Tested debug and release for each i686-pc-windows-gnu and x86_64-pc-windows-gnu using examples from #50176 (comment) and #50176 (comment) but could not reproduce any issue.

@dpelevin
Copy link

dpelevin commented Dec 27, 2019

I'll recheck if problem still take place with a last Rust release.

@dpelevin
Copy link

dpelevin commented Dec 27, 2019

Cargo.toml

[workspace]
members = [
"tlib",
"tbin"
]

[profile.release]
lto = false

Compilation:

D:\rustProjects\bug_with_dll_exports>rustup default
stable-x86_64-pc-windows-gnu (default)

D:\rustProjects\bug_with_dll_exports\target>rustc --version
rustc 1.40.0 (73528e3 2019-12-16)

D:\rustProjects\bug_with_dll_exports>gcc.exe --version
gcc.exe (Rev1, Built by MSYS2 project) 8.2.1 20181214

D:\rustProjects\bug_with_dll_exports>cargo build --release
Compiling tlib v0.0.0 (D:\rustProjects\bug_with_dll_exports\tlib)
Compiling tbin v0.1.0 (D:\rustProjects\bug_with_dll_exports\tbin)
Finished release [optimized] target(s) in 1.37s

D:\rustProjects\bug_with_dll_exports>cargo build
Compiling tlib v0.0.0 (D:\rustProjects\bug_with_dll_exports\tlib)
Compiling tbin v0.1.0 (D:\rustProjects\bug_with_dll_exports\tbin)
Finished dev [unoptimized + debuginfo] target(s) in 0.55s

Release dll:
image

Debug dll:
image

@mati865, the issue is still in place.

Release (with LTO):
image

@dpelevin
Copy link

I've tried to update msys2 packages, but nothing has changed.

D:\rustProjects\bug_with_dll_exports\target\debug>gcc.exe --version
gcc.exe (Rev2, Built by MSYS2 project) 9.2.0

D:\rustProjects\bug_with_dll_exports\target\debug>ld.exe --version
GNU ld (GNU Binutils) 2.33.1

@mati865
Copy link
Contributor

mati865 commented Dec 27, 2019

@dpelevin right, it was my oversight. I can reproduce your issue with Linux and MinGW targets so it appears to be different issue. I think I saw it reported somewhere but cannot find it.

@mati865
Copy link
Contributor

mati865 commented Apr 3, 2020

I believe we can close this issue as there is nothing MinGW specific left.
@dpelevin your issue is tracked in #50007

@YaLTeR
Copy link
Contributor Author

YaLTeR commented Apr 3, 2020

What Rust version was this fixed in?

@mati865
Copy link
Contributor

mati865 commented Apr 3, 2020

@YaLTeR I have no idea, with current nightly I'm getting:

$ nm target/i686-pc-windows-gnu/debug/foo.dll | grep SomeFunction
63b81470 T _SomeFunction@0

YaLTeR added a commit to YaLTeR/vapoursynth-rs that referenced this issue Apr 4, 2020
@YaLTeR
Copy link
Contributor Author

YaLTeR commented Apr 4, 2020

Seems to still be an issue on current beta.

@YaLTeR
Copy link
Contributor Author

YaLTeR commented Apr 4, 2020

Actually doesn't work even on 1.44.0-nightly (74bd074 2020-04-03) on my CI. I can check manually on Windows.

@mati865
Copy link
Contributor

mati865 commented Apr 4, 2020

I've been cross compiling for i686 windows-gnu from x86_64 windows-gnu and linux-gnu toolchains.
I'll check native i686 toolchain in the evening today (CEST timezone).

@mati865
Copy link
Contributor

mati865 commented Apr 4, 2020

@YaLTeR example from this thread works fine for me. Could you check it yourself and open new issue with steps to reproduce?

Cargo.toml

$ cat /tmp/tmp/foo/Cargo.toml
[package]
name = "foo"
version = "0.1.0"
authors = ["foo"]
edition = "2018"

[lib]
crate-type = ["cdylib"]

src/lib.rs

#[no_mangle]
pub extern "system" fn SomeFunction() {}

@YaLTeR
Copy link
Contributor Author

YaLTeR commented Apr 5, 2020

I get the issue using the exact same setup as in the original post and as in your comment. Building in MSYS2 32-bit with the nightly-i686-pc-windows-gnu toolchain gives me a DLL without SomeFunction exported, as per Dependency Walker:
изображение
Same crate built using e.g. stable-x86_64-pc-windows-gnu toolchain:
изображение

So the issue is very much still there.

@mati865
Copy link
Contributor

mati865 commented Apr 5, 2020

@YaLTeR is your Cargo.toml the same as mine in #50176 (comment)?
Dependency walker hangs for me (both 32 and 64 bit executables when trying to open dll built by i686 toolchain on Win 10). Could you try with different tool like nm to rule out Dependency Walker bug?
I'm running out of ideas.

@YaLTeR
Copy link
Contributor Author

YaLTeR commented Apr 5, 2020

is your Cargo.toml the same as mine in #50176 (comment)?

Yes.

to rule out Dependency Walker bug

Well, it fails on my CI where the target program attempts to load the function at runtime and doesn't find it in the .dll (which works for all other variants of the toolchain).

Here's what nm outputs:

$ nm target/debug/foo.dll | grep SomeFunction
68d414a0 T _SomeFunction@0

And here's what it outputs for a good .dll (stable-x86_64):

$ nm target/debug/foo.dll | grep SomeFunction
0000000068b41420 T SomeFunction

@mati865
Copy link
Contributor

mati865 commented Apr 5, 2020

@YaLTeR it looks good IMO.
Looking at CI error replacing some of extern "system" with extern "C" in your source code should fix it.

@YaLTeR
Copy link
Contributor Author

YaLTeR commented Apr 5, 2020

Oh, but I'm using extern "system" because the target program expects stdcall on 32-bit Windows:

#if defined(_WIN32) && !defined(_WIN64)
#    define VS_CC __stdcall
#else
#    define VS_CC
#endif

It gives the desired behavior on all toolchains (including i686-msvc) except i686-gnu where the function is not visible or not exported or something.

@mati865
Copy link
Contributor

mati865 commented Apr 5, 2020

I don't know enough about stdcall convention to tell for sure but this may require import library without @ decoration to work.

@Dylan-DPC please reopen this issue, sorry for the inconvenience.

@petrochenkov petrochenkov reopened this Apr 7, 2020
@jonas-schievink jonas-schievink added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-linkage Area: linking into static, shared libraries and binaries labels May 9, 2020
mati865 added a commit to mati865/rust that referenced this issue Jul 29, 2020
bors added a commit to rust-lang-ci/rust that referenced this issue Jul 29, 2020
MinGW: enable dllexport/dllimport

Fixes (only when using LLD) rust-lang#50176
Fixes rust-lang#72319

This makes `windows-gnu` on pair with `windows-msvc` when it comes to symbol exporting.
For MinGW it means both good things like correctly working dllimport/dllexport, ability to link with LLD and bad things like rust-lang#27438.

Not sure but maybe this should land behind unstable compiler option (`-Z`) or environment variable?
@petrochenkov petrochenkov changed the title Public symbol not exported on cdylib on i686-pc-windows-gnu Public "stdcall" symbol not exported on cdylib on i686-pc-windows-gnu Apr 8, 2022
@halvors
Copy link

halvors commented Apr 27, 2023

I am still experiencing this issue with stdcall not being exported on latest stable Rust version 1.69.0. Was this issue solved or worked around in some way i am not aware of?

@Noratrieb Noratrieb added O-x86_32 Target: x86 processors, 32 bit (like i686-*) and removed O-x86-all labels Oct 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-FFI Area: Foreign function interface (FFI) A-linkage Area: linking into static, shared libraries and binaries C-bug Category: This is a bug. O-windows-gnu Toolchain: GNU, Operating system: Windows O-x86_32 Target: x86 processors, 32 bit (like i686-*) 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