diff options
author | Jeremy Koritzinsky <jkoritzinsky@gmail.com> | 2019-03-20 22:59:29 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-20 22:59:29 -0700 |
commit | ea10aaccb09fe30f0444b821fd8d90d9257dd402 (patch) | |
tree | c8ef86fb97af7c49ac8e9f0635c3ac888c1de6a3 /src/vm/ceeload.cpp | |
parent | 42c234f25baf2a6bdd3a429cb8a9530a5dfa54b6 (diff) | |
download | coreclr-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.cpp | 68 |
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; } |