File: CodePointerUtils.cs
Web Access
Project: src\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;
using System.Diagnostics;
using Microsoft.Diagnostics.DataContractReader.Contracts;

namespace Microsoft.Diagnostics.DataContractReader;

internal static class CodePointerUtils
{
    private const uint Arm32ThumbBit = 1;

    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))
        {
            return new TargetCodePointer(address.Value | Arm32ThumbBit);
        }
        else if (flags.HasFlag(CodePointerFlags.HasArm64PtrAuth))
        {
            throw new NotImplementedException($"{nameof(CodePointerFromAddress)}: ARM64 with pointer authentication");
        }
        Debug.Assert(flags == default);
        return new TargetCodePointer(address.Value);
    }

    internal static TargetPointer AddressFromCodePointer(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(AddressFromCodePointer)}: ARM64 with pointer authentication");
        }
        Debug.Assert(flags == default);
        return new TargetPointer(code.Value);
    }
}