diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs index ce360d3f7a6e48..54ae8e8d815648 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs @@ -283,7 +283,32 @@ public int GetAssemblyInfo(ulong vmAssembly, DacDbiAssemblyInfo* pData) => LegacyFallbackHelper.CanFallback() && _legacy is not null ? _legacy.GetAssemblyInfo(vmAssembly, pData) : HResults.E_NOTIMPL; public int GetModuleForAssembly(ulong vmAssembly, ulong* pModule) - => LegacyFallbackHelper.CanFallback() && _legacy is not null ? _legacy.GetModuleForAssembly(vmAssembly, pModule) : HResults.E_NOTIMPL; + { + *pModule = 0; + int hr = HResults.S_OK; + try + { + Contracts.ILoader loader = _target.Contracts.Loader; + Contracts.ModuleHandle handle = loader.GetModuleHandleFromAssemblyPtr(new TargetPointer(vmAssembly)); + TargetPointer modulePtr = loader.GetModule(handle); + *pModule = modulePtr.Value; + } + catch (System.Exception ex) + { + hr = ex.HResult; + } +#if DEBUG + if (_legacy is not null) + { + ulong moduleLocal; + int hrLocal = _legacy.GetModuleForAssembly(vmAssembly, &moduleLocal); + Debug.ValidateHResult(hr, hrLocal); + if (hr == HResults.S_OK) + Debug.Assert(*pModule == moduleLocal, $"cDAC: {*pModule:x}, DAC: {moduleLocal:x}"); + } +#endif + return hr; + } public int GetAddressType(ulong address, int* pRetVal) => LegacyFallbackHelper.CanFallback() && _legacy is not null ? _legacy.GetAddressType(address, pRetVal) : HResults.E_NOTIMPL; diff --git a/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiLoaderDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiLoaderDumpTests.cs index 5b8937bd8c66a4..d7a776ff19fc5f 100644 --- a/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiLoaderDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiLoaderDumpTests.cs @@ -44,6 +44,43 @@ public void GetAppDomainFullName_ReturnsNonEmpty(TestConfiguration config) Assert.False(string.IsNullOrEmpty(holder.Value), "AppDomain name should not be empty"); } + [ConditionalTheory] + [MemberData(nameof(TestConfigurations))] + public unsafe void GetModuleForAssembly_ReturnsExpectedModule(TestConfiguration config) + { + InitializeDumpTest(config); + DacDbiImpl dbi = CreateDacDbi(); + ILoader loader = Target.Contracts.Loader; + + bool testedAtLeastOne = false; + foreach (ModuleHandle module in GetAllModules()) + { + TargetPointer assemblyPtr = loader.GetAssembly(module); + TargetPointer expectedModulePtr = loader.GetModule(module); + + ulong resultModule; + int hr = dbi.GetModuleForAssembly(assemblyPtr.Value, &resultModule); + Assert.Equal(System.HResults.S_OK, hr); + Assert.NotEqual(0UL, resultModule); + Assert.Equal(expectedModulePtr.Value, resultModule); + testedAtLeastOne = true; + } + Assert.True(testedAtLeastOne, "Expected at least one module in the dump"); + } + + [ConditionalTheory] + [MemberData(nameof(TestConfigurations))] + public unsafe void GetModuleForAssembly_InvalidAssembly(TestConfiguration config) + { + InitializeDumpTest(config); + DacDbiImpl dbi = CreateDacDbi(); + + ulong resultModule = ulong.MaxValue; + int hr = dbi.GetModuleForAssembly(0, &resultModule); + Assert.NotEqual(System.HResults.S_OK, hr); + Assert.Equal(0UL, resultModule); + } + [ConditionalTheory] [MemberData(nameof(TestConfigurations))] public unsafe void GetTypeHandle_ReturnsMethodTableForTypeDef(TestConfiguration config)