diff --git a/src/coreclr/inc/utilcode.h b/src/coreclr/inc/utilcode.h index 8896e10932f7ae..3040798a9b99c8 100644 --- a/src/coreclr/inc/utilcode.h +++ b/src/coreclr/inc/utilcode.h @@ -2788,6 +2788,8 @@ typedef VPTR(class RangeList) PTR_RangeList; class RangeList { + friend struct ::cdac_data; + public: VPTR_BASE_CONCRETE_VTABLE_CLASS(RangeList) @@ -2896,6 +2898,27 @@ class RangeList TADDR m_firstEmptyRange; }; +template<> +struct cdac_data +{ + static constexpr size_t StarterBlock = offsetof(RangeList, m_starterBlock); + + struct RangeListBlock + { + static constexpr size_t Ranges = offsetof(RangeList::RangeListBlock, ranges); + static constexpr size_t Next = offsetof(RangeList::RangeListBlock, next); + static constexpr size_t Size = sizeof(RangeList::RangeListBlock); + }; + + struct Range + { + static constexpr size_t Start = offsetof(RangeList::Range, start); + static constexpr size_t End = offsetof(RangeList::Range, end); + static constexpr size_t Id = offsetof(RangeList::Range, id); + static constexpr size_t Size = sizeof(RangeList::Range); + }; +}; + // // A private function to do the equavilent of a CoCreateInstance in diff --git a/src/coreclr/vm/datadescriptor/datadescriptor.inc b/src/coreclr/vm/datadescriptor/datadescriptor.inc index 6242f9f49da888..f0c27af76237c3 100644 --- a/src/coreclr/vm/datadescriptor/datadescriptor.inc +++ b/src/coreclr/vm/datadescriptor/datadescriptor.inc @@ -1045,6 +1045,29 @@ CDAC_TYPE_INDETERMINATE(CodeRangeMapRangeList) CDAC_TYPE_FIELD(CodeRangeMapRangeList, T_INT32, RangeListType, cdac_data::RangeListType) CDAC_TYPE_END(CodeRangeMapRangeList) +CDAC_TYPE_BEGIN(StubLinkStubManager) +CDAC_TYPE_INDETERMINATE(StubLinkStubManager) +CDAC_TYPE_FIELD(StubLinkStubManager, TYPE(RangeList), RangeList, cdac_data::RangeList) +CDAC_TYPE_END(StubLinkStubManager) + +CDAC_TYPE_BEGIN(RangeList) +CDAC_TYPE_INDETERMINATE(RangeList) +CDAC_TYPE_FIELD(RangeList, TYPE(RangeListBlock), StarterBlock, cdac_data::StarterBlock) +CDAC_TYPE_END(RangeList) + +CDAC_TYPE_BEGIN(RangeListBlock) +CDAC_TYPE_SIZE(cdac_data::RangeListBlock::Size) +CDAC_TYPE_FIELD(RangeListBlock, T_ARRAY(TYPE(RangeListRange)), Ranges, cdac_data::RangeListBlock::Ranges) +CDAC_TYPE_FIELD(RangeListBlock, T_POINTER, Next, cdac_data::RangeListBlock::Next) +CDAC_TYPE_END(RangeListBlock) + +CDAC_TYPE_BEGIN(RangeListRange) +CDAC_TYPE_SIZE(cdac_data::Range::Size) +CDAC_TYPE_FIELD(RangeListRange, T_POINTER, Start, cdac_data::Range::Start) +CDAC_TYPE_FIELD(RangeListRange, T_POINTER, End, cdac_data::Range::End) +CDAC_TYPE_FIELD(RangeListRange, T_POINTER, Id, cdac_data::Range::Id) +CDAC_TYPE_END(RangeListRange) + CDAC_TYPE_BEGIN(EEJitManager) CDAC_TYPE_INDETERMINATE(EEJitManager) CDAC_TYPE_FIELD(EEJitManager, T_BOOL, StoreRichDebugInfo, cdac_data::StoreRichDebugInfo) @@ -1797,6 +1820,8 @@ CDAC_GLOBAL(StressLogEnabled, T_UINT8, 0) #endif CDAC_GLOBAL_POINTER(ExecutionManagerCodeRangeMapAddress, cdac_data::CodeRangeMapAddress) CDAC_GLOBAL_POINTER(EEJitManagerAddress, cdac_data::EEJitManagerAddress) +CDAC_GLOBAL(RangeListRangeCount, T_UINT32, RangeList::RANGE_COUNT) +CDAC_GLOBAL_POINTER(StubLinkStubManagerAddress, &StubLinkStubManager::g_pManager) #ifdef TARGET_WASM CDAC_GLOBAL_POINTER(FunctionTableIndexRangeList, cdac_data::FunctionTableIndexRangeListAddress) #endif // TARGET_WASM diff --git a/src/coreclr/vm/stubmgr.cpp b/src/coreclr/vm/stubmgr.cpp index 258fb74f509658..21841b20419164 100644 --- a/src/coreclr/vm/stubmgr.cpp +++ b/src/coreclr/vm/stubmgr.cpp @@ -1435,6 +1435,9 @@ BOOL RangeSectionStubManager::CheckIsStub_Internal(PCODE stubStartAddress) switch (GetStubKind(stubStartAddress)) { +#ifdef DACCESS_COMPILE + case STUB_CODE_BLOCK_DYNAMICHELPER: +#endif // DACCESS_COMPILE case STUB_CODE_BLOCK_JUMPSTUB: case STUB_CODE_BLOCK_METHOD_CALL_THUNK: #ifdef FEATURE_TIERED_COMPILATION @@ -1514,6 +1517,8 @@ LPCWSTR RangeSectionStubManager::GetStubManagerName(PCODE addr) switch (GetStubKind(addr)) { + case STUB_CODE_BLOCK_DYNAMICHELPER: + return W("DynamicHelper"); case STUB_CODE_BLOCK_JUMPSTUB: return W("JumpStub"); case STUB_CODE_BLOCK_METHOD_CALL_THUNK: diff --git a/src/coreclr/vm/stubmgr.h b/src/coreclr/vm/stubmgr.h index da04e1f11dbe63..37aab612ee3aad 100644 --- a/src/coreclr/vm/stubmgr.h +++ b/src/coreclr/vm/stubmgr.h @@ -451,6 +451,8 @@ typedef VPTR(class StubLinkStubManager) PTR_StubLinkStubManager; class StubLinkStubManager : public StubManager { + friend struct ::cdac_data; + VPTR_VTABLE_CLASS(StubLinkStubManager, StubManager) public: @@ -504,6 +506,12 @@ class StubLinkStubManager : public StubManager #endif } ; +template<> +struct cdac_data +{ + static constexpr size_t RangeList = offsetof(StubLinkStubManager, m_rangeList); +}; + // // Stub manager for code sections. It forwards the query to the more appropriate // stub manager, or handles the query itself. diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IExecutionManager.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IExecutionManager.cs index ef0a13cbce4d7b..c5f292195fe2e0 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IExecutionManager.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IExecutionManager.cs @@ -58,7 +58,8 @@ public enum CodeKind : uint Jitted = 11, ReadyToRun = 12, Interpreter = 13, - ThePreStub = 14 + ThePreStub = 14, + StubLinkStub = 15 } public interface ICodeHeapInfo diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Constants.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Constants.cs index afce81bbf1c224..28d39e13fe9217 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Constants.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Constants.cs @@ -13,6 +13,8 @@ public static class Globals public const string ThreadStore = nameof(ThreadStore); public const string FinalizerThread = nameof(FinalizerThread); public const string FunctionTableIndexRangeList = nameof(FunctionTableIndexRangeList); + public const string RangeListRangeCount = nameof(RangeListRangeCount); + public const string StubLinkStubManagerAddress = nameof(StubLinkStubManagerAddress); public const string GCThread = nameof(GCThread); public const string Debugger = nameof(Debugger); public const string MaxHijackFunctions = nameof(MaxHijackFunctions); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.cs index 8c8f933f948e62..3a77c6121e6d1d 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/ExecutionManager/ExecutionManagerCore.cs @@ -23,6 +23,7 @@ internal sealed partial class ExecutionManagerCore : IExecutionManager private readonly ReadyToRunJitManager _r2rJitManager; private readonly InterpreterJitManager _interpreterJitManager; private readonly TargetPointer _thePreStub; + private readonly TargetPointer _stubLinkStubRangeList; private Data.RangeSectionMap _topRangeSectionMap => _target.ProcessedData.GetOrAdd(_topRangeSectionMapAddress); @@ -39,6 +40,15 @@ public ExecutionManagerCore(Target target, TargetPointer topRangeSectionMapAddre _thePreStub = _target.TryReadGlobalPointer(Constants.Globals.ThePreStub, out TargetPointer? thePreStubPtr) ? _target.ReadPointer(thePreStubPtr.Value) : TargetPointer.Null; + if (_target.TryReadGlobalPointer(Constants.Globals.StubLinkStubManagerAddress, out TargetPointer? stubLinkStubManagerPtr)) + { + TargetPointer stubLinkStubManagerAddress = _target.ReadPointer(stubLinkStubManagerPtr.Value); + if (stubLinkStubManagerAddress != TargetPointer.Null) + { + Data.StubLinkStubManager stubLinkStubManager = _target.ProcessedData.GetOrAdd(stubLinkStubManagerAddress); + _stubLinkStubRangeList = stubLinkStubManager.RangeList; + } + } } public void Flush(FlushScope scope) @@ -673,6 +683,9 @@ public CodeKind GetCodeKind(TargetCodePointer codeAddress) if (address == _thePreStub && _thePreStub != TargetPointer.Null) return CodeKind.ThePreStub; + if (IsStubLinkStub(address)) + return CodeKind.StubLinkStub; + return CodeKind.Unknown; } @@ -685,4 +698,19 @@ public CodeKind GetCodeKind(TargetCodePointer codeAddress) } return jitManager.GetCodeKind(range, codeAddress); } + + private bool IsStubLinkStub(TargetPointer address) + { + if (_stubLinkStubRangeList == TargetPointer.Null) + return false; + + Data.RangeList rangeList = _target.ProcessedData.GetOrAdd(_stubLinkStubRangeList); + foreach (Data.RangeListRange range in rangeList.Ranges) + { + if (range.Id != TargetPointer.Null && address >= range.Start && address < range.End) + return true; + } + + return false; + } } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/RangeList.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/RangeList.cs new file mode 100644 index 00000000000000..b9447f1e8c3118 --- /dev/null +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/RangeList.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.Diagnostics.DataContractReader.Data; + +[CdacType(nameof(DataType.RangeList))] +internal sealed partial class RangeList : IData +{ + [FieldAddress] + public partial TargetPointer StarterBlock { get; } + + public IReadOnlyList Blocks { get; private set; } = []; + public IReadOnlyList Ranges { get; private set; } = []; + + [MemberNotNull(nameof(Blocks), nameof(Ranges))] + partial void OnInit(Target target, TargetPointer address) + { + List blocks = []; + List ranges = []; + uint rangeCount = target.ReadGlobal(Constants.Globals.RangeListRangeCount); + uint rangeSize = target.GetTypeInfo(DataType.RangeListRange).Size!.Value; + TargetPointer blockAddress = StarterBlock; + + while (blockAddress != TargetPointer.Null) + { + RangeListBlock block = target.ProcessedData.GetOrAdd(blockAddress); + blocks.Add(block); + + for (uint i = 0; i < rangeCount; i++) + { + TargetPointer rangeAddress = block.Ranges + (i * rangeSize); + ranges.Add(target.ProcessedData.GetOrAdd(rangeAddress)); + } + + blockAddress = block.Next; + } + + Blocks = blocks; + Ranges = ranges; + } +} diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/RangeListBlock.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/RangeListBlock.cs new file mode 100644 index 00000000000000..bbb4f1815c742e --- /dev/null +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/RangeListBlock.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Diagnostics.DataContractReader.Data; + +[CdacType(nameof(DataType.RangeListBlock))] +internal sealed partial class RangeListBlock : IData +{ + [FieldAddress] + public partial TargetPointer Ranges { get; } + + [Field] + public partial TargetPointer Next { get; } +} diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/RangeListRange.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/RangeListRange.cs new file mode 100644 index 00000000000000..458f204301ba6e --- /dev/null +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/RangeListRange.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Diagnostics.DataContractReader.Data; + +[CdacType(nameof(DataType.RangeListRange))] +internal sealed partial class RangeListRange : IData +{ + [Field] public partial TargetPointer Start { get; } + [Field] public partial TargetPointer End { get; } + [Field] public partial TargetPointer Id { get; } +} diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/StubLinkStubManager.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/StubLinkStubManager.cs new file mode 100644 index 00000000000000..cf689c0cca615a --- /dev/null +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/StubLinkStubManager.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Diagnostics.DataContractReader.Data; + +[CdacType(nameof(DataType.StubLinkStubManager))] +internal sealed partial class StubLinkStubManager : IData +{ + [FieldAddress] + public partial TargetPointer RangeList { get; } +} diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/DataType.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/DataType.cs index be5194e0a537a6..2eae4005921357 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/DataType.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/DataType.cs @@ -204,6 +204,10 @@ public enum DataType VASigCookie, Signature, CodeRangeMapRangeList, + StubLinkStubManager, + RangeList, + RangeListBlock, + RangeListRange, /* GC Data Types */ diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs index 019bbe5f9083ee..b769b8671abcdc 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs @@ -341,6 +341,7 @@ int IXCLRDataProcess.GetRuntimeNameByAddress( if (codeKind is Contracts.CodeKind.Unknown or Contracts.CodeKind.Jitted or Contracts.CodeKind.ReadyToRun + or Contracts.CodeKind.Interpreter or Contracts.CodeKind.ThePreStub) { return null;