Closed jevansaks closed 2 months ago
FYI @MichalStrehovsky
Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas See info in area-owners.md if you want to be subscribed.
@MichalStrehovsky fixed by https://github.com/dotnet/runtime/pull/106132?
@MichalStrehovsky fixed by #106132?
No, that one only affects OptimizationPreference=Size and there's no observable failure mode. We still don't know what this one is. I'm going to spend time on this in the coming weeks.
I'll jot down what I found out:
DllCanUnloadNow
, the output of cl.exe
does not place DllCanUnloadNow
in the gfids section of the object file. This is kind of expected - DllCanUnloadNow
is not referenced from anywhere nor address taken.DllCanUnloadNow
using a DEF file, linker will place the symbol in the gfids of the output DLL. The entrypoint is also marked "export suppressed" (the E letter next to the entry in the output of dumpbin /loadconfig
on the output DLL).1 also happens for native AOT, but only if StackTraceSupport=false
is in the project file (like in the @jevansaks repro repository). If StackTraceSupport=false is not in the project file, the AOT compiler assumes the symbol is address exposed and places it in the gfids.
For some reason that I want not able to figure out, 2 does not happen for native AOT object files. Linker is not happy about something and won't automatically consider the symbol address exposed even though it's exported through the DEF file.
Of course, we can just work around by making sure 1 never happens and exported symbols are always considered address exposed in the compiler.
For some reason that I want not able to figure out, 2 does not happen for native AOT object files.
You can ask linker dev to figure this out for you. This may be a symptom of some other problem that we may want to fix.
For some reason that I want not able to figure out, 2 does not happen for native AOT object files.
You can ask linker dev to figure this out for you. This may be a symptom of some other problem that we may want to fix.
I've sent them an email with a repro... will see.
Description
Using ControlFlowGuard when creating a native dll that uses CsWinRT (which generates the DllGetActivationFactory and DllCanUnloadNow native exports) and publishing that as AOT creates a dll with DllCanUnloadNow not in the icall table. This causes an external caller of DllCanUnloadNow (in my case, combase.dll since this is part of implementing the WinRT contract) to failfast with FAST_FAIL_GUARD_ICALL_CHECK_FAILURE.
Reproduction Steps
Minimal repro project with repro steps in readme:
https://github.com/jevansaks/NAOTControlFlowGuardRepro/tree/main
Expected behavior
All exports of the dll should be in the CFG table since they're designed to be called virtually.
Actual behavior
DllGetActivationFactory export is in the CFG table but DllCanUnloadNow is not.
Regression?
I don't know. Probably not a regression.
Known Workarounds
No response
Configuration
.NET 8, running on Windows 11, compiling for windows-x64 native. I didn't try any other windows native targets.
Other information
No response