| File: Contracts\ExecutionManager\Helpers\RuntimeFunctionLookup.cs | Web Access |
| Project: src\runtime\src\native\managed\cdac\Microsoft.Diagnostics.DataContractReader.Contracts\Microsoft.Diagnostics.DataContractReader.Contracts.csproj (Microsoft.Diagnostics.DataContractReader.Contracts) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; namespace Microsoft.Diagnostics.DataContractReader.ExecutionManagerHelpers; internal sealed class RuntimeFunctionLookup { public static RuntimeFunctionLookup Create(Target target) => new RuntimeFunctionLookup(target); private readonly uint _runtimeFunctionSize; private readonly Target _target; private RuntimeFunctionLookup(Target target) { _target = target; _runtimeFunctionSize = target.GetTypeInfo(DataType.RuntimeFunction).Size!.Value; } public uint GetFunctionLength(TargetPointer imageBase, Data.RuntimeFunction function) { if (function.EndAddress.HasValue) return function.EndAddress.Value - function.BeginAddress; Data.UnwindInfo unwindInfo = _target.ProcessedData.GetOrAdd<Data.UnwindInfo>(imageBase + function.UnwindData); if (unwindInfo.FunctionLength.HasValue) return unwindInfo.FunctionLength.Value; Debug.Assert(unwindInfo.Header.HasValue); // First 18 bits are function length / (pointer size / 2). // See UnwindFragmentInfo::Finalize uint funcLengthInHeader = unwindInfo.Header.Value & ((1 << 18) - 1); return (uint)(funcLengthInHeader * (_target.PointerSize / 2)); } public bool TryGetRuntimeFunctionIndexForAddress(TargetPointer runtimeFunctions, uint numRuntimeFunctions, TargetPointer relativeAddress, out uint index) { // NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod uint start = 0; uint end = numRuntimeFunctions - 1; relativeAddress = CodePointerUtils.CodePointerFromAddress(relativeAddress, _target).AsTargetPointer; // Entries are sorted. return BinaryThenLinearSearch.Search(start, end, Compare, Match, out index); bool Compare(uint index) { Data.RuntimeFunction func = GetRuntimeFunction(runtimeFunctions, index); return relativeAddress < func.BeginAddress; }; bool Match(uint index) { // If there is a next Unwind Info, check if the address is in the next Unwind Info. if (index < numRuntimeFunctions - 1) { Data.RuntimeFunction nextFunc = GetRuntimeFunction(runtimeFunctions, index + 1); if (relativeAddress >= nextFunc.BeginAddress) return false; } Data.RuntimeFunction func = GetRuntimeFunction(runtimeFunctions, index); return relativeAddress >= func.BeginAddress; } } public TargetPointer GetRuntimeFunctionAddress(TargetPointer runtimeFunctions, uint index) { return runtimeFunctions + (index * _runtimeFunctionSize); } public Data.RuntimeFunction GetRuntimeFunction(TargetPointer runtimeFunctions, uint index) { TargetPointer addr = GetRuntimeFunctionAddress(runtimeFunctions, index); return _target.ProcessedData.GetOrAdd<Data.RuntimeFunction>(addr); } }