[llvm-dev] LLVM_DYLIB and CLANG_DYLIB with MSVC

Cristian Adam via llvm-dev llvm-dev at lists.llvm.org
Sat Jun 5 06:46:29 PDT 2021

On 03/06/2021 23:09, Martin Storsjö wrote:

> On Sun, 30 May 2021, Cristian Adam via llvm-dev wrote:
>> Due to the nature of MSVC regarding default visibility of symbols 
>> (hidden by
>> default, whereas MinGW has visible by default), one needs to generate 
>> a .def
>> file with the symbols needed to be exported.
>> This is done already in two cases for LLVM_BUILD_LLVM_C_DYLIB
>> (llvm/tools/llvm-shlib/gen-msvc-exports.py) and for
>> LLVM_EXPORT_SYMBOLS_FOR_PLUGINS (llvm/utils/extract_symbols.py).
>> I've put together a patch that enables LLVM_DYLIB and CLANG_DYLIB for 
>> MSVC.
>> I tested with clang-cl from the official Clang 12 x64 Windows binary
>> release:
>>  *  Normal build: 1,42 GB
>>  *  shlib build: 536 MB
>> The shlib release build compiled and linked fine with LLVM.dll and
>> clang-cpp.dll, unfortunately it crashes at runtime.
> Without digging into the scripts, I have one hunch:
> Does the def generator script differentiate between code and data 
> symbols?
No. The CMake script just calls llvm-nm, exports the symbols and filters 
some out.

llvm-nm needs to exist beforehand. I tried using dumpbin, but it's 
slower than llvm-nm. CMake's __create_def also works, but it's not 
exporting all symbols needed to proper link.

> For the cases where accessing a data symbol from another DLL, the 
> caller would have to have seen a declaration with the dllimport 
> attribute. For functions, it doesn't matter (it just does an extra hop 
> via the import thunk), but for data variables it matters. If the def 
> file would have proper DATA annotations for such symbols, you would 
> end up with linker errors (where you'd have an undefined reference to 
> dataSymbol, where the import library only provides __imp_dataSymbol).
> This is fixed up by the autoimport feature when linking in mingw mode 
> (which, in general, requires you to link against the mingw runtime 
> too); for cases where the caller references dataSymbol but you only 
> have __imp_dataSymbol available, the linker adds an entry to a list of 
> pseudo relocations, which the mingw runtime handles when loaded, which 
> then maps sections as writable and patches up the addresses to where 
> they are located in another DLL.
> So to avoid this, we would either need to actually provide proper 
> dllimport declarations at least for all data symbols, or avoid 
> cross-DLL data accesses (by using e.g. accessor functions instead).
According to 
you need to:

    /When you export a variable from a DLL by using a .DEF file, you do
    not have to specify __declspec(dllexport) on the variable. However,
    in any file that uses the DLL, you must still use
    __declspec(dllimport) on the declaration of data.//

Then tested it out in a small project 

Then proceeded to add dllimport declarations for 
llvm::cl::TopLevelSubCommand and llvm::cl::AllSubCommands as seen in the 
updated patch:

Now llvm-nm doesn't crash anymore!

Adding the dllimport declaration for the exported data symbols should be 
less work than doing proper dllimport declaration for everything that 
uses LLVM.dll andclang-cpp.dll. Now I /just /need to find out which data 
variables I need to update.

Thank you!


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20210605/1d207d76/attachment.html>

More information about the llvm-dev mailing list