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

Fail to link i686 staticlib with MSVC #36097

Closed
upsuper opened this issue Aug 29, 2016 · 8 comments
Closed

Fail to link i686 staticlib with MSVC #36097

upsuper opened this issue Aug 29, 2016 · 8 comments
Labels
O-windows-msvc Toolchain: MSVC, Operating system: Windows

Comments

@upsuper
Copy link
Contributor

upsuper commented Aug 29, 2016

See my test repo: upsuper/rust-msvc-link-test

  • Build the crate with i686-pc-windows-msvc toolchain
  • Build the C++ file with cl.exe from MSVC 2015
  • Link them together via link.exe from MSVC 2015

(The 32bit MSVC 2015 toolchain locates at "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\amd64_x86" for me)

It shows linker error like:

test.lib(test.0.o) : error LNK2019: unresolved external symbol __imp__?after@nsCSSPseudoElements@@2PAVnsICSSPseudoElement@@A referenced in function _test
test.lib(test.0.o) : error LNK2019: unresolved external symbol _?before@nsCSSPseudoElements@@2PAVnsICSSPseudoElement@@A referenced in function _test

Using dumpbin -symbols to analyse main.obj and test.lib shows that, in main.obj, the symbols are

008 00000000 SECT3  notype       External     | ?after@nsCSSPseudoElements@@2PAVnsICSSPseudoElement@@A (public: static class nsICSSPseudoElement * nsCSSPseudoElements::after)
009 00000004 SECT3  notype       External     | ?before@nsCSSPseudoElements@@2PAVnsICSSPseudoElement@@A (public: static class nsICSSPseudoElement * nsCSSPseudoElements::before)

however, in test.lib generated by rustc, the import symbols are

02A 00000000 UNDEF  notype       External     | __imp__?after@nsCSSPseudoElements@@2PAVnsICSSPseudoElement@@A
02D 00000000 UNDEF  notype       External     | _?before@nsCSSPseudoElements@@2PAVnsICSSPseudoElement@@A

Thus the mismatch.

It's even more interesting that the symbol from nested crate is different from the crate of the lib, even though they are both extern symbols.

This issue doesn't show up for 64bit build with proper link_name. The corresponding symbols in rust staticlib with x86_64 toolchain would be:

A15B 00000000 UNDEF  notype       External     | __imp_?after@nsCSSPseudoElements@@2PEAVnsICSSPseudoElement@@EA (__declspec(dllimport) public: static class nsICSSPseudoElement * nsCSSPseudoElements::after)
A15C 00000000 UNDEF  notype       External     | __imp_?before@nsCSSPseudoElements@@2PEAVnsICSSPseudoElement@@EA (__declspec(dllimport) public: static class nsICSSPseudoElement * nsCSSPseudoElements::before)

It could either because of the different prefix (__imp_ vs. __imp__ and _) or the different link type? But the linker also complains about dllimport using on static link symbols for 64bit build.

cc @alexcrichton

@upsuper
Copy link
Contributor Author

upsuper commented Aug 29, 2016

This affects Stylo. See atom_macro.rs. (The test code is also simplified from Stylo case)

@Aatch Aatch added the O-windows-msvc Toolchain: MSVC, Operating system: Windows label Aug 29, 2016
@alexcrichton
Copy link
Member

Yes I think this may have to do with dllimport at least a little? Right now we blindly apply dllimport to all imports and we rely on the linker to fix up any mistakes. This in general works for most references and will otherwise be fixed by rust-lang/rfcs#1717

The other remaining piece here is that it looks like LLVM is adding a leading _ on x86 which I believe is part of the symbol mangling ABI. You can disable I believe (untested) by changing the attribute to:

#[link_name = "\x01?..."]

That is, add a leading "1 byte" to the symbol and I think it disables the otherwise present name mangling.

@upsuper
Copy link
Contributor Author

upsuper commented Aug 30, 2016

Looks like adding \x01 at the beginning of link_name works. Thanks for the advice.

@upsuper
Copy link
Contributor Author

upsuper commented Aug 30, 2016

FWIW, it seems the warning is simply based on the name having __imp_ prefix. In this case, after I prepend the link_name with \x01, the linker no longer complains about dllimport using on static link symbos for before (but still for after because it still has __imp_ prefix).

bors-servo pushed a commit to servo/servo that referenced this issue Aug 30, 2016
Avoid LLVM prepending "_" for msvc32 symbols.

See rust-lang/rust#36097. This patch adds a workaround to that issue, which makes win32 stylo build.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/13116)
<!-- Reviewable:end -->
@alexcrichton
Copy link
Member

Ok cool! Should this be closed?

@upsuper
Copy link
Contributor Author

upsuper commented Aug 30, 2016

Should it? I suppose Rust (or LLVM) should fix this rather than relying on users to prepend an \x01 to link_name?

@retep998
Copy link
Member

@upsuper LLVM decorating symbols based on the calling convention is expected behavior and not a bug. It is surprising behavior sometimes, yes, and there are cases where you don't want it, but the majority of the time it does the right thing. Dllimport shenanigans are a different yet known issue #27438

@alexcrichton
Copy link
Member

Yes it sounds like here you're basically taking on the name mangling of MSVC yourself, so I don't think there's much we could really do here other than offer this escape hatch.

gecko-dev-updater pushed a commit to marco-c/gecko-dev-comments-removed that referenced this issue Oct 1, 2019
…rom upsuper:msvc32-atoms); r=emilio

See rust-lang/rust#36097. This patch adds a workaround to that issue, which makes win32 stylo build.

Source-Repo: https://github.com/servo/servo
Source-Revision: c55588d25b6e0390d11b2cb654ccb1f95e16cebb

UltraBlame original commit: 54bc210408658c7d7b27836cd9e04de7e2267381
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified-and-comments-removed that referenced this issue Oct 1, 2019
…rom upsuper:msvc32-atoms); r=emilio

See rust-lang/rust#36097. This patch adds a workaround to that issue, which makes win32 stylo build.

Source-Repo: https://github.com/servo/servo
Source-Revision: c55588d25b6e0390d11b2cb654ccb1f95e16cebb

UltraBlame original commit: 54bc210408658c7d7b27836cd9e04de7e2267381
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified that referenced this issue Oct 1, 2019
…rom upsuper:msvc32-atoms); r=emilio

See rust-lang/rust#36097. This patch adds a workaround to that issue, which makes win32 stylo build.

Source-Repo: https://github.com/servo/servo
Source-Revision: c55588d25b6e0390d11b2cb654ccb1f95e16cebb

UltraBlame original commit: 54bc210408658c7d7b27836cd9e04de7e2267381
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
O-windows-msvc Toolchain: MSVC, Operating system: Windows
Projects
None yet
Development

No branches or pull requests

4 participants