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 a480fe86b576b4..70b31ecadcdb6c 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 @@ -1199,13 +1199,137 @@ public int GetMDStructuresVersion(uint* pMDStructuresVersion) } public int GetActiveRejitILCodeVersionNode(ulong vmModule, uint methodTk, ulong* pVmILCodeVersionNode) - => LegacyFallbackHelper.CanFallback() && _legacy is not null ? _legacy.GetActiveRejitILCodeVersionNode(vmModule, methodTk, pVmILCodeVersionNode) : HResults.E_NOTIMPL; + { + int hr = HResults.S_OK; + try + { + if (pVmILCodeVersionNode is null) + throw new ArgumentException("Output pointer cannot be null.", nameof(pVmILCodeVersionNode)); + + *pVmILCodeVersionNode = 0; + + if (!_target.Contracts.TryGetContract(out IReJIT rejit)) + return hr; + + ILoader loader = _target.Contracts.Loader; + Contracts.ModuleHandle module = loader.GetModuleHandleFromModulePtr(new TargetPointer(vmModule)); + ModuleLookupTables lookupTables = loader.GetLookupTables(module); + TargetPointer methodDesc = TargetPointer.Null; + try + { + if ((EcmaMetadataUtils.TokenType)(methodTk & EcmaMetadataUtils.TokenTypeMask) != EcmaMetadataUtils.TokenType.mdtMethodDef) + throw new ArgumentException("methodTk must be a MethodDef token.", nameof(methodTk)); + methodDesc = loader.GetModuleLookupMapElement(lookupTables.MethodDefToDesc, methodTk, out _); + } + catch (ArgumentOutOfRangeException) + { + // Invalid method token + } + if (methodDesc != TargetPointer.Null) + { + ICodeVersions codeVersions = _target.Contracts.CodeVersions; + ILCodeVersionHandle ilCodeVersion = codeVersions.GetActiveILCodeVersion(methodDesc); + if (ilCodeVersion.IsValid + && ilCodeVersion.IsExplicit + && rejit.GetRejitState(ilCodeVersion) == RejitState.Active) + { + *pVmILCodeVersionNode = ilCodeVersion.ILCodeVersionNode.Value; + } + } + } + catch (System.Exception ex) + { + hr = ex.HResult; + } + +#if DEBUG + if (_legacy is not null) + { + ulong resultLocal; + int hrLocal = _legacy.GetActiveRejitILCodeVersionNode(vmModule, methodTk, &resultLocal); + Debug.ValidateHResult(hr, hrLocal); + if (hr == HResults.S_OK) + Debug.Assert(*pVmILCodeVersionNode == resultLocal, $"cDAC: {*pVmILCodeVersionNode:x}, DAC: {resultLocal:x}"); + } +#endif + + return hr; + } public int GetNativeCodeVersionNode(ulong vmMethod, ulong codeStartAddress, ulong* pVmNativeCodeVersionNode) - => LegacyFallbackHelper.CanFallback() && _legacy is not null ? _legacy.GetNativeCodeVersionNode(vmMethod, codeStartAddress, pVmNativeCodeVersionNode) : HResults.E_NOTIMPL; + { + int hr = HResults.S_OK; + try + { + if (pVmNativeCodeVersionNode is null) + throw new ArgumentException("Output pointer cannot be null.", nameof(pVmNativeCodeVersionNode)); + + *pVmNativeCodeVersionNode = 0; + + TargetCodePointer codeAddress = new TargetCodePointer(codeStartAddress); + ICodeVersions codeVersions = _target.Contracts.CodeVersions; + + NativeCodeVersionHandle nativeCodeVersion = codeVersions.GetNativeCodeVersionForIP(codeAddress); + if (nativeCodeVersion.Valid && nativeCodeVersion.IsExplicit) + { + *pVmNativeCodeVersionNode = nativeCodeVersion.CodeVersionNodeAddress.Value; + } + } + catch (System.Exception ex) + { + hr = ex.HResult; + } + +#if DEBUG + if (_legacy is not null) + { + ulong resultLocal; + int hrLocal = _legacy.GetNativeCodeVersionNode(vmMethod, codeStartAddress, &resultLocal); + Debug.ValidateHResult(hr, hrLocal); + if (hr == HResults.S_OK) + Debug.Assert(*pVmNativeCodeVersionNode == resultLocal, $"cDAC: {*pVmNativeCodeVersionNode:x}, DAC: {resultLocal:x}"); + } +#endif + + return hr; + } public int GetILCodeVersionNode(ulong vmNativeCodeVersionNode, ulong* pVmILCodeVersionNode) - => LegacyFallbackHelper.CanFallback() && _legacy is not null ? _legacy.GetILCodeVersionNode(vmNativeCodeVersionNode, pVmILCodeVersionNode) : HResults.E_NOTIMPL; + { + int hr = HResults.S_OK; + try + { + if (pVmILCodeVersionNode is null) + throw new ArgumentException("Output pointer cannot be null.", nameof(pVmILCodeVersionNode)); + + *pVmILCodeVersionNode = 0; + + ICodeVersions codeVersions = _target.Contracts.CodeVersions; + NativeCodeVersionHandle nativeCodeVersion = NativeCodeVersionHandle.CreateExplicit(new TargetPointer(vmNativeCodeVersionNode)); + ILCodeVersionHandle ilCodeVersion = codeVersions.GetILCodeVersion(nativeCodeVersion); + if (ilCodeVersion.IsValid && ilCodeVersion.IsExplicit) + { + *pVmILCodeVersionNode = ilCodeVersion.ILCodeVersionNode.Value; + } + } + catch (System.Exception ex) + { + hr = ex.HResult; + } + +#if DEBUG + if (_legacy is not null) + { + ulong resultLocal; + int hrLocal = _legacy.GetILCodeVersionNode(vmNativeCodeVersionNode, &resultLocal); + Debug.ValidateHResult(hr, hrLocal); + if (hr == HResults.S_OK) + Debug.Assert(*pVmILCodeVersionNode == resultLocal, $"cDAC: {*pVmILCodeVersionNode:x}, DAC: {resultLocal:x}"); + } +#endif + + return hr; + } public int GetILCodeVersionNodeData(ulong ilCodeVersionNode, DacDbiSharedReJitInfo* pData) => LegacyFallbackHelper.CanFallback() && _legacy is not null ? _legacy.GetILCodeVersionNodeData(ilCodeVersionNode, pData) : HResults.E_NOTIMPL;