diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index a2fe622c8c6eb5..edb8cc84c01baf 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -888,11 +888,11 @@ HRESULT ClrDataAccess::GetThreadData(CLRDATA_ADDRESS threadAddr, struct DacpThre #ifdef FEATURE_EH_FUNCLETS if (thread->m_ExceptionState.m_pCurrentTracker) { - threadData->firstNestedException = PTR_HOST_TO_TADDR( + threadData->firstNestedException = HOST_CDADDR( thread->m_ExceptionState.m_pCurrentTracker->m_pPrevNestedInfo); } #else - threadData->firstNestedException = PTR_HOST_TO_TADDR( + threadData->firstNestedException = HOST_CDADDR( thread->m_ExceptionState.m_currentExInfo.m_pPrevNestedInfo); #endif // FEATURE_EH_FUNCLETS diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/CodePointerUtils.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/CodePointerUtils.cs index b0b5d10f4ac742..49ad041a478440 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/CodePointerUtils.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/CodePointerUtils.cs @@ -13,6 +13,11 @@ internal static class CodePointerUtils internal static TargetCodePointer CodePointerFromAddress(TargetPointer address, Target target) { + if (address == TargetPointer.Null) + { + return TargetCodePointer.Null; + } + IPlatformMetadata metadata = target.Contracts.PlatformMetadata; CodePointerFlags flags = metadata.GetCodePointerFlags(); if (flags.HasFlag(CodePointerFlags.HasArm32ThumbBit)) diff --git a/src/native/managed/cdac/mscordaccore_universal/Legacy/ClrDataStackWalk.cs b/src/native/managed/cdac/mscordaccore_universal/Legacy/ClrDataStackWalk.cs index 8440611106be13..720d445fc3f2d4 100644 --- a/src/native/managed/cdac/mscordaccore_universal/Legacy/ClrDataStackWalk.cs +++ b/src/native/managed/cdac/mscordaccore_universal/Legacy/ClrDataStackWalk.cs @@ -128,7 +128,7 @@ int IXCLRDataStackWalk.Request(uint reqCode, uint inBufferSize, byte* inBuffer, IStackWalk sw = _target.Contracts.StackWalk; IStackDataFrameHandle frameData = _dataFrames.Current; TargetPointer frameAddr = sw.GetFrameAddress(frameData); - *(ulong*)outBuffer = frameAddr.Value; + *(ulong*)outBuffer = frameAddr.ToClrDataAddress(_target); hr = HResults.S_OK; break; default: diff --git a/src/native/managed/cdac/mscordaccore_universal/Legacy/ConversionExtensions.cs b/src/native/managed/cdac/mscordaccore_universal/Legacy/ConversionExtensions.cs index 7ad4114956f309..569c4492d433a9 100644 --- a/src/native/managed/cdac/mscordaccore_universal/Legacy/ConversionExtensions.cs +++ b/src/native/managed/cdac/mscordaccore_universal/Legacy/ConversionExtensions.cs @@ -2,11 +2,15 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics; +using Microsoft.Diagnostics.DataContractReader.Contracts; namespace Microsoft.Diagnostics.DataContractReader.Legacy; internal static class ConversionExtensions { + private const uint Arm32ThumbBit = 1; + /// /// Converts a TargetPointer to a ClrDataAddress using sign extension if required. /// @@ -24,21 +28,62 @@ public static ClrDataAddress ToClrDataAddress(this TargetPointer address, Target /// /// Converts a ClrDataAddress to a TargetPointer, ensuring the address is within the valid range for the target platform. + /// When overrideCheck is true, this will not check the range and will allow any address. This is used on legacy endpoints which + /// may pass in invalid ClrDataAddress values. /// - public static TargetPointer ToTargetPointer(this ClrDataAddress address, Target target) + public static TargetPointer ToTargetPointer(this ClrDataAddress address, Target target, bool overrideCheck = false) { if (target.PointerSize == sizeof(ulong)) { return new TargetPointer(address); } else + { + long signedAddr = (long)address.Value; + if (!overrideCheck && (signedAddr > int.MaxValue || signedAddr < int.MinValue)) + { + throw new ArgumentException($"ClrDataAddress 0x{address.Value:x} out of range for the target platform.", nameof(address)); + } + return new TargetPointer((uint)address); + } + } + + /// + /// Converts a ClrDataAddress to a TargetCodePointer, ensuring the address is within the valid range for the target platform. + /// + public static TargetCodePointer ToTargetCodePointer(this ClrDataAddress address, Target target) + { + if (target.PointerSize == sizeof(ulong)) + { + return new TargetCodePointer(address); + } + else { long signedAddr = (long)address.Value; if (signedAddr > int.MaxValue || signedAddr < int.MinValue) { - throw new ArgumentException(nameof(address), "ClrDataAddress out of range for the target platform."); + throw new ArgumentException($"ClrDataAddress 0x{address.Value:x} out of range for the target platform.", nameof(address)); } - return new TargetPointer((ulong)address); + return new TargetCodePointer((uint)address); + } + } + + /// + /// Converts a TargetCodePointer to an address TargetPointer, removing any platform-specific bits such as the ARM32 Thumb bit or ARM64 pointer authentication. + /// + internal static TargetPointer ToAddress(this TargetCodePointer code, Target target) + { + IPlatformMetadata metadata = target.Contracts.PlatformMetadata; + CodePointerFlags flags = metadata.GetCodePointerFlags(); + if (flags.HasFlag(CodePointerFlags.HasArm32ThumbBit)) + { + return new TargetPointer(code.Value & ~Arm32ThumbBit); + } + else if (flags.HasFlag(CodePointerFlags.HasArm64PtrAuth)) + { + throw new NotImplementedException($"{nameof(ToAddress)}: ARM64 with pointer authentication"); } + Debug.Assert(flags == default); + return new TargetPointer(code.Value); } } diff --git a/src/native/managed/cdac/mscordaccore_universal/Legacy/SOSDacImpl.cs b/src/native/managed/cdac/mscordaccore_universal/Legacy/SOSDacImpl.cs index 54d1e2c87949eb..f56cab86548497 100644 --- a/src/native/managed/cdac/mscordaccore_universal/Legacy/SOSDacImpl.cs +++ b/src/native/managed/cdac/mscordaccore_universal/Legacy/SOSDacImpl.cs @@ -438,7 +438,7 @@ int ISOSDacInterface.GetMethodDescData(ClrDataAddress addr, ClrDataAddress ip, D NativeCodeVersionHandle? activeNativeCodeVersion = null; if (ip != 0) { - requestedNativeCodeVersion = nativeCodeContract.GetNativeCodeVersionForIP(new TargetCodePointer(ip)); + requestedNativeCodeVersion = nativeCodeContract.GetNativeCodeVersionForIP(ip.ToTargetCodePointer(_target)); } else { @@ -457,7 +457,7 @@ int ISOSDacInterface.GetMethodDescData(ClrDataAddress addr, ClrDataAddress ip, D if (nativeCodeAddr != TargetCodePointer.Null) { data->bHasNativeCode = 1; - data->NativeCodeAddr = nativeCodeAddr.AsTargetPointer.ToClrDataAddress(_target); + data->NativeCodeAddr = nativeCodeAddr.ToAddress(_target).ToClrDataAddress(_target); } else { @@ -615,41 +615,41 @@ int ISOSDacInterface.GetMethodDescData(ClrDataAddress addr, ClrDataAddress ip, D Debug.Assert(hrLocal == hr, $"cDAC: {hr:x}, DAC: {hrLocal:x}"); if (hr == HResults.S_OK) { - Debug.Assert(data->bHasNativeCode == dataLocal.bHasNativeCode); - Debug.Assert(data->bIsDynamic == dataLocal.bIsDynamic); - Debug.Assert(data->wSlotNumber == dataLocal.wSlotNumber); - Debug.Assert(data->NativeCodeAddr == dataLocal.NativeCodeAddr); - Debug.Assert(data->AddressOfNativeCodeSlot == dataLocal.AddressOfNativeCodeSlot); - Debug.Assert(data->MethodDescPtr == dataLocal.MethodDescPtr); - Debug.Assert(data->MethodTablePtr == dataLocal.MethodTablePtr); - Debug.Assert(data->ModulePtr == dataLocal.ModulePtr); - Debug.Assert(data->MDToken == dataLocal.MDToken); - Debug.Assert(data->GCInfo == dataLocal.GCInfo); - Debug.Assert(data->GCStressCodeCopy == dataLocal.GCStressCodeCopy); + Debug.Assert(data->bHasNativeCode == dataLocal.bHasNativeCode, $"cDAC: {data->bHasNativeCode}, DAC: {dataLocal.bHasNativeCode}"); + Debug.Assert(data->bIsDynamic == dataLocal.bIsDynamic, $"cDAC: {data->bIsDynamic}, DAC: {dataLocal.bIsDynamic}"); + Debug.Assert(data->wSlotNumber == dataLocal.wSlotNumber, $"cDAC: {data->wSlotNumber}, DAC: {dataLocal.wSlotNumber}"); + Debug.Assert(data->NativeCodeAddr == dataLocal.NativeCodeAddr, $"cDAC: {data->NativeCodeAddr:x}, DAC: {dataLocal.NativeCodeAddr:x}"); + Debug.Assert(data->AddressOfNativeCodeSlot == dataLocal.AddressOfNativeCodeSlot, $"cDAC: {data->AddressOfNativeCodeSlot:x}, DAC: {dataLocal.AddressOfNativeCodeSlot:x}"); + Debug.Assert(data->MethodDescPtr == dataLocal.MethodDescPtr, $"cDAC: {data->MethodDescPtr:x}, DAC: {dataLocal.MethodDescPtr:x}"); + Debug.Assert(data->MethodTablePtr == dataLocal.MethodTablePtr, $"cDAC: {data->MethodTablePtr:x}, DAC: {dataLocal.MethodTablePtr:x}"); + Debug.Assert(data->ModulePtr == dataLocal.ModulePtr, $"cDAC: {data->ModulePtr:x}, DAC: {dataLocal.ModulePtr:x}"); + Debug.Assert(data->MDToken == dataLocal.MDToken, $"cDAC: {data->MDToken:x}, DAC: {dataLocal.MDToken:x}"); + Debug.Assert(data->GCInfo == dataLocal.GCInfo, $"cDAC: {data->GCInfo:x}, DAC: {dataLocal.GCInfo:x}"); + Debug.Assert(data->GCStressCodeCopy == dataLocal.GCStressCodeCopy, $"cDAC: {data->GCStressCodeCopy:x}, DAC: {dataLocal.GCStressCodeCopy:x}"); // managedDynamicMethodObject is not currently populated by the cDAC API and may differ from legacyImpl. Debug.Assert(data->managedDynamicMethodObject == 0); - Debug.Assert(data->requestedIP == dataLocal.requestedIP); - Debug.Assert(data->cJittedRejitVersions == dataLocal.cJittedRejitVersions); + Debug.Assert(data->requestedIP == dataLocal.requestedIP, $"cDAC: {data->requestedIP:x}, DAC: {dataLocal.requestedIP:x}"); + Debug.Assert(data->cJittedRejitVersions == dataLocal.cJittedRejitVersions, $"cDAC: {data->cJittedRejitVersions}, DAC: {dataLocal.cJittedRejitVersions}"); // rejitDataCurrent - Debug.Assert(data->rejitDataCurrent.rejitID == dataLocal.rejitDataCurrent.rejitID); - Debug.Assert(data->rejitDataCurrent.NativeCodeAddr == dataLocal.rejitDataCurrent.NativeCodeAddr); - Debug.Assert(data->rejitDataCurrent.flags == dataLocal.rejitDataCurrent.flags); + Debug.Assert(data->rejitDataCurrent.rejitID == dataLocal.rejitDataCurrent.rejitID, $"cDAC: {data->rejitDataCurrent.rejitID}, DAC: {dataLocal.rejitDataCurrent.rejitID}"); + Debug.Assert(data->rejitDataCurrent.NativeCodeAddr == dataLocal.rejitDataCurrent.NativeCodeAddr, $"cDAC: {data->rejitDataCurrent.NativeCodeAddr:x}, DAC: {dataLocal.rejitDataCurrent.NativeCodeAddr:x}"); + Debug.Assert(data->rejitDataCurrent.flags == dataLocal.rejitDataCurrent.flags, $"cDAC: {data->rejitDataCurrent.flags}, DAC: {dataLocal.rejitDataCurrent.flags}"); // rejitDataRequested - Debug.Assert(data->rejitDataRequested.rejitID == dataLocal.rejitDataRequested.rejitID); - Debug.Assert(data->rejitDataRequested.NativeCodeAddr == dataLocal.rejitDataRequested.NativeCodeAddr); - Debug.Assert(data->rejitDataRequested.flags == dataLocal.rejitDataRequested.flags); + Debug.Assert(data->rejitDataRequested.rejitID == dataLocal.rejitDataRequested.rejitID, $"cDAC: {data->rejitDataRequested.rejitID}, DAC: {dataLocal.rejitDataRequested.rejitID}"); + Debug.Assert(data->rejitDataRequested.NativeCodeAddr == dataLocal.rejitDataRequested.NativeCodeAddr, $"cDAC: {data->rejitDataRequested.NativeCodeAddr:x}, DAC: {dataLocal.rejitDataRequested.NativeCodeAddr:x}"); + Debug.Assert(data->rejitDataRequested.flags == dataLocal.rejitDataRequested.flags, $"cDAC: {data->rejitDataRequested.flags}, DAC: {dataLocal.rejitDataRequested.flags}"); // rgRevertedRejitData if (rgRevertedRejitData != null && rgRevertedRejitDataLocal != null) { - Debug.Assert(cNeededRevertedRejitDataLocal == *pcNeededRevertedRejitData); + Debug.Assert(cNeededRevertedRejitDataLocal == *pcNeededRevertedRejitData, $"cDAC: {*pcNeededRevertedRejitData}, DAC: {cNeededRevertedRejitDataLocal}"); for (ulong i = 0; i < cNeededRevertedRejitDataLocal; i++) { - Debug.Assert(rgRevertedRejitData[i].rejitID == rgRevertedRejitDataLocal[i].rejitID); - Debug.Assert(rgRevertedRejitData[i].NativeCodeAddr == rgRevertedRejitDataLocal[i].NativeCodeAddr); - Debug.Assert(rgRevertedRejitData[i].flags == rgRevertedRejitDataLocal[i].flags); + Debug.Assert(rgRevertedRejitData[i].rejitID == rgRevertedRejitDataLocal[i].rejitID, $"cDAC: {rgRevertedRejitData[i].rejitID}, DAC: {rgRevertedRejitDataLocal[i].rejitID}"); + Debug.Assert(rgRevertedRejitData[i].NativeCodeAddr == rgRevertedRejitDataLocal[i].NativeCodeAddr, $"cDAC: {rgRevertedRejitData[i].NativeCodeAddr:x}, DAC: {rgRevertedRejitDataLocal[i].NativeCodeAddr:x}"); + Debug.Assert(rgRevertedRejitData[i].flags == rgRevertedRejitDataLocal[i].flags, $"cDAC: {rgRevertedRejitData[i].flags}, DAC: {rgRevertedRejitDataLocal[i].flags}"); } } } @@ -803,7 +803,7 @@ int ISOSDacInterface.GetMethodDescPtrFromIP(ClrDataAddress ip, ClrDataAddress* p IExecutionManager executionManager = _target.Contracts.ExecutionManager; IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; - CodeBlockHandle? handle = executionManager.GetCodeBlockHandle(new TargetCodePointer(ip)); + CodeBlockHandle? handle = executionManager.GetCodeBlockHandle(ip.ToTargetCodePointer(_target)); if (handle is CodeBlockHandle codeHandle) { TargetPointer methodDescAddr = executionManager.GetMethodDesc(codeHandle); @@ -814,7 +814,7 @@ int ISOSDacInterface.GetMethodDescPtrFromIP(ClrDataAddress ip, ClrDataAddress* p // if validation fails, should return E_INVALIDARG rts.GetMethodDescHandle(methodDescAddr); - *ppMD = methodDescAddr.Value; + *ppMD = methodDescAddr.ToClrDataAddress(_target); hr = HResults.S_OK; } catch (System.Exception) @@ -963,7 +963,7 @@ int ISOSDacInterface.GetMethodTableName(ClrDataAddress mt, uint count, char* mtN try { Contracts.IRuntimeTypeSystem typeSystemContract = _target.Contracts.RuntimeTypeSystem; - Contracts.TypeHandle methodTableHandle = typeSystemContract.GetTypeHandle(mt.ToTargetPointer(_target)); + Contracts.TypeHandle methodTableHandle = typeSystemContract.GetTypeHandle(mt.ToTargetPointer(_target, overrideCheck: true)); if (typeSystemContract.IsFreeObjectMethodTable(methodTableHandle)) { OutputBufferHelpers.CopyStringToBuffer(mtName, count, pNeeded, "Free"); @@ -1511,21 +1511,21 @@ int ISOSDacInterface.GetThreadData(ClrDataAddress thread, DacpThreadData* data) Debug.Assert(hrLocal == hr, $"cDAC: {hr:x}, DAC: {hrLocal:x}"); if (hr == HResults.S_OK) { - Debug.Assert(data->corThreadId == dataLocal.corThreadId); - Debug.Assert(data->osThreadId == dataLocal.osThreadId); - Debug.Assert(data->state == dataLocal.state); - Debug.Assert(data->preemptiveGCDisabled == dataLocal.preemptiveGCDisabled); - Debug.Assert(data->allocContextPtr == dataLocal.allocContextPtr); - Debug.Assert(data->allocContextLimit == dataLocal.allocContextLimit); - Debug.Assert(data->fiberData == dataLocal.fiberData); - Debug.Assert(data->context == dataLocal.context); - Debug.Assert(data->domain == dataLocal.domain); - Debug.Assert(data->lockCount == dataLocal.lockCount); - Debug.Assert(data->pFrame == dataLocal.pFrame); - Debug.Assert(data->firstNestedException == dataLocal.firstNestedException); - Debug.Assert(data->teb == dataLocal.teb); - Debug.Assert(data->lastThrownObjectHandle == dataLocal.lastThrownObjectHandle); - Debug.Assert(data->nextThread == dataLocal.nextThread); + Debug.Assert(data->corThreadId == dataLocal.corThreadId, $"cDAC: {data->corThreadId}, DAC: {dataLocal.corThreadId}"); + Debug.Assert(data->osThreadId == dataLocal.osThreadId, $"cDAC: {data->osThreadId}, DAC: {dataLocal.osThreadId}"); + Debug.Assert(data->state == dataLocal.state, $"cDAC: {data->state}, DAC: {dataLocal.state}"); + Debug.Assert(data->preemptiveGCDisabled == dataLocal.preemptiveGCDisabled, $"cDAC: {data->preemptiveGCDisabled}, DAC: {dataLocal.preemptiveGCDisabled}"); + Debug.Assert(data->allocContextPtr == dataLocal.allocContextPtr, $"cDAC: {data->allocContextPtr:x}, DAC: {dataLocal.allocContextPtr:x}"); + Debug.Assert(data->allocContextLimit == dataLocal.allocContextLimit, $"cDAC: {data->allocContextLimit:x}, DAC: {dataLocal.allocContextLimit:x}"); + Debug.Assert(data->fiberData == dataLocal.fiberData, $"cDAC: {data->fiberData:x}, DAC: {dataLocal.fiberData:x}"); + Debug.Assert(data->context == dataLocal.context, $"cDAC: {data->context:x}, DAC: {dataLocal.context:x}"); + Debug.Assert(data->domain == dataLocal.domain, $"cDAC: {data->domain:x}, DAC: {dataLocal.domain:x}"); + Debug.Assert(data->lockCount == dataLocal.lockCount, $"cDAC: {data->lockCount}, DAC: {dataLocal.lockCount}"); + Debug.Assert(data->pFrame == dataLocal.pFrame, $"cDAC: {data->pFrame:x}, DAC: {dataLocal.pFrame:x}"); + Debug.Assert(data->firstNestedException == dataLocal.firstNestedException, $"cDAC: {data->firstNestedException:x}, DAC: {dataLocal.firstNestedException:x}"); + Debug.Assert(data->teb == dataLocal.teb, $"cDAC: {data->teb:x}, DAC: {dataLocal.teb:x}"); + Debug.Assert(data->lastThrownObjectHandle == dataLocal.lastThrownObjectHandle, $"cDAC: {data->lastThrownObjectHandle:x}, DAC: {dataLocal.lastThrownObjectHandle:x}"); + Debug.Assert(data->nextThread == dataLocal.nextThread, $"cDAC: {data->nextThread:x}, DAC: {dataLocal.nextThread:x}"); } } #endif diff --git a/src/native/managed/compile-native.proj b/src/native/managed/compile-native.proj index ccdcbd57f31a3d..737593267ed65f 100644 --- a/src/native/managed/compile-native.proj +++ b/src/native/managed/compile-native.proj @@ -23,7 +23,7 @@ false false - false + false true false