Skip to content

Commit

Permalink
Generate the DAC table on Windows with MSVC linker directives instead…
Browse files Browse the repository at this point in the history
… of resource injection (#68065)
  • Loading branch information
jkoritzinsky authored May 12, 2022
1 parent dd3cd5d commit 04e65d2
Show file tree
Hide file tree
Showing 35 changed files with 681 additions and 22,147 deletions.
7 changes: 5 additions & 2 deletions docs/design/coreclr/botr/dac-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,15 @@ Even better, in a DAC build, the DAC will automatically marshal variables, data

`PTR` types defined with `DPTR` are the most common in the runtime, but we also have `PTR` types for global and static pointers, restricted-use arrays, pointers to variable-sized objects, and pointers to classes with virtual functions that we may need to call from mscordacwks.dll (msdaccore.dll). Most of these are rare and you can refer to [daccess.h][daccess.h] to learn more about them if you need them.

The `GPTR` and `VPTR` macros are common enough to warrant special mention here. Both the way we use these and their external behavior is quite similar to `DPTR`s. Again, marshaling is automatic and transparent. The `VPTR` macro declares a marshaled pointer type for a class with virtual functions. This special macro is necessary because the virtual function table is essentially an implicit extra field. The DAC has to marshal this separately, since the function addresses are all target addresses that the DAC must convert to host addresses. Treating these classes in this way means that the DAC automatically instantiates the correct implementation class, making casts between base and derived types unnecessary. When you declare a `VPTR` type, you must also list it in [vptr_list.h][vptr_list.h]. `__GlobalPtr` types provide base functionality to marshal both global variables and static data members through the `GPTR`, `GVAL`, `SPTR` and `SVAL` macros. The implementation of global variables is almost identical to that of static fields (both use the `__GlobalPtr` class) and require the addition of an entry in [dacvars.h][dacvars.h]. The comments in [daccess.h][daccess.h] and [dacvars.h][dacvars.h] provide more details about declaring these types.
The `GPTR` and `VPTR` macros are common enough to warrant special mention here. Both the way we use these and their external behavior is quite similar to `DPTR`s. Again, marshaling is automatic and transparent. The `VPTR` macro declares a marshaled pointer type for a class with virtual functions. This special macro is necessary because the virtual function table is essentially an implicit extra field. The DAC has to marshal this separately, since the function addresses are all target addresses that the DAC must convert to host addresses. Treating these classes in this way means that the DAC automatically instantiates the correct implementation class, making casts between base and derived types unnecessary. When you declare a `VPTR` type, you must also list it in [vptr_list.h][vptr_list.h]. `__GlobalPtr` types provide base functionality to marshal both global variables and static data members through the `GPTR`, `GVAL`, `SPTR` and `SVAL` macros. The implementation of global variables is almost identical to that of static fields (both use the `__GlobalPtr` class) and require the addition of an entry in [dacvars.h][dacvars.h]. Global functions used in the DAC do not require macros at the implementation site, but they must be declared in the [gfunc_list.h][gfunc_list.h] header to have their addresses be automatically available to the DAC. The comments in [daccess.h][daccess.h] and [dacvars.h][dacvars.h] provide more details about declaring these types.

[dacvars.h]: https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/dacvars.h
[vptr_list.h]: https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/vptr_list.h
[gfunc_list.h]: https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gfunc_list.h

Global and static values and pointers are interesting because they form the entry points to the target address space (all other uses of the DAC require you to have a target address already). Many of the globals in the runtime are already DACized. It occasionally becomes necessary to make a previously un-DACized (or a newly introduced) global available to the DAC. By using the appropriate macros and [dacvars.h][dacvars.h] entry, you enable a post-build step (DacTableGen.exe run by the build in ndp\clr\src\dacupdatedll) to save the address of the global (from clr.pdb) into a table that is embedded into mscordacwks.dll. The DAC uses this table at run-time to determine where to look in the target address space when the code accesses a global.
Global and static values and pointers are interesting because they form the entry points to the target address space (all other uses of the DAC require you to have a target address already). Many of the globals in the runtime are already DACized. It occasionally becomes necessary to make a previously un-DACized (or a newly introduced) global available to the DAC. By using the appropriate macros and [dacvars.h][dacvars.h] entry, you enable the dac table machinery (in [dactable.cpp]) to save the address of the global into a table that is exported from coreclr.dll. The DAC uses this table at run-time to determine where to look in the target address space when the code accesses a global.

[dactable.cpp]: https://github.com/dotnet/runtime/blob/main/src/coreclr/debug/ee/dactable.cpp

### VAL Types

Expand Down
8 changes: 0 additions & 8 deletions src/coreclr/EmptyProps.props

This file was deleted.

3 changes: 0 additions & 3 deletions src/coreclr/build-runtime.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,6 @@ if not exist "%__IntermediatesDir%" md "%__IntermediatesDir%"
if not exist "%__LogsDir%" md "%__LogsDir%"
if not exist "%__MsbuildDebugLogsDir%" md "%__MsbuildDebugLogsDir%"

if not exist "%__RootBinDir%\Directory.Build.props" copy "%__ProjectDir%\EmptyProps.props" "%__RootBinDir%\Directory.Build.props"
if not exist "%__RootBinDir%\Directory.Build.targets" copy "%__ProjectDir%\EmptyProps.props" "%__RootBinDir%\Directory.Build.targets"

REM Set up the directory for MSBuild debug logs.
set MSBUILDDEBUGPATH=%__MsbuildDebugLogsDir%

Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/debug/createdump/crashinfomac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,9 @@ void CrashInfo::VisitModule(MachOModule& module)
m_runtimeBaseAddress = module.BaseAddress();

uint64_t symbolOffset;
if (!module.TryLookupSymbol("g_dacTable", &symbolOffset))
if (!module.TryLookupSymbol(DACCESS_TABLE_SYMBOL, &symbolOffset))
{
TRACE("TryLookupSymbol(g_dacTable) FAILED\n");
TRACE("TryLookupSymbol(" DACCESS_TABLE_SYMBOL ") FAILED\n");
}
}
else if (g_checkForSingleFile)
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/debug/createdump/crashinfounix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,9 +290,9 @@ CrashInfo::VisitModule(uint64_t baseAddress, std::string& moduleName)
if (PopulateForSymbolLookup(baseAddress))
{
uint64_t symbolOffset;
if (!TryLookupSymbol("g_dacTable", &symbolOffset))
if (!TryLookupSymbol(DACCESS_TABLE_SYMBOL, &symbolOffset))
{
TRACE("TryLookupSymbol(g_dacTable) FAILED\n");
TRACE("TryLookupSymbol(" DACCESS_TABLE_SYMBOL ") FAILED\n");
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/debug/createdump/createdump.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,6 @@ extern bool CreateDump(const char* dumpPathTemplate, int pid, const char* dumpTy

extern void printf_status(const char* format, ...);
extern void printf_error(const char* format, ...);

// Keep in sync with the definitions in dbgutil.cpp and daccess.h
#define DACCESS_TABLE_SYMBOL "g_dacTable"
Loading

0 comments on commit 04e65d2

Please sign in to comment.