-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Description
Summary
On Windows, when building LLVM with CLANG_LINK_CLANG_DYLIB=ON
, external plugins cannot register themselves through llvm::Registry<clang::PluginASTAction>
due to two issues:
- Static data members (
Head
,Tail
) are filtered out during symbol export - Static methods (
add_node()
,begin()
) are not linked into the executable
This breaks the plugin registration mechanism that relies on static initialization.
Affected Versions
- LLVM 19, 20, 21, and main branch (verified 2025-01-14)
- Specifically affects Windows builds with
CLANG_LINK_CLANG_DYLIB=ON
Problem Description
Issue 1: Registry symbols filtered from DLL exports
The script llvm/utils/extract_symbols.py
generates .def
files for Windows DLL symbol exports. At line 126, it filters symbols with this regex:
elif re.search(r"(llvm|clang)@@[A-Z][A-Z0-9_]*[A-JQ].+(X|.+@|.*Z)$", symbol):
This pattern matches MSVC-mangled function symbols but excludes static data members, which have @@0
or @@3
suffixes. The Registry<T>
static members Head
and Tail
are therefore filtered out:
?Head@?$Registry@VPluginASTAction@clang@@@llvm@@0PEAVnode@12@EA
?Tail@?$Registry@VPluginASTAction@clang@@@llvm@@0PEAPEAVnode@12@EA
Without these symbols exported, plugins cannot access the registry's linked list.
Issue 2: Registry methods not linked into executable
Even if the symbols are exported from the DLL, the Registry<T>
methods add_node()
and begin()
exist in libraries but aren't linked into clang.exe
by default because nothing in the main executable references them. When plugins try to call these functions, they fail because the symbols aren't present in the executable's import address table.
Reproduction
- Build LLVM with
-DCLANG_LINK_CLANG_DYLIB=ON -DLLVM_EXPORT_SYMBOLS_FOR_PLUGINS=ON
on Windows - Create an external plugin that registers via
Registry<PluginASTAction>
- Try to load the plugin with
clang.exe -Xclang -load -Xclang plugin.dll
Result: Plugin fails to register, either due to missing symbols or unresolved externals.
Expected Behavior
Plugins should be able to register themselves using the Registry<T>
pattern, as they can on Linux/macOS and as documented in the LLVM plugin documentation.
Context
This issue was discovered while enabling Clang 20 support for Firefox's clang-plugin on Windows. Firefox has been working around similar issues with local patches, but this affects any downstream project trying to build Windows plugins with dynamic linking.
The Registry<T>
pattern is fundamental to LLVM's plugin infrastructure and is used throughout the codebase for various plugin types (PluginASTAction
, PassBuilderOptPluginPass
, etc.).
Related
llvm/utils/extract_symbols.py
- Symbol export scriptclang/tools/driver/driver.cpp
- Main executablellvm/include/llvm/Support/Registry.h
- Registry template definition