Skip to content

Force MetaDataGetDispenser to be linked into singlefilehost#127036

Open
elinor-fung wants to merge 3 commits intodotnet:mainfrom
elinor-fung:fix126634
Open

Force MetaDataGetDispenser to be linked into singlefilehost#127036
elinor-fung wants to merge 3 commits intodotnet:mainfrom
elinor-fung:fix126634

Conversation

@elinor-fung
Copy link
Copy Markdown
Member

@elinor-fung elinor-fung commented Apr 16, 2026

Add linker flags on Unix/macOS to force MetaDataGetDispenser as an undefined symbol, which makes the linker pull mscoree.o from coreclr_static. On Windows, the .def file already forces this.

Add a test that validates the export is present in the singlefilehost binary using NativeLibrary.

See #126634. We'll want to backport to 10.0.

cc @dotnet/appmodel @dotnet/dotnet-diag

Add linker flags on Unix/macOS to force MetaDataGetDispenser as
an undefined symbol, which makes the linker pull mscoree.o from
coreclr_static. On Windows, the .def file already forces this.

Add a test that validates the export is present in the singlefilehost
binary using NativeLibrary.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Ensures singlefilehost continues to export MetaDataGetDispenser (regression in .NET 10 due to static-library dead-code elimination) by forcing the symbol to remain undefined at link time so the relevant object file is pulled in, and adds a regression test to validate expected exports are present.

Changes:

  • Add Unix/macOS linker options to force MetaDataGetDispenser to be pulled from coreclr_static into singlefilehost.
  • Add an installer test that validates key singlefilehost exports (including MetaDataGetDispenser) are present.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/native/corehost/apphost/static/CMakeLists.txt Adds linker flags to force MetaDataGetDispenser to be linked into singlefilehost on non-Windows.
src/installer/tests/AppHost.Bundle.Tests/StaticHost.cs Adds a test that checks singlefilehost exports on Windows (NativeLibrary) and non-Windows (nm).

Comment thread src/installer/tests/AppHost.Bundle.Tests/StaticHost.cs Outdated
Comment thread src/installer/tests/AppHost.Bundle.Tests/StaticHost.cs Outdated
Copy link
Copy Markdown
Member

@noahfalk noahfalk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@elinor-fung
Copy link
Copy Markdown
Member Author

@copilot apply changes based on the comments in this thread

Comment thread src/native/corehost/apphost/static/CMakeLists.txt Outdated
Comment thread src/installer/tests/AppHost.Bundle.Tests/StaticHost.cs
Copilot AI review requested due to automatic review settings April 17, 2026 01:52
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

Comment thread src/installer/tests/AppHost.Bundle.Tests/StaticHost.cs
Comment thread src/native/corehost/apphost/static/CMakeLists.txt
# This should be kept in sync with singlefilehost_unixexports.src.
if(CLR_CMAKE_TARGET_APPLE)
target_link_options(singlefilehost PRIVATE
-Wl,-u,_DotNetRuntimeInfo
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we instead annotate these properly, e.g.:

--- a/src/coreclr/debug/runtimeinfo/runtimeinfo.cpp
+++ b/src/coreclr/debug/runtimeinfo/runtimeinfo.cpp
@@ -13,8 +13,9 @@
 #include <runtime_version.h>
 
 // Runtime information public export
-#ifdef HOST_UNIX
 DLLEXPORT
+#ifdef HOST_UNIX
+__attribute__((used, retain))
 #endif
 RuntimeInfo DotNetRuntimeInfo = {
     {

and then cleanup from various scripts like:

src/native/corehost/apphost/static/singlefilehost.def:DotNetRuntimeInfo                                   @4 data
src/native/corehost/apphost/static/singlefilehost_freebsdexports.src:DotNetRuntimeInfo
src/native/corehost/apphost/static/singlefilehost_unixexports.src:DotNetRuntimeInfo

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I'm missing something, but with just the attributes, MetaDataGetDispenser seems to no longer be retained?

--- a/src/coreclr/dlls/mscoree/mscoree.cpp
+++ b/src/coreclr/dlls/mscoree/mscoree.cpp
@@ -41,7 +41,11 @@ BOOL WINAPI DllMain(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved)
 // This function gets the Dispenser interface given the CLSID and REFIID.
 // Exported from coreclr and used by external profilers.
 // ---------------------------------------------------------------------------
-STDAPI DLLEXPORT MetaDataGetDispenser(  // Return HRESULT
+STDAPI DLLEXPORT
+#ifdef HOST_UNIX
+__attribute__((used, retain))
+#endif
+MetaDataGetDispenser(  // Return HRESULT
     REFCLSID    rclsid,                 // The class to desired.
> nm -D --defined-only ./artifacts/bin/linux-x64.Release/corehost/singlefilehost
0000000000bb9340 D DotNetRuntimeInfo@@V1.0
0000000000000000 A V1.0
0000000000bc6708 B g_dacTable@@V1.0

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, this is using linker script, which overrides what to keep. I wonder why linker script isn't keeping MetaDataGetDispenser as it's already there?

This workaround looks good to me, I will take a look later what can be done to make these symbols always available. I was just wondering since we used a similar linker workaround in NativeAOT BuildIntegration

<!-- this workaround can be deleted once the minimum supported glibc version
(runtime's official build machine's glibc version) is at least 2.33
see https://github.com/bminor/glibc/commit/99468ed45f5a58f584bab60364af937eb6f8afda -->
<LinkerArg Include="-Wl,--defsym,__xmknod=mknod" Condition="'$(StaticExecutable)' == 'true'" />
but it was only done for the API which wasn't owned by us. 🤔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

6 participants