Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 26 additions & 5 deletions docs/design/datacontracts/RuntimeInfo.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,32 @@ public enum RuntimeInfoArchitecture : uint
{
Unknown = 0,
X86,
Arm32,
X64,
Arm,
Arm64,
Wasm,
S390x,
LoongArch64,
RISCV,
Armv6,
Ppc64le,
RiscV64,
}

public enum RuntimeInfoOperatingSystem : uint
{
Unknown = 0,
Win,
Windows,
Unix,
Browser,
Apple,
}

public enum RuntimeInfoRuntimeFlavor : uint
{
Unknown = 0,
Coreclr,
NativeAot,
}
Comment thread
max-charlamb marked this conversation as resolved.
```

```csharp
Expand All @@ -33,6 +44,14 @@ RuntimeInfoArchitecture GetTargetArchitecture();
// Gets the targets operating system. If this information is not available returns Unknown.
RuntimeInfoOperatingSystem GetTargetOperatingSystem();

// Gets the target's runtime flavor. If this information is not
// available returns Unknown. This is intended to be descriptive information for
// users and provides no guarantees how the underlying runtime works. Over time
// implementation details may change dramatically. For determining what features or
// invariants a given runtime implementation supports look at which contracts are
// implemented or call contract APIs that probe for specific capabilities.
Comment thread
max-charlamb marked this conversation as resolved.
RuntimeInfoRuntimeFlavor GetRuntimeFlavor();

// Returns the runtime's RecommendedReaderVersion global. Returns 0 if the global is absent.
uint GetRecommendedReaderVersion();

Expand All @@ -47,10 +66,12 @@ Global variables used:
| --- | --- | --- |
| Architecture | string | Target architecture |
| OperatingSystem | string | Target operating system |
| RuntimeFlavor | string | Target runtime flavor |
| RecommendedReaderVersion | uint32 | Incremented when an update to the latest contracts is recommended |

The contract implementation returns the architecture and operating system global values parsed as the
respective enum case-insensitively. If these globals are not available, the contract returns Unknown.
The contract implementation returns the architecture, operating system, and runtime flavor global
values parsed as the respective enum case-insensitively. If these globals are not available, the
contract returns Unknown.

`Apple` covers all Apple platforms (macOS, iOS, tvOS, MacCatalyst) — i.e. any target where the
runtime is compiled with `TARGET_APPLE` defined. It is distinct from `Unix` so that consumers which
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,15 @@ set(CMAKE_INCLUDE_CURRENT_DIR OFF)

include(${CLR_DIR}/clrdatadescriptors.cmake)

if(CDAC_BUILD_TOOL_BINARY_PATH AND "${CLR_DOTNET_RID}" STREQUAL "")
message(FATAL_ERROR "CLR_DOTNET_RID is not set. Please ensure it is being set to the portable RID of the target platform by runtime.proj.")
endif()
configure_file(configure.h.in ${CMAKE_CURRENT_BINARY_DIR}/configure.h)

add_library(nativeaot_descriptor_interface INTERFACE)
target_include_directories(nativeaot_descriptor_interface INTERFACE
${CMAKE_CURRENT_SOURCE_DIR})
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(nativeaot_descriptor_interface INTERFACE nativeaot_runtime_includes)
add_dependencies(nativeaot_descriptor_interface aot_eventing_headers)
generate_data_descriptors(
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/nativeaot/Runtime/datadescriptor/configure.h.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef NATIVEAOT_RUNTIME_INFO_CONFIGURE_H_INCLUDED
#define NATIVEAOT_RUNTIME_INFO_CONFIGURE_H_INCLUDED

#define RID_STRING @CLR_DOTNET_RID@

#endif // NATIVEAOT_RUNTIME_INFO_CONFIGURE_H_INCLUDED
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include "thread.h"
#include "threadstore.h"

#include "configure.h"

#include <stdint.h>
#include <stddef.h>

Expand Down
60 changes: 60 additions & 0 deletions src/coreclr/nativeaot/Runtime/datadescriptor/datadescriptor.inc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@
// 3. Update the contract implementation in src/native/managed/cdac/.../Contracts/<Contract>.cs
// 4. Update the mock descriptors and tests in src/native/managed/cdac/tests/.

// Increment this when making a change where we'd like to recommend users update their diagnostic tools.
// Tools can use this to display an advisory notice to users encouraging them to update. Changing
// this value on its own is not considered a breaking change. See the RuntimeInfo.md data contract for details.
// When incrementing this value, also implement the new functionality in the cDAC reader and update the
// GetCurrentReaderVersion() method on the IRuntimeInfo contract in
// src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeInfo_1.cs
// to match.
#ifndef CDAC_RECOMMENDED_READER_VERSION
#define CDAC_RECOMMENDED_READER_VERSION 1
#endif

CDAC_BASELINE("empty")
CDAC_TYPES_BEGIN()

Expand Down Expand Up @@ -160,10 +171,59 @@ CDAC_GLOBAL(StressLogChunkSize, T_UINT32, STRESSLOG_CHUNK_SIZE)
CDAC_GLOBAL(StressLogValidChunkSig, T_UINT32, 0xCFCFCFCF)
CDAC_GLOBAL(StressLogMaxMessageSize, T_UINT64, (uint64_t)StressMsg::maxMsgSize)

#if defined(TARGET_BROWSER)
#ifdef Browser
#error Handle 'Browser' define
#endif // Browser
CDAC_GLOBAL_STRING(OperatingSystem, Browser)
#elif defined(TARGET_APPLE)
#ifdef Apple
#error Handle 'Apple' define
#endif // Apple
CDAC_GLOBAL_STRING(OperatingSystem, Apple)
#elif defined(TARGET_UNIX)
#ifdef Unix
#error Handle 'Unix' define
#endif // Unix
CDAC_GLOBAL_STRING(OperatingSystem, Unix)
#elif defined(TARGET_WINDOWS)
#ifdef Windows
#error Handle 'Windows' define
#endif // Windows
CDAC_GLOBAL_STRING(OperatingSystem, Windows)
#else
#error TARGET_{OS} define is not recognized by the cDAC. Update this switch and the enum values in IRuntimeInfo.cs
#endif

#if defined(TARGET_X86)
CDAC_GLOBAL_STRING(Architecture, x86)
#elif defined(TARGET_AMD64)
CDAC_GLOBAL_STRING(Architecture, x64)
#elif defined(TARGET_ARM)
CDAC_GLOBAL_STRING(Architecture, arm)
#elif defined(TARGET_ARM64)
CDAC_GLOBAL_STRING(Architecture, arm64)
#elif defined(TARGET_LOONGARCH64)
CDAC_GLOBAL_STRING(Architecture, loongarch64)
#elif defined(TARGET_RISCV64)
CDAC_GLOBAL_STRING(Architecture, riscv64)
#elif defined(TARGET_WASM)
CDAC_GLOBAL_STRING(Architecture, wasm)
#else
#error TARGET_{ARCH} define is not recognized by the cDAC. Update this switch and the enum values in IRuntimeInfo.cs
#endif

CDAC_GLOBAL_STRING(RuntimeFlavor, NativeAot)

CDAC_GLOBAL_STRING(RID, RID_STRING)

CDAC_GLOBAL(RecommendedReaderVersion, T_UINT32, CDAC_RECOMMENDED_READER_VERSION)

// Contracts: declare which contracts this runtime supports
CDAC_GLOBAL_CONTRACT(Thread, n1)
CDAC_GLOBAL_CONTRACT(Exception, c1)
CDAC_GLOBAL_CONTRACT(RuntimeTypeSystem, n1)
CDAC_GLOBAL_CONTRACT(RuntimeInfo, c1)
CDAC_GLOBAL_CONTRACT(StressLog, c2)

// Managed type sub-descriptor: ILC emits a ContractDescriptor with managed type layouts
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/vm/datadescriptor/datadescriptor.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1506,6 +1506,8 @@ CDAC_GLOBAL_STRING(Architecture, wasm)
#error TARGET_{ARCH} define is not recognized by the cDAC. Update this switch and the enum values in IRuntimeInfo.cs
#endif

CDAC_GLOBAL_STRING(RuntimeFlavor, Coreclr)

CDAC_GLOBAL_STRING(RID, RID_STRING)

CDAC_GLOBAL(GCInfoVersion, T_UINT32, GCINFO_VERSION)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,19 @@ public enum RuntimeInfoOperatingSystem : uint
Apple,
}

public enum RuntimeInfoRuntimeFlavor : uint
{
Unknown = 0,
Coreclr,
NativeAot,
}
Comment thread
max-charlamb marked this conversation as resolved.
Comment thread
max-charlamb marked this conversation as resolved.

public interface IRuntimeInfo : IContract
{
static string IContract.Name { get; } = nameof(RuntimeInfo);
RuntimeInfoArchitecture GetTargetArchitecture() => throw new NotImplementedException();
RuntimeInfoOperatingSystem GetTargetOperatingSystem() => throw new NotImplementedException();
RuntimeInfoRuntimeFlavor GetRuntimeFlavor() => throw new NotImplementedException();
Comment thread
max-charlamb marked this conversation as resolved.
Comment thread
max-charlamb marked this conversation as resolved.
uint GetCurrentReaderVersion() => throw new NotImplementedException();
uint GetRecommendedReaderVersion() => throw new NotImplementedException();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ public static class Globals

public const string Architecture = nameof(Architecture);
public const string OperatingSystem = nameof(OperatingSystem);
public const string RuntimeFlavor = nameof(RuntimeFlavor);

public const string GCInfoVersion = nameof(GCInfoVersion);
public const string GCLowestAddress = nameof(GCLowestAddress);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,43 @@

namespace Microsoft.Diagnostics.DataContractReader.Contracts;

internal struct RuntimeInfo_1 : IRuntimeInfo
internal sealed class RuntimeInfo_1 : IRuntimeInfo
{
internal readonly Target _target;
private readonly Target _target;

private RuntimeInfoArchitecture? _architecture;
private RuntimeInfoOperatingSystem? _operatingSystem;
private RuntimeInfoRuntimeFlavor? _runtimeFlavor;
private uint? _recommendedReaderVersion;

public RuntimeInfo_1(Target target)
{
_target = target;
}

readonly RuntimeInfoArchitecture IRuntimeInfo.GetTargetArchitecture()
public void Flush(FlushScope scope)
{
_architecture = null;
Comment thread
max-charlamb marked this conversation as resolved.
_operatingSystem = null;
_runtimeFlavor = null;
_recommendedReaderVersion = null;
}
Comment thread
max-charlamb marked this conversation as resolved.

RuntimeInfoArchitecture IRuntimeInfo.GetTargetArchitecture()
=> _architecture ??= ReadArchitecture();

RuntimeInfoOperatingSystem IRuntimeInfo.GetTargetOperatingSystem()
=> _operatingSystem ??= ReadOperatingSystem();

RuntimeInfoRuntimeFlavor IRuntimeInfo.GetRuntimeFlavor()
=> _runtimeFlavor ??= ReadRuntimeFlavor();

uint IRuntimeInfo.GetCurrentReaderVersion() => 1;

uint IRuntimeInfo.GetRecommendedReaderVersion()
=> _recommendedReaderVersion ??= ReadRecommendedReaderVersion();

private RuntimeInfoArchitecture ReadArchitecture()
{
if (_target.TryReadGlobalString(Constants.Globals.Architecture, out string? arch))
{
Expand All @@ -27,7 +54,7 @@ readonly RuntimeInfoArchitecture IRuntimeInfo.GetTargetArchitecture()
return RuntimeInfoArchitecture.Unknown;
}

readonly RuntimeInfoOperatingSystem IRuntimeInfo.GetTargetOperatingSystem()
private RuntimeInfoOperatingSystem ReadOperatingSystem()
{
if (_target.TryReadGlobalString(Constants.Globals.OperatingSystem, out string? os))
{
Expand All @@ -40,9 +67,20 @@ readonly RuntimeInfoOperatingSystem IRuntimeInfo.GetTargetOperatingSystem()
return RuntimeInfoOperatingSystem.Unknown;
}

readonly uint IRuntimeInfo.GetCurrentReaderVersion() => 1;
private RuntimeInfoRuntimeFlavor ReadRuntimeFlavor()
{
if (_target.TryReadGlobalString(Constants.Globals.RuntimeFlavor, out string? flavor))
{
if (Enum.TryParse(flavor, ignoreCase: true, out RuntimeInfoRuntimeFlavor parsedFlavor))
{
return parsedFlavor;
}
}
Comment thread
max-charlamb marked this conversation as resolved.

return RuntimeInfoRuntimeFlavor.Unknown;
}

readonly uint IRuntimeInfo.GetRecommendedReaderVersion()
private uint ReadRecommendedReaderVersion()
{
_target.TryReadGlobal(Constants.Globals.RecommendedReaderVersion, out uint? runtimeVersion);
return runtimeVersion ?? 0;
Expand Down
12 changes: 12 additions & 0 deletions src/native/managed/cdac/tests/DumpTests/RuntimeInfoDumpTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,16 @@ public void RuntimeInfo_OperatingSystemMatchesDumpMetadata(TestConfiguration con

Assert.Equal(expected, os);
}

[ConditionalTheory]
[MemberData(nameof(TestConfigurations))]
public void RuntimeInfo_RuntimeFlavorIsCoreclr(TestConfiguration config)
{
InitializeDumpTest(config);

IRuntimeInfo runtimeInfo = Target.Contracts.RuntimeInfo;
RuntimeInfoRuntimeFlavor flavor = runtimeInfo.GetRuntimeFlavor();

Assert.Equal(RuntimeInfoRuntimeFlavor.Coreclr, flavor);
}
}
Loading
Loading