Skip to content

Regression .NET 10- Missing MetaDataGetDispenser export missing for PublishSingleFile=true, and --self-contained #126634

@georgschausberger

Description

@georgschausberger

Description

See old issue: #103687

Root cause: Dead code elimination due to mscoree.cpp refactoring in .NET 10
The chain is:

  1. singlefilehost_unixexports.src is unchanged — it lists MetaDataGetDispenser in both .NET 8 and .NET 10.
  2. mscoree.cpp was massively refactored for .NET 10:
    VersionFunctions in mscoree.cppLines.NET 8/9MetaDataGetDispenser, GetMetaDataInternalInterface, GetMetaDataInternalInterfaceFromPublic, GetMetaDataPublicInterfaceFromInternal, ReOpenMetaDataWithMemory, ReOpenMetaDataWithMemoryEx, GetInternalSystemDirectory, SetInternalSystemDirectory, ...~300+.NET 10DllMain (excluded by CORECLR_EMBEDDED) + MetaDataGetDispenser60
    All the internal metadata functions were moved out into the metadata subsystem directly.
  3. coreclr_static is compiled with CORECLR_EMBEDDED defined (as seen in the CMakeLists.txt):
    With this flag, DllMain is #if'd out, leaving MetaDataGetDispenser as the only symbol from mscoree.cpp.
  4. Static library dead code elimination:
    singlefilehost links against coreclr_static without --whole-archive. The GNU linker only pulls object files from static libraries when they resolve an undefined symbol. Since nothing in singlefilehost calls MetaDataGetDispenser, the linker never pulls mscoree.o into the binary. In .NET 8/9, mscoree.o was pulled in because it contained GetInternalSystemDirectory (and other functions) referenced from within the runtime — MetaDataGetDispenser just came along for free.
    Fix for the dotnet/runtime project: force mscoree.o into the final binary, e.g. by adding -Wl,--undefined=MetaDataGetDispenser to the singlefilehost link flags, or moving MetaDataGetDispenser into a .cpp file that is already guaranteed to be linked (e.g., exports.cpp), or using attribute((used)) on the function.

PR: #116405 — "Delete extra layers" by @jkotas, merged June 9, 2025
Merge commit: c8403e6

Reproduction Steps

build single file self contained assembly and test
objdump -TC ./test | grep MetaDataGetDispenser

Expected behavior

show an exported symbol for MetaDataGetDispenser

Actual behavior

no exported symbol for MetaDataGetDispenser

Regression?

This seems to be a regression.

Known Workarounds

No response

Configuration

No response

Other information

No response

Metadata

Metadata

Assignees

Labels

Type

No type
No fields configured for issues without a type.

Projects

Status

No status

Relationships

None yet

Development

No branches or pull requests

Issue actions