summaryrefslogtreecommitdiff
path: root/src/vm/ceeload.cpp
diff options
context:
space:
mode:
authorJeremy Koritzinsky <jkoritzinsky@gmail.com>2019-03-20 22:59:29 -0700
committerGitHub <noreply@github.com>2019-03-20 22:59:29 -0700
commitea10aaccb09fe30f0444b821fd8d90d9257dd402 (patch)
treec8ef86fb97af7c49ac8e9f0635c3ac888c1de6a3 /src/vm/ceeload.cpp
parent42c234f25baf2a6bdd3a429cb8a9530a5dfa54b6 (diff)
downloadcoreclr-ea10aaccb09fe30f0444b821fd8d90d9257dd402.tar.gz
coreclr-ea10aaccb09fe30f0444b821fd8d90d9257dd402.tar.bz2
coreclr-ea10aaccb09fe30f0444b821fd8d90d9257dd402.zip
Runtime changes for IJW Activation (#22636)
* Implement loading an assembly from an HMODULE on Windows. * Use the native runtime to execute the main method so I don't have to replicate all of the startup behavior. * If ijwhost is loaded, then call back into ijwhost to resolve tokens for vtable entries. * Refactor our various component loaders (COM and IJW) and have IJW load components into separate ALCs when loaded from native. * Move VTableFixups after DeliverSyncEvents in our incremental load. We need the module to be loaded to at least FILE_LOAD_DELIVER_EVENTS when resolving dependencies loaded via VTableFixups, otherwise they try to load into the default ALC. * Only try to get ijwhost module handle on Windows. * Use defined() instead of ifndef * Fix off-Windows build break and fix unvalid comment. * ComponentLoadContext->IsolatedComponentLoadContext * Only build InMemoryAssemblyLoader when targeting windows. * Add doc comments for IsolatedComponentLoadContext. * Rename qcall. * Add comment for boolean parameter. * Add null check for managed ExecuteMainMethod entrypoint. * Add comments in ceeload.cpp for the ijwhost method resolution. * Add test verifying runtime callback to IJW host. * Add test for InMemoryAssemblyLoader.LoadInMemoryAssembly. * Fix x86 behavior rel. loading symbols by name and stdcall mangling. * Remove exe entrypoints. The executable case for mixed-mode will go through the normal .NET Core app model (no special hosting support needed). * Clean up whitespace * Add test verifying M->N->M ALC switch behavior with IJW. * Resolve the ijwhost module by probing the PE for the IJW assembly instead of hardcoding the name. * Remove static caching in GetTokenGetterFromHostModule. * Disable new IJW tests on Win7. * PR Feedback. * Cleanup extra copy of function. * Use old-style environment checking in LoadIjwFromModuleHandle since we reference S.P.CL directly. * Fix break in rebase * Clean up fake mscoree code. * Only validate that a CLR header exists. The OS verifies everything else. * Make ijw host resolution code static to ceeload.cpp * Use bracketed include for xplatform.h * Update comment on _CorDllMain * PR feedback. * Remove .def file. * PR feedback. * Verify we export correctly on x86 and x64. * Fix path to ijwhostmock for CopyConstructorMarshaler * Disable IJW tests on arm32 nightly. Can't repro the dependency load failures. Fixes #23358
Diffstat (limited to 'src/vm/ceeload.cpp')
-rw-r--r--src/vm/ceeload.cpp68
1 files changed, 66 insertions, 2 deletions
diff --git a/src/vm/ceeload.cpp b/src/vm/ceeload.cpp
index 1fec2c262d..b9cf4a7900 100644
--- a/src/vm/ceeload.cpp
+++ b/src/vm/ceeload.cpp
@@ -6482,6 +6482,59 @@ void Module::NotifyDebuggerUnload(AppDomain *pDomain)
}
#if !defined(CROSSGEN_COMPILE)
+using GetTokenForVTableEntry_t = mdToken(STDMETHODCALLTYPE*)(HMODULE module, BYTE**ppVTEntry);
+
+static HMODULE GetIJWHostForModule(Module* module)
+{
+#if !defined(FEATURE_PAL)
+ PEDecoder* pe = module->GetFile()->GetLoadedIL();
+
+ BYTE* baseAddress = (BYTE*)module->GetFile()->GetIJWBase();
+
+ IMAGE_IMPORT_DESCRIPTOR* importDescriptor = (IMAGE_IMPORT_DESCRIPTOR*)pe->GetDirectoryData(pe->GetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_IMPORT));
+
+ for(; importDescriptor->Characteristics != 0; importDescriptor++)
+ {
+ IMAGE_THUNK_DATA* importNameTable = (IMAGE_THUNK_DATA*)pe->GetRvaData(importDescriptor->OriginalFirstThunk);
+
+ IMAGE_THUNK_DATA* importAddressTable = (IMAGE_THUNK_DATA*)pe->GetRvaData(importDescriptor->FirstThunk);
+
+ for (int thunkIndex = 0; importNameTable[thunkIndex].u1.AddressOfData != 0; thunkIndex++)
+ {
+ // The most significant bit will be set if the entry points to an ordinal.
+ if ((importNameTable[thunkIndex].u1.Ordinal & (1LL << (sizeof(importNameTable[thunkIndex].u1.Ordinal) * CHAR_BIT - 1))) == 0)
+ {
+ IMAGE_IMPORT_BY_NAME* nameImport = (IMAGE_IMPORT_BY_NAME*)(baseAddress + importNameTable[thunkIndex].u1.AddressOfData);
+ if (strcmp("_CorDllMain", nameImport->Name) == 0)
+ {
+ HMODULE ijwHost;
+
+ if (WszGetModuleHandleEx(
+ GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+ (LPCWSTR)importAddressTable[thunkIndex].u1.Function,
+ &ijwHost))
+ {
+ return ijwHost;
+ }
+
+ }
+ }
+ }
+ }
+#endif
+ return nullptr;
+}
+
+static GetTokenForVTableEntry_t GetTokenGetterFromHostModule(HMODULE ijwHost)
+{
+ if (ijwHost != nullptr)
+ {
+ return (GetTokenForVTableEntry_t)GetProcAddress(ijwHost, "GetTokenForVTableEntry");
+ }
+
+ return nullptr;
+}
+
//=================================================================================
mdToken GetTokenForVTableEntry(HINSTANCE hInst, BYTE **ppVTEntry)
{
@@ -6504,7 +6557,6 @@ void SetTargetForVTableEntry(HINSTANCE hInst, BYTE **ppVTEntry, BYTE *pTarget)
DWORD oldProtect;
if (!ClrVirtualProtect(ppVTEntry, sizeof(BYTE*), PAGE_READWRITE, &oldProtect))
{
-
// This is very bad. We are not going to be able to update header.
_ASSERTE(!"SetTargetForVTableEntry(): VirtualProtect() changing IJW thunk vtable to R/W failed.\n");
ThrowLastError();
@@ -6548,6 +6600,18 @@ void Module::FixupVTables()
return;
}
+ // Try getting a callback to the IJW host if it is loaded.
+ // The IJW host substitutes in special shims in the vtfixup table
+ // so if it is loaded, we need to query it for the tokens that were in the slots.
+ // If it is not loaded, then we know that the vtfixup table entries are tokens,
+ // so we can resolve them ourselves.
+ GetTokenForVTableEntry_t GetTokenForVTableEntryCallback = GetTokenGetterFromHostModule(GetIJWHostForModule(this));
+
+ if (GetTokenForVTableEntryCallback == nullptr)
+ {
+ GetTokenForVTableEntryCallback = GetTokenForVTableEntry;
+ }
+
HINSTANCE hInstThis = GetFile()->GetIJWBase();
// <REVISIT_TODO>@todo: workaround!</REVISIT_TODO>
@@ -6648,7 +6712,7 @@ void Module::FixupVTables()
{
if (pData->IsMethodFixedUp(iFixup, iMethod))
continue;
- mdToken mdTok = GetTokenForVTableEntry(hInstThis, (BYTE **)(pPointers + iMethod));
+ mdToken mdTok = GetTokenForVTableEntryCallback(hInstThis, (BYTE**)(pPointers + iMethod));
CONSISTENCY_CHECK(mdTok != mdTokenNil);
rgMethodsToLoad[iCurMethod++].token = mdTok;
}