From 50f24311ff331d435076d87e1be97c30d6247f00 Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 11:51:59 -0400 Subject: [PATCH 01/19] refactor --- src/coreclr/CMakeLists.txt | 6 + src/coreclr/clrdatadescriptors.cmake | 97 +++++++++ .../debug/datadescriptor-shared/README.md | 187 ++++++++++++++++++ .../contract-descriptor.c.in | 17 +- .../contractconfiguration.h.in | 6 + .../contractdescriptorstub.c | 15 +- .../contractpointerdata.cpp | 20 +- .../datadescriptor.cpp | 49 ++--- .../datadescriptorwrapper.inc | 59 ++++++ src/coreclr/debug/runtimeinfo/CMakeLists.txt | 72 ++----- .../debug/runtimeinfo/datadescriptor.h | 24 +++ .../debug/runtimeinfo/datadescriptor.inc | 114 +---------- 12 files changed, 434 insertions(+), 232 deletions(-) create mode 100644 src/coreclr/clrdatadescriptors.cmake create mode 100644 src/coreclr/debug/datadescriptor-shared/README.md rename src/coreclr/debug/{runtimeinfo => datadescriptor-shared}/contract-descriptor.c.in (62%) create mode 100644 src/coreclr/debug/datadescriptor-shared/contractconfiguration.h.in rename src/coreclr/debug/{runtimeinfo => datadescriptor-shared}/contractdescriptorstub.c (68%) rename src/coreclr/debug/{runtimeinfo => datadescriptor-shared}/contractpointerdata.cpp (54%) rename src/coreclr/debug/{runtimeinfo => datadescriptor-shared}/datadescriptor.cpp (94%) create mode 100644 src/coreclr/debug/datadescriptor-shared/datadescriptorwrapper.inc create mode 100644 src/coreclr/debug/runtimeinfo/datadescriptor.h diff --git a/src/coreclr/CMakeLists.txt b/src/coreclr/CMakeLists.txt index 6e9519affb16d1..b1433e14def45b 100644 --- a/src/coreclr/CMakeLists.txt +++ b/src/coreclr/CMakeLists.txt @@ -178,6 +178,12 @@ endif(CLR_CMAKE_HOST_WIN32) #---------------------------------- include(clrdefinitions.cmake) +#-------------------------------- +# Data descriptors mechanics +# - all clr specific data descriptor helpers should be included in this file +#---------------------------------- +include(clrdatadescriptors.cmake) + if(FEATURE_STANDALONE_GC) add_definitions(-DFEATURE_STANDALONE_GC) endif(FEATURE_STANDALONE_GC) diff --git a/src/coreclr/clrdatadescriptors.cmake b/src/coreclr/clrdatadescriptors.cmake new file mode 100644 index 00000000000000..fc4b4ca613bd13 --- /dev/null +++ b/src/coreclr/clrdatadescriptors.cmake @@ -0,0 +1,97 @@ +# cDAC contract descriptor + +function(generate_data_descriptors) + set(options DLLEXPORT) + set(oneValueArgs LIBRARY_NAME CONTRACT_FILE CONTRACT_NAME INTERFACE_TARGET) + set(multiValueArgs "") + cmake_parse_arguments(DATA_DESCRIPTORS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGV}) + + # INTERMEDIARY_LIBRARY is used as part of the build and not linked into the final product. + set(INTERMEDIARY_LIBRARY ${DATA_DESCRIPTORS_LIBRARY_NAME}_temp) + set(LIBRARY ${DATA_DESCRIPTORS_LIBRARY_NAME}) + + set(DATA_DESCRIPTOR_SHARED_SOURCE_DIR "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/debug/datadescriptor-shared") + set(GENERATED_CDAC_DESCRIPTOR_DIR "${CMAKE_CURRENT_BINARY_DIR}/cdac-${LIBRARY}") + + # configure contract export name + set(POINTER_DATA_NAME ${DATA_DESCRIPTORS_CONTRACT_NAME}PointerData) + set(CONTRACT_NAME ${DATA_DESCRIPTORS_CONTRACT_NAME}) + if (DATA_DESCRIPTORS_DLLEXPORT) + set(EXPORT_CONTRACT 1) + else() + set(EXPORT_CONTRACT 0) + endif() + configure_file("${DATA_DESCRIPTOR_SHARED_SOURCE_DIR}/contractconfiguration.h.in" "${GENERATED_CDAC_DESCRIPTOR_DIR}/contractconfiguration.h") + + if (NOT CDAC_BUILD_TOOL_BINARY_PATH) + # if CDAC_BUILD_TOOL_BINARY_PATH is unspecified (for example for a build without a .NET SDK or msbuild), + # link a stub contract descriptor into the runtime + add_library_clr(${LIBRARY} OBJECT "${DATA_DESCRIPTOR_SHARED_SOURCE_DIR}/contractdescriptorstub.c") + target_include_directories(${LIBRARY} PRIVATE ${GENERATED_CDAC_DESCRIPTOR_DIR}) + message(STATUS "Using a stub cDAC contract descriptor") + else() + # generate a contract descriptor using cdac-build-tool from a data descriptor and contract json file + + if(NOT EXISTS "${CDAC_BUILD_TOOL_BINARY_PATH}") + message(FATAL_ERROR "${CDAC_BUILD_TOOL_BINARY_PATH} does not exist") + endif() + + add_library(${INTERMEDIARY_LIBRARY} OBJECT "${DATA_DESCRIPTOR_SHARED_SOURCE_DIR}/datadescriptor.cpp") + target_include_directories(${INTERMEDIARY_LIBRARY} PRIVATE ${DATA_DESCRIPTOR_SHARED_SOURCE_DIR}) + + if(CLR_CMAKE_TARGET_WIN32) + # turn off whole program optimization: + # 1. it creates object files that cdac-build-tool can't read + # 2. we never link INTERMEDIARY_LIBRARY into the final product - it's only job is to be scraped + set_target_properties(${INTERMEDIARY_LIBRARY} PROPERTIES + INTERPROCEDURAL_OPTIMIZATION_RELEASE OFF + INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO OFF) + endif() + + # inherit definitions, include directories, and dependencies from the INTERFACE target + add_interface_library(${INTERMEDIARY_LIBRARY} ${DATA_DESCRIPTORS_INTERFACE_TARGET}) + + set(CONTRACT_BASELINE_DIR "${CLR_REPO_ROOT_DIR}/docs/design/datacontracts/data") + set(CONTRACT_DESCRIPTOR_INPUT "${DATA_DESCRIPTOR_SHARED_SOURCE_DIR}/contract-descriptor.c.in") + set(CONTRACT_DESCRIPTOR_OUTPUT "${GENERATED_CDAC_DESCRIPTOR_DIR}/contract-descriptor.c") + set(CONTRACT_FILE "${DATA_DESCRIPTORS_CONTRACT_FILE}") + + # generate the contract descriptor by running cdac-build-tool + # n.b. this just uses `dotnet` from the PATH. InitializeDotNetCli adds the appropriate directory + add_custom_command( + OUTPUT "${CONTRACT_DESCRIPTOR_OUTPUT}" + VERBATIM + COMMAND ${CLR_DOTNET_HOST_PATH} ${CDAC_BUILD_TOOL_BINARY_PATH} compose -i "${CONTRACT_DESCRIPTOR_INPUT}" -o "${CONTRACT_DESCRIPTOR_OUTPUT}" -b "${CONTRACT_BASELINE_DIR}" -c "${CONTRACT_FILE}" $ + DEPENDS ${INTERMEDIARY_LIBRARY} ${DATA_DESCRIPTORS_DEPENDENCIES} $ "${CONTRACT_FILE}" "${CONTRACT_DESCRIPTOR_INPUT}" + USES_TERMINAL + ) + + # It is important that LIBRARY is an object library; + # if it was static, linking it into the final dll would not export + # DotNetRuntimeContractDescriptor since it is not referenced anywhere. + add_library_clr(${LIBRARY} OBJECT + "${CONTRACT_DESCRIPTOR_OUTPUT}" + "${DATA_DESCRIPTOR_SHARED_SOURCE_DIR}/contractpointerdata.cpp" + ) + add_dependencies(${LIBRARY} ${INTERMEDIARY_LIBRARY}) + + target_include_directories(${LIBRARY} PRIVATE + ${DATA_DESCRIPTOR_SHARED_SOURCE_DIR} + ${GENERATED_CDAC_DESCRIPTOR_DIR} + ) + + # inherit definitions, include directories, and dependencies from the INTERFACE target + add_interface_library(${LIBRARY} ${DATA_DESCRIPTORS_INTERFACE_TARGET}) + endif() +endfunction(generate_data_descriptors) + +# Links in an interface to a target with the interface include directories included +# before the targets include directories. +function(add_interface_library target_name interface_name) + get_target_property(target_includes ${target_name} INCLUDE_DIRECTORIES) + target_link_libraries(${target_name} PRIVATE ${interface_name}) + set_target_properties(${target_name} PROPERTIES INCLUDE_DIRECTORIES "${target_includes}") + + get_target_property(interface_includes ${interface_name} INTERFACE_INCLUDE_DIRECTORIES) + target_include_directories(${target_name} BEFORE PRIVATE ${interface_includes}) +endfunction(add_interface_library) \ No newline at end of file diff --git a/src/coreclr/debug/datadescriptor-shared/README.md b/src/coreclr/debug/datadescriptor-shared/README.md new file mode 100644 index 00000000000000..a9cb3f5890e19c --- /dev/null +++ b/src/coreclr/debug/datadescriptor-shared/README.md @@ -0,0 +1,187 @@ +# Datadescriptor Implementation Infrastructure + +This folder contains infrastructure to create data descriptors as defined in the [data_descriptor.md](../../../../docs/design/datacontracts/data_descriptor.md). Data descriptors enable diagnostic tooling (debuggers, profilers, etc.) to understand the internal layout and structure of .NET runtime objects without requiring intimate knowledge of implementation details. + + + +## Getting Started + +### Quick Example + +Here's how to create a simple data descriptor for a new runtime component: + +**1. Create the required files:** + +``` +your_component/ +├── CMakeLists.txt +├── datadescriptor.h +├── datadescriptor.inc +└── contracts.jsonc +``` + +**2. Define your data descriptor (`datadescriptor.inc`):** + +```cpp +CDAC_BASELINE("empty") +CDAC_TYPES_BEGIN() + +CDAC_TYPE_BEGIN(MyRuntimeObject) +CDAC_TYPE_SIZE(sizeof(MyRuntimeObject)) +CDAC_TYPE_FIELD(MyRuntimeObject, uint32, Id, offsetof(MyRuntimeObject, m_id)) +CDAC_TYPE_FIELD(MyRuntimeObject, pointer, NextObject, offsetof(MyRuntimeObject, m_next)) +CDAC_TYPE_END(MyRuntimeObject) + +CDAC_TYPES_END() +CDAC_GLOBALS_BEGIN() + +CDAC_GLOBAL(g_MyGlobalCounter, uint32, g_myGlobalCounter) + +CDAC_GLOBALS_END() +``` + +**3. Create the header file (`datadescriptor.h`):** + +```cpp +#include "my_runtime_object.h" // Your actual runtime structures +``` + +**4. Add CMake integration (`CMakeLists.txt`):** + +```cmake +add_library(my_component_interface INTERFACE) +target_include_directories(my_component_interface INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR} + # include dirs here) +generate_data_descriptors( + LIBRARY_NAME my_component_contract_descriptor + CONTRACT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/contracts.jsonc" + CONTRACT_NAME "MyComponentContractDescriptor" + INTERFACE_TARGET my_component_interface + DLLEXPORT +) +``` + +Then the output object library `my_component_contract_descriptor` can be linked into the shipping dll. + +## CMake Integration and Build System + +### Function Parameters + +The `generate_data_descriptors` function defined in `clrdatadescriptors.cmake` takes the following arguments: + +* **`LIBRARY_NAME`** (Required) - Sets the name of the target object being created +* **`CONTRACT_FILE`** (Required) - Path to the contract JSON file defining supported contracts +* **`CONTRACT_NAME`** (Required) - Name of the `ContractDescriptor` export symbol +* **`INTERFACE_TARGET`** (Required) - Interface target providing dependencies, include directories, and definitions +* **`DLLEXPORT`** (Optional) - Controls if the `CONTRACT_NAME` will be exported from the DLL + +### Two-Phase Build Process + +The build system uses a sophisticated two-phase approach: + +**Phase 1: Intermediary Library** +- Compiles `datadescriptor.cpp` with your `datadescriptor.h` and `datadescriptor.inc` +- Creates object files that the `cdac-build-tool` can analyze +- Extracts type layout information and generates string pools + +**Phase 2: Contract Descriptor Generation** +- Runs `cdac-build-tool` to process the intermediary object files +- Generates the final contract descriptor C source file +- Compiles this into the final library that gets linked into the runtime + + +## Macro Reference + +### Structure Definition Macros + +**`CDAC_BASELINE("identifier")`** +- Specifies the baseline data contract version +- Use `"empty"` for new descriptors +- Must appear before any other content + +**`CDAC_TYPES_BEGIN()` / `CDAC_TYPES_END()`** +- Delimits the type definitions section +- Must contain all `CDAC_TYPE_*` macros + +**`CDAC_TYPE_BEGIN(typeName)`** +- Starts a new type definition +- `typeName` must be globally unique within the descriptor + +**`CDAC_TYPE_SIZE(sizeInBytes)`** +- Specifies the type has a determinate size +- Usually `sizeof(YourNativeType)` + +**`CDAC_TYPE_INDETERMINATE(typeName)`** +- Specifies the type has indeterminate size +- Alternative to `CDAC_TYPE_SIZE` + +**`CDAC_TYPE_FIELD(typeName, fieldType, fieldName, offset)`** +- Defines a field within the type +- `fieldType`: primitive type or another defined type +- `fieldName`: diagnostic-friendly name (use managed names for managed types) +- `offset`: byte offset, usually `offsetof()` or `cdac_data::FieldName` + +**`CDAC_TYPE_END(typeName)`** +- Closes the type definition +- `typeName` must match the corresponding `CDAC_TYPE_BEGIN` + +### Global Value Macros + +**`CDAC_GLOBALS_BEGIN()` / `CDAC_GLOBALS_END()`** +- Delimits the global values section + +**`CDAC_GLOBAL(globalName, typeName, value)`** +- Defines a global literal value +- `value` must be a compile-time constant +- `typeName` can be a primitive type or defined type + +**`CDAC_GLOBAL_POINTER(globalName, address)`** +- Defines a global pointer value +- `address` must be a compile-time constant pointer or `uintptr_t` + +**`CDAC_GLOBAL_STRING(globalName, stringValue)`** +- Defines a global string value +- `stringValue` must be a compile-time string literal + + +## Reference Implementation + +For comprehensive examples, see the current implementation in: +- **`src/coreclr/debug/runtimeinfo/`** - Complete real-world implementation + - `datadescriptor.h` - Headers and includes + - `datadescriptor.inc` - Full type definitions for runtime objects + - `contracts.jsonc` - Contract definitions + - `CMakeLists.txt` - Build integration + +## Related Documentation + +- **[Data Contracts Design](../../../../docs/design/datacontracts/datacontracts_design.md)** - Overall design and motivation +- **[Contract Descriptor](../../../../docs/design/datacontracts/contract-descriptor.md)** - Binary format specification +- **[Data Descriptor](../../../../docs/design/datacontracts/data_descriptor.md)** - Logical format specification diff --git a/src/coreclr/debug/runtimeinfo/contract-descriptor.c.in b/src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in similarity index 62% rename from src/coreclr/debug/runtimeinfo/contract-descriptor.c.in rename to src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in index c1f0edd7a66f9c..1df29d8df2f5f2 100644 --- a/src/coreclr/debug/runtimeinfo/contract-descriptor.c.in +++ b/src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in @@ -1,7 +1,7 @@ -// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #include +#include "contractconfiguration.h" #ifdef _MSC_VER #define DLLEXPORT __declspec(dllexport) @@ -9,7 +9,7 @@ #define DLLEXPORT __attribute__((visibility("default"))) #endif -struct DotNetRuntimeContractDescriptor +struct ContractDescriptor { uint64_t magic; uint32_t flags; @@ -20,15 +20,16 @@ struct DotNetRuntimeContractDescriptor const uintptr_t *pointer_data; }; -extern const uintptr_t contractDescriptorPointerData[]; +extern const uintptr_t POINTER_DATA_NAME[]; -DLLEXPORT struct DotNetRuntimeContractDescriptor DotNetRuntimeContractDescriptor; - -DLLEXPORT struct DotNetRuntimeContractDescriptor DotNetRuntimeContractDescriptor = { +#if EXPORT_CONTRACT +DLLEXPORT +#endif // EXPORT_CONTRACT +struct ContractDescriptor CONTRACT_NAME = { .magic = 0x0043414443434e44ull, // "DNCCDAC\0" .flags = %%platformFlags%%, .descriptor_size = %%jsonDescriptorSize%%, .descriptor = "%%jsonDescriptor%%", .pointer_data_count = %%pointerDataCount%%, - .pointer_data = &contractDescriptorPointerData[0], -}; + .pointer_data = &POINTER_DATA_NAME[0], +}; \ No newline at end of file diff --git a/src/coreclr/debug/datadescriptor-shared/contractconfiguration.h.in b/src/coreclr/debug/datadescriptor-shared/contractconfiguration.h.in new file mode 100644 index 00000000000000..95e3eada4e0782 --- /dev/null +++ b/src/coreclr/debug/datadescriptor-shared/contractconfiguration.h.in @@ -0,0 +1,6 @@ +#pragma once + +#define POINTER_DATA_NAME @POINTER_DATA_NAME@ +#define CONTRACT_NAME @CONTRACT_NAME@ + +#define EXPORT_CONTRACT @EXPORT_CONTRACT@ \ No newline at end of file diff --git a/src/coreclr/debug/runtimeinfo/contractdescriptorstub.c b/src/coreclr/debug/datadescriptor-shared/contractdescriptorstub.c similarity index 68% rename from src/coreclr/debug/runtimeinfo/contractdescriptorstub.c rename to src/coreclr/debug/datadescriptor-shared/contractdescriptorstub.c index 59421a6692d2a7..9494db3e66a703 100644 --- a/src/coreclr/debug/runtimeinfo/contractdescriptorstub.c +++ b/src/coreclr/debug/datadescriptor-shared/contractdescriptorstub.c @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. #include +#include "contractconfiguration.h" #ifdef _MSC_VER #define DLLEXPORT __declspec(dllexport) @@ -9,7 +10,7 @@ #define DLLEXPORT __attribute__((visibility("default"))) #endif -struct DotNetRuntimeContractDescriptor +struct ContractDescriptor { uint64_t magic; uint32_t flags; @@ -20,20 +21,20 @@ struct DotNetRuntimeContractDescriptor const uintptr_t *pointer_data; }; -extern const uintptr_t contractDescriptorPointerData[]; +extern const uintptr_t POINTER_DATA_NAME[]; // just the placeholder pointer -const uintptr_t contractDescriptorPointerData[] = { (uintptr_t)0 }; +const uintptr_t POINTER_DATA_NAME[] = { (uintptr_t)0 }; -DLLEXPORT struct DotNetRuntimeContractDescriptor DotNetRuntimeContractDescriptor; +DLLEXPORT struct ContractDescriptor CONTRACT_NAME; #define STUB_DESCRIPTOR "{\"version\":0,\"baseline\":\"empty\",\"contracts\":{},\"types\":{},\"globals\":{}}" -DLLEXPORT struct DotNetRuntimeContractDescriptor DotNetRuntimeContractDescriptor = { +DLLEXPORT struct ContractDescriptor CONTRACT_NAME = { .magic = 0x0043414443434e44ull, // "DNCCDAC\0" .flags = 0x1u & (sizeof(void*) == 4 ? 0x02u : 0x00u), .descriptor_size = sizeof(STUB_DESCRIPTOR), .descriptor = STUB_DESCRIPTOR, .pointer_data_count = 1, - .pointer_data = &contractDescriptorPointerData[0], -}; + .pointer_data = &POINTER_DATA_NAME[0], +}; \ No newline at end of file diff --git a/src/coreclr/debug/runtimeinfo/contractpointerdata.cpp b/src/coreclr/debug/datadescriptor-shared/contractpointerdata.cpp similarity index 54% rename from src/coreclr/debug/runtimeinfo/contractpointerdata.cpp rename to src/coreclr/debug/datadescriptor-shared/contractpointerdata.cpp index 1848b1fb69d898..317e3e87b44007 100644 --- a/src/coreclr/debug/runtimeinfo/contractpointerdata.cpp +++ b/src/coreclr/debug/datadescriptor-shared/contractpointerdata.cpp @@ -1,24 +1,18 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#include "common.h" - -#include -#include - -#include "cdacplatformmetadata.hpp" -#include "threads.h" -#include "vars.hpp" +#include "datadescriptor.h" +#include "contractconfiguration.h" extern "C" { // without an extern declaration, clang does not emit this global into the object file -extern const uintptr_t contractDescriptorPointerData[]; +extern const uintptr_t POINTER_DATA_NAME[]; -const uintptr_t contractDescriptorPointerData[] = { +const uintptr_t POINTER_DATA_NAME[] = { (uintptr_t)0, // placeholder #define CDAC_GLOBAL_POINTER(name,value) (uintptr_t)(value), -#include "datadescriptor.inc" +#define CDAC_GLOBAL_SUB_DESCRIPTOR(name,value) (uintptr_t)(value), +#include "datadescriptorwrapper.inc" }; - -} +} \ No newline at end of file diff --git a/src/coreclr/debug/runtimeinfo/datadescriptor.cpp b/src/coreclr/debug/datadescriptor-shared/datadescriptor.cpp similarity index 94% rename from src/coreclr/debug/runtimeinfo/datadescriptor.cpp rename to src/coreclr/debug/datadescriptor-shared/datadescriptor.cpp index 0efae1ad25089f..9b84cc413bc3a9 100644 --- a/src/coreclr/debug/runtimeinfo/datadescriptor.cpp +++ b/src/coreclr/debug/datadescriptor-shared/datadescriptor.cpp @@ -1,26 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -#include "common.h" - -#include -#include - -#include "static_assert.h" - -#include -#include "cdacplatformmetadata.hpp" -#include "methodtable.h" -#include "threads.h" -#include "exinfo.h" - -#include "configure.h" - -#include "../debug/ee/debugger.h" - -#ifdef HAVE_GCCOVER -#include "gccover.h" -#endif // HAVE_GCCOVER +#include "datadescriptor.h" // begin blob definition @@ -89,7 +70,7 @@ struct CDacStringPoolSizes #define CDAC_GLOBAL_POINTER(name,value) DECL_LEN(MAKE_GLOBALLEN_NAME(name), sizeof(#name)) #define CDAC_GLOBAL(name,tyname,value) DECL_LEN(MAKE_GLOBALLEN_NAME(name), sizeof(#name)) \ DECL_LEN(MAKE_GLOBALTYPELEN_NAME(name), sizeof(#tyname)) -#include "datadescriptor.inc" +#include "datadescriptorwrapper.inc" char cdac_string_pool_trailing_nil; #undef DECL_LEN }; @@ -107,7 +88,7 @@ enum CDacBlobTypesCount = #define CDAC_TYPES_BEGIN() 0 #define CDAC_TYPE_BEGIN(name) + 1 -#include "datadescriptor.inc" +#include "datadescriptorwrapper.inc" }; // count the field pool size. @@ -118,7 +99,7 @@ enum #define CDAC_TYPES_BEGIN() 1 #define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) + 1 #define CDAC_TYPE_END(name) + 1 -#include "datadescriptor.inc" +#include "datadescriptorwrapper.inc" }; // count the literal globals @@ -127,7 +108,7 @@ enum CDacBlobGlobalLiteralsCount = #define CDAC_GLOBALS_BEGIN() 0 #define CDAC_GLOBAL(name,tyname,value) + 1 -#include "datadescriptor.inc" +#include "datadescriptorwrapper.inc" }; // count the aux vector globals @@ -136,7 +117,7 @@ enum CDacBlobGlobalPointersCount = #define CDAC_GLOBALS_BEGIN() 0 #define CDAC_GLOBAL_POINTER(name,value) + 1 -#include "datadescriptor.inc" +#include "datadescriptorwrapper.inc" }; // count the global strings @@ -145,7 +126,7 @@ enum CDacBlobGlobalStringsCount = #define CDAC_GLOBALS_BEGIN() 0 #define CDAC_GLOBAL_STRING(name,value) + 1 -#include "datadescriptor.inc" +#include "datadescriptorwrapper.inc" }; @@ -175,7 +156,7 @@ struct CDacFieldsPoolSizes #define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) DECL_LEN(CONCAT4(cdac_fields_pool_member__, tyname, __, membername)) #define CDAC_TYPE_END(name) DECL_LEN(CONCAT4(cdac_fields_pool_member__, tyname, _, endmarker)) \ } MAKE_TYPEFIELDS_TYNAME(name); -#include "datadescriptor.inc" +#include "datadescriptorwrapper.inc" #undef DECL_LEN }; @@ -197,7 +178,7 @@ struct CDacGlobalPointerIndex #define DECL_LEN(membername) char membername; #define CDAC_GLOBALS_BEGIN() DECL_LEN(cdac_global_pointer_index_start_placeholder__) #define CDAC_GLOBAL_POINTER(name,value) DECL_LEN(CONCAT(cdac_global_pointer_index__, name)) -#include "datadescriptor.inc" +#include "datadescriptorwrapper.inc" #undef DECL_LEN }; @@ -295,7 +276,7 @@ struct MagicAndBlob BlobDataDescriptor = { #define CDAC_TYPE_INDETERMINATE(name) /*.Size = */ 0, #define CDAC_TYPE_SIZE(size) /* .Size = */ size, #define CDAC_TYPE_END(name) }, -#include "datadescriptor.inc" +#include "datadescriptorwrapper.inc" }, /* .FieldsPool = */ { @@ -306,22 +287,22 @@ struct MagicAndBlob BlobDataDescriptor = { /* .FieldOffset = */ offset, \ }, #define CDAC_TYPE_END(name) { 0, }, -#include "datadescriptor.inc" +#include "datadescriptorwrapper.inc" }, /* .GlobalLiteralValues = */ { #define CDAC_GLOBAL(name,tyname,value) { /*.Name = */ GET_GLOBAL_NAME(name), /* .TypeName = */ GET_GLOBALTYPE_NAME(name), /* .Value = */ value }, -#include "datadescriptor.inc" +#include "datadescriptorwrapper.inc" }, /* .GlobalPointerValues = */ { #define CDAC_GLOBAL_POINTER(name,value) { /* .Name = */ GET_GLOBAL_NAME(name), /* .PointerDataIndex = */ GET_GLOBAL_POINTER_INDEX(name) }, -#include "datadescriptor.inc" +#include "datadescriptorwrapper.inc" }, /* .GlobalStringValues = */ { #define CDAC_GLOBAL_STRING(name,value) { /* .Name = */ GET_GLOBAL_NAME(name), /* .Value = */ GET_GLOBALSTRING_VALUE(name) }, -#include "datadescriptor.inc" +#include "datadescriptorwrapper.inc" }, /* .NamesPool = */ ("\0" // starts with a nul @@ -331,7 +312,7 @@ struct MagicAndBlob BlobDataDescriptor = { #define CDAC_GLOBAL_STRING(name,value) #name "\0" STRINGIFY(value) "\0" #define CDAC_GLOBAL_POINTER(name,value) #name "\0" #define CDAC_GLOBAL(name,tyname,value) #name "\0" #tyname "\0" -#include "datadescriptor.inc" +#include "datadescriptorwrapper.inc" ), /* .EndMagic = */ { 0x01, 0x02, 0x03, 0x04 }, diff --git a/src/coreclr/debug/datadescriptor-shared/datadescriptorwrapper.inc b/src/coreclr/debug/datadescriptor-shared/datadescriptorwrapper.inc new file mode 100644 index 00000000000000..adca117c6d7384 --- /dev/null +++ b/src/coreclr/debug/datadescriptor-shared/datadescriptorwrapper.inc @@ -0,0 +1,59 @@ +#ifndef CDAC_BASELINE +#define CDAC_BASELINE(identifier) +#endif +#ifndef CDAC_TYPES_BEGIN +#define CDAC_TYPES_BEGIN() +#endif +#ifndef CDAC_TYPE_BEGIN +#define CDAC_TYPE_BEGIN(tyname) +#endif +#ifndef CDAC_TYPE_SIZE +#define CDAC_TYPE_SIZE(k) +#endif +#ifndef CDAC_TYPE_INDETERMINATE +#define CDAC_TYPE_INDETERMINATE(tyname) +#endif +#ifndef CDAC_TYPE_FIELD +#define CDAC_TYPE_FIELD(tyname,fieldtyname,fieldname,off) +#endif +#ifndef CDAC_TYPE_END +#define CDAC_TYPE_END(tyname) +#endif +#ifndef CDAC_TYPES_END +#define CDAC_TYPES_END() +#endif +#ifndef CDAC_GLOBALS_BEGIN +#define CDAC_GLOBALS_BEGIN() +#endif +#ifndef CDAC_GLOBAL +#define CDAC_GLOBAL(globalname,tyname,val) +#endif +#ifndef CDAC_GLOBAL_POINTER +#define CDAC_GLOBAL_POINTER(globalname,addr) +#endif +#ifndef CDAC_GLOBAL_STRING +#define CDAC_GLOBAL_STRING(globalname,stringval) +#endif +#ifndef CDAC_GLOBAL_SUB_DESCRIPTOR +#define CDAC_GLOBAL_SUB_DESCRIPTOR(globalname,addr) +#endif +#ifndef CDAC_GLOBALS_END +#define CDAC_GLOBALS_END() +#endif + +#include "datadescriptor.inc" + +#undef CDAC_BASELINE +#undef CDAC_TYPES_BEGIN +#undef CDAC_TYPE_BEGIN +#undef CDAC_TYPE_INDETERMINATE +#undef CDAC_TYPE_SIZE +#undef CDAC_TYPE_FIELD +#undef CDAC_TYPE_END +#undef CDAC_TYPES_END +#undef CDAC_GLOBALS_BEGIN +#undef CDAC_GLOBAL +#undef CDAC_GLOBAL_POINTER +#undef CDAC_GLOBAL_STRING +#undef CDAC_GLOBAL_SUB_DESCRIPTOR +#undef CDAC_GLOBALS_END \ No newline at end of file diff --git a/src/coreclr/debug/runtimeinfo/CMakeLists.txt b/src/coreclr/debug/runtimeinfo/CMakeLists.txt index 1d0abd332c6011..127426b4f80749 100644 --- a/src/coreclr/debug/runtimeinfo/CMakeLists.txt +++ b/src/coreclr/debug/runtimeinfo/CMakeLists.txt @@ -1,10 +1,9 @@ -set(CMAKE_INCLUDE_CURRENT_DIR ON) - set(RUNTIMEINFO_SOURCES runtimeinfo.cpp ) add_library_clr(runtimeinfo STATIC ${RUNTIMEINFO_SOURCES}) +target_include_directories(runtimeinfo PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) function(generate_module_index Target ModuleIndexFile) # Win32 may be false when cross compiling @@ -47,58 +46,17 @@ if(CDAC_BUILD_TOOL_BINARY_PATH AND "${CLR_DOTNET_RID}" STREQUAL "") endif() configure_file(configure.h.in ${CMAKE_CURRENT_BINARY_DIR}/configure.h) -if (NOT CDAC_BUILD_TOOL_BINARY_PATH) - # if CDAC_BUILD_TOOL_BINARY_PATH is unspecified (for example for a build without a .NET SDK or msbuild), - # link a stub contract descriptor into the runtime - add_library_clr(cdac_contract_descriptor OBJECT contractdescriptorstub.c) - message(STATUS "Using a stub cDAC contract descriptor") -else() - # generate a contract descriptor using cdac-build-tool from a data descriptor and contract json file - - add_library(cdac_data_descriptor OBJECT datadescriptor.cpp) - # don't build the data descriptor before the VM (and any of its dependencies' generated headers) - add_dependencies(cdac_data_descriptor cee_wks_core) - if(CLR_CMAKE_TARGET_WIN32) - # turn off whole program optimization: - # 1. it creates object files that cdac-build-tool can't read - # 2. we never link cdac_data_descriptor into the final product - it's only job is to be scraped - set_target_properties(cdac_data_descriptor PROPERTIES - INTERPROCEDURAL_OPTIMIZATION_RELEASE OFF - INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO OFF) - endif() - target_include_directories(cdac_data_descriptor BEFORE PRIVATE ${VM_DIR}) - target_include_directories(cdac_data_descriptor BEFORE PRIVATE ${VM_DIR}/${ARCH_SOURCES_DIR}) - target_include_directories(cdac_data_descriptor PRIVATE ${CLR_DIR}/interop/inc) - - set(GENERATED_CDAC_DESCRIPTOR_DIR "${CMAKE_CURRENT_BINARY_DIR}/cdac") - set(CONTRACT_DESCRIPTOR_OUTPUT "${GENERATED_CDAC_DESCRIPTOR_DIR}/contract-descriptor.c") - if(NOT EXISTS "${CDAC_BUILD_TOOL_BINARY_PATH}") - message(FATAL_ERROR "${CDAC_BUILD_TOOL_BINARY_PATH} does not exist") - endif() - set(CONTRACT_DESCRIPTOR_INPUT "${CMAKE_CURRENT_SOURCE_DIR}/contract-descriptor.c.in") - - set(CONTRACT_BASELINE_DIR "${CLR_REPO_ROOT_DIR}/docs/design/datacontracts/data") - set(CONTRACT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/contracts.jsonc") - - # generate the contract descriptor by running cdac-build-tool - # n.b. this just uses `dotnet` from the PATH. InitializeDotNetCli adds the apropropriate directory - add_custom_command( - OUTPUT "${CONTRACT_DESCRIPTOR_OUTPUT}" - VERBATIM - COMMAND ${CLR_DOTNET_HOST_PATH} ${CDAC_BUILD_TOOL_BINARY_PATH} compose -i "${CONTRACT_DESCRIPTOR_INPUT}" -o "${CONTRACT_DESCRIPTOR_OUTPUT}" -b "${CONTRACT_BASELINE_DIR}" -c "${CONTRACT_FILE}" $ - DEPENDS cdac_data_descriptor cee_wks_core $ "${CONTRACT_FILE}" "${CONTRACT_DESCRIPTOR_INPUT}" - USES_TERMINAL - ) - - # It is important that cdac_contract_descriptor is an object library; - # if it was static, linking it into the final dll would not export - # DotNetRuntimeContractDescriptor since it is not referenced anywhere. - add_library_clr(cdac_contract_descriptor OBJECT - "${CONTRACT_DESCRIPTOR_OUTPUT}" - contractpointerdata.cpp - ) - target_include_directories(cdac_contract_descriptor BEFORE PRIVATE ${VM_DIR}) - target_include_directories(cdac_contract_descriptor BEFORE PRIVATE ${VM_DIR}/${ARCH_SOURCES_DIR}) - target_include_directories(cdac_contract_descriptor PRIVATE ${CLR_DIR}/interop/inc) - add_dependencies(cdac_contract_descriptor cdac_data_descriptor cee_wks_core) -endif() +add_library(runtime_descriptor_interface INTERFACE) +target_include_directories(runtime_descriptor_interface INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${VM_DIR} + ${VM_DIR}/${ARCH_SOURCES_DIR} + ${CLR_DIR}/interop/inc) +add_dependencies(runtime_descriptor_interface cee_wks_core) +generate_data_descriptors( + LIBRARY_NAME cdac_contract_descriptor + CONTRACT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/contracts.jsonc" + CONTRACT_NAME "DotNetRuntimeContractDescriptor" + INTERFACE_TARGET runtime_descriptor_interface + DLLEXPORT) \ No newline at end of file diff --git a/src/coreclr/debug/runtimeinfo/datadescriptor.h b/src/coreclr/debug/runtimeinfo/datadescriptor.h new file mode 100644 index 00000000000000..84adff2a49b4d3 --- /dev/null +++ b/src/coreclr/debug/runtimeinfo/datadescriptor.h @@ -0,0 +1,24 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include "common.h" + +#include +#include + +#include "static_assert.h" + +#include +#include "cdacplatformmetadata.hpp" +#include "methodtable.h" +#include "threads.h" +#include "vars.hpp" +#include "exinfo.h" + +#include "configure.h" + +#include "../debug/ee/debugger.h" + +#ifdef HAVE_GCCOVER +#include "gccover.h" +#endif // HAVE_GCCOVER diff --git a/src/coreclr/debug/runtimeinfo/datadescriptor.inc b/src/coreclr/debug/runtimeinfo/datadescriptor.inc index 250ac0f4f9a95b..e5de8fa6302325 100644 --- a/src/coreclr/debug/runtimeinfo/datadescriptor.inc +++ b/src/coreclr/debug/runtimeinfo/datadescriptor.inc @@ -2,108 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // // No include guards. This file is included multiple times. - -// The format is: -// CDAC_BASELINE("string") baseline data contract that the runtime should follow. "empty" is reasonable -// CDAC_TYPES_BEGIN() -// ... ... -// CDAC_TYPES_END() -// CDAC_GLOBALS_BEGIN() -// ... ... -// CDAC_GLOBALS_END() -// -// In the format is: -// CDAC_TYPE_BEGIN(cdacTypeIdentifier) // defined a new data descriptor named cdacIdentifier -// -// CDAC_TYPE_SIZE(k) -or- CDAC_TYPE_INDETERMINATE(cdacTypeIdentifier) specifies that the type has -// size k (bytes - usually sizeof(SomeNativeType)) or specify that the type's size is not provided -// It is important that CDAC_TYPE_SIZE or CDAC_TYPE_INDETERMINATE immediately follows -// CDAC_TYPE_BEGIN -// -// CDAC_TYPE_FIELD(cdacTypeIdentifier, cdacFieldTypeIdentifier, cdacFieldName, k) specifies the -// field of "cdacTypeIdentifier" that has name cdacFieldName and has the type -// "cdacFieldtypeIdentifier" located at offset k in the type layout. k is usually -// offsetof(SomeClass, m_FieldName) if the field is public -// -// if the field is private, the convention is that SomeClass declares a friend struct -// cdac_data and provides a specialization of cdac_data with a public constexpr -// size_t member that holds the offset: -// -// class MyClass { -// private: -// void* m_myField; -// friend template cdac_data; -// }; -// template<> struct cdac_data { -// static constexpr size_t MyField = offsetof(MyClass, m_myField); -// }; -// -// then the field layout can be specified as -// CDAC_TYPE_FIELD(MyClassLayout, pointer, MyField, cdac_data::MyField) -// There can be zero or more CDAC_TYPE_FIELD entries per type layout -// For types mapping to managed objects, use exact managed type field names in the descriptor, as -// field names often can't change due to binary serialization or implicit diagnostic contracts -// -// CDAC_TYPE_END(cdacTypeIdentifier) specifies the end of the type layout for cdacTypeIdentifier -// -// In the format is: -// -// CDAC_GLOBAL(cdacGlobalName, cdacTypeIdentifier, value) -// or -// CDAC_GLOBAL_POINTER(cdacGlobalName, cdacTypeIdentifier, address) -// -// Zero or more globals can be defined -// -// if a global is given with CDAC_GLOBAL(), `value` should be a constexpr uint64_t (or convertible -// to uint64_t) for example, it can be a literal constant or a preprocessor definition -// -// if a global is a CDAC_GLOBAL_POINTER(), address should be a constexpr pointer or a constexpr -// uintptr_t -// -// // // This file is compiled using the target architecture. Preprocessor defines for the target // platform will be available. It is ok to use `#ifdef`. -#ifndef CDAC_BASELINE -#define CDAC_BASELINE(identifier) -#endif -#ifndef CDAC_TYPES_BEGIN -#define CDAC_TYPES_BEGIN() -#endif -#ifndef CDAC_TYPE_BEGIN -#define CDAC_TYPE_BEGIN(tyname) -#endif -#ifndef CDAC_TYPE_SIZE -#define CDAC_TYPE_SIZE(k) -#endif -#ifndef CDAC_TYPE_INDETERMINATE -#define CDAC_TYPE_INDETERMINATE(tyname) -#endif -#ifndef CDAC_TYPE_FIELD -#define CDAC_TYPE_FIELD(tyname,fieldtyname,fieldname,off) -#endif -#ifndef CDAC_TYPE_END -#define CDAC_TYPE_END(tyname) -#endif -#ifndef CDAC_TYPES_END -#define CDAC_TYPES_END() -#endif -#ifndef CDAC_GLOBALS_BEGIN -#define CDAC_GLOBALS_BEGIN() -#endif -#ifndef CDAC_GLOBAL -#define CDAC_GLOBAL(globalname,tyname,val) -#endif -#ifndef CDAC_GLOBAL_POINTER -#define CDAC_GLOBAL_POINTER(globalname,addr) -#endif -#ifndef CDAC_GLOBAL_STRING -#define CDAC_GLOBAL_STRING(globalname,stringval) -#endif -#ifndef CDAC_GLOBALS_END -#define CDAC_GLOBALS_END() -#endif CDAC_BASELINE("empty") CDAC_TYPES_BEGIN() @@ -1017,18 +919,4 @@ CDAC_GLOBAL(StressLogEnabled, uint8, 0) CDAC_GLOBAL_POINTER(ExecutionManagerCodeRangeMapAddress, cdac_data::CodeRangeMapAddress) CDAC_GLOBAL_POINTER(PlatformMetadata, &::g_cdacPlatformMetadata) CDAC_GLOBAL_POINTER(ProfilerControlBlock, &::g_profControlBlock) -CDAC_GLOBALS_END() - -#undef CDAC_BASELINE -#undef CDAC_TYPES_BEGIN -#undef CDAC_TYPE_BEGIN -#undef CDAC_TYPE_INDETERMINATE -#undef CDAC_TYPE_SIZE -#undef CDAC_TYPE_FIELD -#undef CDAC_TYPE_END -#undef CDAC_TYPES_END -#undef CDAC_GLOBALS_BEGIN -#undef CDAC_GLOBAL -#undef CDAC_GLOBAL_POINTER -#undef CDAC_GLOBAL_STRING -#undef CDAC_GLOBALS_END +CDAC_GLOBALS_END() \ No newline at end of file From 0216767d2b139aa323f737d995fcb179126623b9 Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 11:53:34 -0400 Subject: [PATCH 02/19] change name --- src/coreclr/clrdatadescriptors.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/clrdatadescriptors.cmake b/src/coreclr/clrdatadescriptors.cmake index fc4b4ca613bd13..99d29746bd74ef 100644 --- a/src/coreclr/clrdatadescriptors.cmake +++ b/src/coreclr/clrdatadescriptors.cmake @@ -68,7 +68,7 @@ function(generate_data_descriptors) # It is important that LIBRARY is an object library; # if it was static, linking it into the final dll would not export - # DotNetRuntimeContractDescriptor since it is not referenced anywhere. + # ${CONTRACT_NAME} since it is not referenced anywhere. add_library_clr(${LIBRARY} OBJECT "${CONTRACT_DESCRIPTOR_OUTPUT}" "${DATA_DESCRIPTOR_SHARED_SOURCE_DIR}/contractpointerdata.cpp" From e00088c8163cc03f7f16a13273408ba6291b0c76 Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 11:55:07 -0400 Subject: [PATCH 03/19] remove docs --- .../debug/datadescriptor-shared/README.md | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/src/coreclr/debug/datadescriptor-shared/README.md b/src/coreclr/debug/datadescriptor-shared/README.md index a9cb3f5890e19c..a4335cb28ed428 100644 --- a/src/coreclr/debug/datadescriptor-shared/README.md +++ b/src/coreclr/debug/datadescriptor-shared/README.md @@ -2,34 +2,6 @@ This folder contains infrastructure to create data descriptors as defined in the [data_descriptor.md](../../../../docs/design/datacontracts/data_descriptor.md). Data descriptors enable diagnostic tooling (debuggers, profilers, etc.) to understand the internal layout and structure of .NET runtime objects without requiring intimate knowledge of implementation details. - - ## Getting Started ### Quick Example From 823379a38aee2ee77abb05cf855bb78210cb7683 Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 11:57:55 -0400 Subject: [PATCH 04/19] clean-up --- src/coreclr/clrdatadescriptors.cmake | 2 +- .../contract-descriptor.c.in | 2 +- .../contractconfiguration.h.in | 2 +- .../contractdescriptorstub.c | 2 +- .../contractpointerdata.cpp | 4 +-- .../datadescriptor-shared/datadescriptor.cpp | 28 +++++++++---------- ...rwrapper.inc => wrappeddatadescriptor.inc} | 2 +- src/coreclr/debug/runtimeinfo/CMakeLists.txt | 2 +- .../debug/runtimeinfo/datadescriptor.inc | 2 +- 9 files changed, 23 insertions(+), 23 deletions(-) rename src/coreclr/debug/datadescriptor-shared/{datadescriptorwrapper.inc => wrappeddatadescriptor.inc} (98%) diff --git a/src/coreclr/clrdatadescriptors.cmake b/src/coreclr/clrdatadescriptors.cmake index 99d29746bd74ef..42bde915f72f1e 100644 --- a/src/coreclr/clrdatadescriptors.cmake +++ b/src/coreclr/clrdatadescriptors.cmake @@ -94,4 +94,4 @@ function(add_interface_library target_name interface_name) get_target_property(interface_includes ${interface_name} INTERFACE_INCLUDE_DIRECTORIES) target_include_directories(${target_name} BEFORE PRIVATE ${interface_includes}) -endfunction(add_interface_library) \ No newline at end of file +endfunction(add_interface_library) diff --git a/src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in b/src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in index 1df29d8df2f5f2..076800b2a6ccbc 100644 --- a/src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in +++ b/src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in @@ -32,4 +32,4 @@ struct ContractDescriptor CONTRACT_NAME = { .descriptor = "%%jsonDescriptor%%", .pointer_data_count = %%pointerDataCount%%, .pointer_data = &POINTER_DATA_NAME[0], -}; \ No newline at end of file +}; diff --git a/src/coreclr/debug/datadescriptor-shared/contractconfiguration.h.in b/src/coreclr/debug/datadescriptor-shared/contractconfiguration.h.in index 95e3eada4e0782..e38f320a8de5ac 100644 --- a/src/coreclr/debug/datadescriptor-shared/contractconfiguration.h.in +++ b/src/coreclr/debug/datadescriptor-shared/contractconfiguration.h.in @@ -3,4 +3,4 @@ #define POINTER_DATA_NAME @POINTER_DATA_NAME@ #define CONTRACT_NAME @CONTRACT_NAME@ -#define EXPORT_CONTRACT @EXPORT_CONTRACT@ \ No newline at end of file +#define EXPORT_CONTRACT @EXPORT_CONTRACT@ diff --git a/src/coreclr/debug/datadescriptor-shared/contractdescriptorstub.c b/src/coreclr/debug/datadescriptor-shared/contractdescriptorstub.c index 9494db3e66a703..bc82ff0ab67536 100644 --- a/src/coreclr/debug/datadescriptor-shared/contractdescriptorstub.c +++ b/src/coreclr/debug/datadescriptor-shared/contractdescriptorstub.c @@ -37,4 +37,4 @@ DLLEXPORT struct ContractDescriptor CONTRACT_NAME = { .descriptor = STUB_DESCRIPTOR, .pointer_data_count = 1, .pointer_data = &POINTER_DATA_NAME[0], -}; \ No newline at end of file +}; diff --git a/src/coreclr/debug/datadescriptor-shared/contractpointerdata.cpp b/src/coreclr/debug/datadescriptor-shared/contractpointerdata.cpp index 317e3e87b44007..9e1c9929aa41df 100644 --- a/src/coreclr/debug/datadescriptor-shared/contractpointerdata.cpp +++ b/src/coreclr/debug/datadescriptor-shared/contractpointerdata.cpp @@ -13,6 +13,6 @@ const uintptr_t POINTER_DATA_NAME[] = { (uintptr_t)0, // placeholder #define CDAC_GLOBAL_POINTER(name,value) (uintptr_t)(value), #define CDAC_GLOBAL_SUB_DESCRIPTOR(name,value) (uintptr_t)(value), -#include "datadescriptorwrapper.inc" +#include "wrappeddatadescriptor.inc" }; -} \ No newline at end of file +} diff --git a/src/coreclr/debug/datadescriptor-shared/datadescriptor.cpp b/src/coreclr/debug/datadescriptor-shared/datadescriptor.cpp index 9b84cc413bc3a9..0e3332539df9ec 100644 --- a/src/coreclr/debug/datadescriptor-shared/datadescriptor.cpp +++ b/src/coreclr/debug/datadescriptor-shared/datadescriptor.cpp @@ -70,7 +70,7 @@ struct CDacStringPoolSizes #define CDAC_GLOBAL_POINTER(name,value) DECL_LEN(MAKE_GLOBALLEN_NAME(name), sizeof(#name)) #define CDAC_GLOBAL(name,tyname,value) DECL_LEN(MAKE_GLOBALLEN_NAME(name), sizeof(#name)) \ DECL_LEN(MAKE_GLOBALTYPELEN_NAME(name), sizeof(#tyname)) -#include "datadescriptorwrapper.inc" +#include "wrappeddatadescriptor.inc" char cdac_string_pool_trailing_nil; #undef DECL_LEN }; @@ -88,7 +88,7 @@ enum CDacBlobTypesCount = #define CDAC_TYPES_BEGIN() 0 #define CDAC_TYPE_BEGIN(name) + 1 -#include "datadescriptorwrapper.inc" +#include "wrappeddatadescriptor.inc" }; // count the field pool size. @@ -99,7 +99,7 @@ enum #define CDAC_TYPES_BEGIN() 1 #define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) + 1 #define CDAC_TYPE_END(name) + 1 -#include "datadescriptorwrapper.inc" +#include "wrappeddatadescriptor.inc" }; // count the literal globals @@ -108,7 +108,7 @@ enum CDacBlobGlobalLiteralsCount = #define CDAC_GLOBALS_BEGIN() 0 #define CDAC_GLOBAL(name,tyname,value) + 1 -#include "datadescriptorwrapper.inc" +#include "wrappeddatadescriptor.inc" }; // count the aux vector globals @@ -117,7 +117,7 @@ enum CDacBlobGlobalPointersCount = #define CDAC_GLOBALS_BEGIN() 0 #define CDAC_GLOBAL_POINTER(name,value) + 1 -#include "datadescriptorwrapper.inc" +#include "wrappeddatadescriptor.inc" }; // count the global strings @@ -126,7 +126,7 @@ enum CDacBlobGlobalStringsCount = #define CDAC_GLOBALS_BEGIN() 0 #define CDAC_GLOBAL_STRING(name,value) + 1 -#include "datadescriptorwrapper.inc" +#include "wrappeddatadescriptor.inc" }; @@ -156,7 +156,7 @@ struct CDacFieldsPoolSizes #define CDAC_TYPE_FIELD(tyname,membertyname,membername,offset) DECL_LEN(CONCAT4(cdac_fields_pool_member__, tyname, __, membername)) #define CDAC_TYPE_END(name) DECL_LEN(CONCAT4(cdac_fields_pool_member__, tyname, _, endmarker)) \ } MAKE_TYPEFIELDS_TYNAME(name); -#include "datadescriptorwrapper.inc" +#include "wrappeddatadescriptor.inc" #undef DECL_LEN }; @@ -178,7 +178,7 @@ struct CDacGlobalPointerIndex #define DECL_LEN(membername) char membername; #define CDAC_GLOBALS_BEGIN() DECL_LEN(cdac_global_pointer_index_start_placeholder__) #define CDAC_GLOBAL_POINTER(name,value) DECL_LEN(CONCAT(cdac_global_pointer_index__, name)) -#include "datadescriptorwrapper.inc" +#include "wrappeddatadescriptor.inc" #undef DECL_LEN }; @@ -276,7 +276,7 @@ struct MagicAndBlob BlobDataDescriptor = { #define CDAC_TYPE_INDETERMINATE(name) /*.Size = */ 0, #define CDAC_TYPE_SIZE(size) /* .Size = */ size, #define CDAC_TYPE_END(name) }, -#include "datadescriptorwrapper.inc" +#include "wrappeddatadescriptor.inc" }, /* .FieldsPool = */ { @@ -287,22 +287,22 @@ struct MagicAndBlob BlobDataDescriptor = { /* .FieldOffset = */ offset, \ }, #define CDAC_TYPE_END(name) { 0, }, -#include "datadescriptorwrapper.inc" +#include "wrappeddatadescriptor.inc" }, /* .GlobalLiteralValues = */ { #define CDAC_GLOBAL(name,tyname,value) { /*.Name = */ GET_GLOBAL_NAME(name), /* .TypeName = */ GET_GLOBALTYPE_NAME(name), /* .Value = */ value }, -#include "datadescriptorwrapper.inc" +#include "wrappeddatadescriptor.inc" }, /* .GlobalPointerValues = */ { #define CDAC_GLOBAL_POINTER(name,value) { /* .Name = */ GET_GLOBAL_NAME(name), /* .PointerDataIndex = */ GET_GLOBAL_POINTER_INDEX(name) }, -#include "datadescriptorwrapper.inc" +#include "wrappeddatadescriptor.inc" }, /* .GlobalStringValues = */ { #define CDAC_GLOBAL_STRING(name,value) { /* .Name = */ GET_GLOBAL_NAME(name), /* .Value = */ GET_GLOBALSTRING_VALUE(name) }, -#include "datadescriptorwrapper.inc" +#include "wrappeddatadescriptor.inc" }, /* .NamesPool = */ ("\0" // starts with a nul @@ -312,7 +312,7 @@ struct MagicAndBlob BlobDataDescriptor = { #define CDAC_GLOBAL_STRING(name,value) #name "\0" STRINGIFY(value) "\0" #define CDAC_GLOBAL_POINTER(name,value) #name "\0" #define CDAC_GLOBAL(name,tyname,value) #name "\0" #tyname "\0" -#include "datadescriptorwrapper.inc" +#include "wrappeddatadescriptor.inc" ), /* .EndMagic = */ { 0x01, 0x02, 0x03, 0x04 }, diff --git a/src/coreclr/debug/datadescriptor-shared/datadescriptorwrapper.inc b/src/coreclr/debug/datadescriptor-shared/wrappeddatadescriptor.inc similarity index 98% rename from src/coreclr/debug/datadescriptor-shared/datadescriptorwrapper.inc rename to src/coreclr/debug/datadescriptor-shared/wrappeddatadescriptor.inc index adca117c6d7384..05de094383e543 100644 --- a/src/coreclr/debug/datadescriptor-shared/datadescriptorwrapper.inc +++ b/src/coreclr/debug/datadescriptor-shared/wrappeddatadescriptor.inc @@ -56,4 +56,4 @@ #undef CDAC_GLOBAL_POINTER #undef CDAC_GLOBAL_STRING #undef CDAC_GLOBAL_SUB_DESCRIPTOR -#undef CDAC_GLOBALS_END \ No newline at end of file +#undef CDAC_GLOBALS_END diff --git a/src/coreclr/debug/runtimeinfo/CMakeLists.txt b/src/coreclr/debug/runtimeinfo/CMakeLists.txt index 127426b4f80749..1ca807abee0289 100644 --- a/src/coreclr/debug/runtimeinfo/CMakeLists.txt +++ b/src/coreclr/debug/runtimeinfo/CMakeLists.txt @@ -59,4 +59,4 @@ generate_data_descriptors( CONTRACT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/contracts.jsonc" CONTRACT_NAME "DotNetRuntimeContractDescriptor" INTERFACE_TARGET runtime_descriptor_interface - DLLEXPORT) \ No newline at end of file + DLLEXPORT) diff --git a/src/coreclr/debug/runtimeinfo/datadescriptor.inc b/src/coreclr/debug/runtimeinfo/datadescriptor.inc index e5de8fa6302325..167c581cf9e2d3 100644 --- a/src/coreclr/debug/runtimeinfo/datadescriptor.inc +++ b/src/coreclr/debug/runtimeinfo/datadescriptor.inc @@ -919,4 +919,4 @@ CDAC_GLOBAL(StressLogEnabled, uint8, 0) CDAC_GLOBAL_POINTER(ExecutionManagerCodeRangeMapAddress, cdac_data::CodeRangeMapAddress) CDAC_GLOBAL_POINTER(PlatformMetadata, &::g_cdacPlatformMetadata) CDAC_GLOBAL_POINTER(ProfilerControlBlock, &::g_profControlBlock) -CDAC_GLOBALS_END() \ No newline at end of file +CDAC_GLOBALS_END() From 5f77536bd780efac68c94cf1e2977a24cba6c82f Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 11:59:29 -0400 Subject: [PATCH 05/19] clean up --- src/coreclr/debug/datadescriptor-shared/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreclr/debug/datadescriptor-shared/README.md b/src/coreclr/debug/datadescriptor-shared/README.md index a4335cb28ed428..a54bee40c3d654 100644 --- a/src/coreclr/debug/datadescriptor-shared/README.md +++ b/src/coreclr/debug/datadescriptor-shared/README.md @@ -6,7 +6,7 @@ This folder contains infrastructure to create data descriptors as defined in the ### Quick Example -Here's how to create a simple data descriptor for a new runtime component: +Here's how to create a simple data descriptor: **1. Create the required files:** @@ -76,7 +76,7 @@ The `generate_data_descriptors` function defined in `clrdatadescriptors.cmake` t ### Two-Phase Build Process -The build system uses a sophisticated two-phase approach: +The build system uses a two-phase approach: **Phase 1: Intermediary Library** - Compiles `datadescriptor.cpp` with your `datadescriptor.h` and `datadescriptor.inc` @@ -143,9 +143,9 @@ The build system uses a sophisticated two-phase approach: - `stringValue` must be a compile-time string literal -## Reference Implementation +## Current Implementation -For comprehensive examples, see the current implementation in: +For reference, see the current implementation in: - **`src/coreclr/debug/runtimeinfo/`** - Complete real-world implementation - `datadescriptor.h` - Headers and includes - `datadescriptor.inc` - Full type definitions for runtime objects From bec16e6343a46beb9432e51a89ae4d64ef09445a Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 12:01:49 -0400 Subject: [PATCH 06/19] trim docs --- .../debug/datadescriptor-shared/README.md | 60 ------------------- 1 file changed, 60 deletions(-) diff --git a/src/coreclr/debug/datadescriptor-shared/README.md b/src/coreclr/debug/datadescriptor-shared/README.md index a54bee40c3d654..8581e07fd83d54 100644 --- a/src/coreclr/debug/datadescriptor-shared/README.md +++ b/src/coreclr/debug/datadescriptor-shared/README.md @@ -2,66 +2,6 @@ This folder contains infrastructure to create data descriptors as defined in the [data_descriptor.md](../../../../docs/design/datacontracts/data_descriptor.md). Data descriptors enable diagnostic tooling (debuggers, profilers, etc.) to understand the internal layout and structure of .NET runtime objects without requiring intimate knowledge of implementation details. -## Getting Started - -### Quick Example - -Here's how to create a simple data descriptor: - -**1. Create the required files:** - -``` -your_component/ -├── CMakeLists.txt -├── datadescriptor.h -├── datadescriptor.inc -└── contracts.jsonc -``` - -**2. Define your data descriptor (`datadescriptor.inc`):** - -```cpp -CDAC_BASELINE("empty") -CDAC_TYPES_BEGIN() - -CDAC_TYPE_BEGIN(MyRuntimeObject) -CDAC_TYPE_SIZE(sizeof(MyRuntimeObject)) -CDAC_TYPE_FIELD(MyRuntimeObject, uint32, Id, offsetof(MyRuntimeObject, m_id)) -CDAC_TYPE_FIELD(MyRuntimeObject, pointer, NextObject, offsetof(MyRuntimeObject, m_next)) -CDAC_TYPE_END(MyRuntimeObject) - -CDAC_TYPES_END() -CDAC_GLOBALS_BEGIN() - -CDAC_GLOBAL(g_MyGlobalCounter, uint32, g_myGlobalCounter) - -CDAC_GLOBALS_END() -``` - -**3. Create the header file (`datadescriptor.h`):** - -```cpp -#include "my_runtime_object.h" // Your actual runtime structures -``` - -**4. Add CMake integration (`CMakeLists.txt`):** - -```cmake -add_library(my_component_interface INTERFACE) -target_include_directories(my_component_interface INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR} - # include dirs here) -generate_data_descriptors( - LIBRARY_NAME my_component_contract_descriptor - CONTRACT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/contracts.jsonc" - CONTRACT_NAME "MyComponentContractDescriptor" - INTERFACE_TARGET my_component_interface - DLLEXPORT -) -``` - -Then the output object library `my_component_contract_descriptor` can be linked into the shipping dll. - ## CMake Integration and Build System ### Function Parameters From 61698e137bca8b938b401d22fc4c169ced526785 Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 12:05:40 -0400 Subject: [PATCH 07/19] fix --- src/coreclr/debug/datadescriptor-shared/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/debug/datadescriptor-shared/README.md b/src/coreclr/debug/datadescriptor-shared/README.md index 8581e07fd83d54..8066a85727a5e3 100644 --- a/src/coreclr/debug/datadescriptor-shared/README.md +++ b/src/coreclr/debug/datadescriptor-shared/README.md @@ -95,5 +95,5 @@ For reference, see the current implementation in: ## Related Documentation - **[Data Contracts Design](../../../../docs/design/datacontracts/datacontracts_design.md)** - Overall design and motivation -- **[Contract Descriptor](../../../../docs/design/datacontracts/contract-descriptor.md)** - Binary format specification +- **[Contract Descriptor](../../../../docs/design/datacontracts/contract-descriptor.md)** - Binary format specification - **[Data Descriptor](../../../../docs/design/datacontracts/data_descriptor.md)** - Logical format specification From 972813906740dc062f036fbb67a9415ac7c4d9de Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 12:15:03 -0400 Subject: [PATCH 08/19] doc --- .../debug/datadescriptor-shared/wrappeddatadescriptor.inc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/coreclr/debug/datadescriptor-shared/wrappeddatadescriptor.inc b/src/coreclr/debug/datadescriptor-shared/wrappeddatadescriptor.inc index 05de094383e543..abb73293885cb9 100644 --- a/src/coreclr/debug/datadescriptor-shared/wrappeddatadescriptor.inc +++ b/src/coreclr/debug/datadescriptor-shared/wrappeddatadescriptor.inc @@ -1,3 +1,9 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// No include guards. This file is included multiple times. +// Wraps datadescriptor.inc to define and undefine macros used in the file. + #ifndef CDAC_BASELINE #define CDAC_BASELINE(identifier) #endif From 4698361abd88b1a1fff16f6b175d8838e9c7844e Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 14:41:36 -0400 Subject: [PATCH 09/19] rename DLLEXPORT -> EXPORT_VISIBLE --- src/coreclr/clrdatadescriptors.cmake | 4 ++-- src/coreclr/debug/datadescriptor-shared/README.md | 2 +- src/coreclr/debug/runtimeinfo/CMakeLists.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreclr/clrdatadescriptors.cmake b/src/coreclr/clrdatadescriptors.cmake index 42bde915f72f1e..4b9ddcddb6188b 100644 --- a/src/coreclr/clrdatadescriptors.cmake +++ b/src/coreclr/clrdatadescriptors.cmake @@ -1,7 +1,7 @@ # cDAC contract descriptor function(generate_data_descriptors) - set(options DLLEXPORT) + set(options EXPORT_VISIBLE) set(oneValueArgs LIBRARY_NAME CONTRACT_FILE CONTRACT_NAME INTERFACE_TARGET) set(multiValueArgs "") cmake_parse_arguments(DATA_DESCRIPTORS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGV}) @@ -16,7 +16,7 @@ function(generate_data_descriptors) # configure contract export name set(POINTER_DATA_NAME ${DATA_DESCRIPTORS_CONTRACT_NAME}PointerData) set(CONTRACT_NAME ${DATA_DESCRIPTORS_CONTRACT_NAME}) - if (DATA_DESCRIPTORS_DLLEXPORT) + if (DATA_DESCRIPTORS_EXPORT_VISIBLE) set(EXPORT_CONTRACT 1) else() set(EXPORT_CONTRACT 0) diff --git a/src/coreclr/debug/datadescriptor-shared/README.md b/src/coreclr/debug/datadescriptor-shared/README.md index 8066a85727a5e3..41fba1319161fe 100644 --- a/src/coreclr/debug/datadescriptor-shared/README.md +++ b/src/coreclr/debug/datadescriptor-shared/README.md @@ -12,7 +12,7 @@ The `generate_data_descriptors` function defined in `clrdatadescriptors.cmake` t * **`CONTRACT_FILE`** (Required) - Path to the contract JSON file defining supported contracts * **`CONTRACT_NAME`** (Required) - Name of the `ContractDescriptor` export symbol * **`INTERFACE_TARGET`** (Required) - Interface target providing dependencies, include directories, and definitions -* **`DLLEXPORT`** (Optional) - Controls if the `CONTRACT_NAME` will be exported from the DLL +* **`EXPORT_VISIBLE`** (Optional) - Controls if the `CONTRACT_NAME` will be exported from the DLL ### Two-Phase Build Process diff --git a/src/coreclr/debug/runtimeinfo/CMakeLists.txt b/src/coreclr/debug/runtimeinfo/CMakeLists.txt index 1ca807abee0289..0f00e86523284e 100644 --- a/src/coreclr/debug/runtimeinfo/CMakeLists.txt +++ b/src/coreclr/debug/runtimeinfo/CMakeLists.txt @@ -59,4 +59,4 @@ generate_data_descriptors( CONTRACT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/contracts.jsonc" CONTRACT_NAME "DotNetRuntimeContractDescriptor" INTERFACE_TARGET runtime_descriptor_interface - DLLEXPORT) + EXPORT_VISIBLE) From 378a71f2dbec82355cc7561e0b71330a0d452600 Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 14:42:04 -0400 Subject: [PATCH 10/19] fix license --- src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in b/src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in index 076800b2a6ccbc..2c01200926e5d9 100644 --- a/src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in +++ b/src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in @@ -1,3 +1,4 @@ +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #include From 8f138338f10846df2fe45f9f305c6476b5dfbc78 Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 14:42:11 -0400 Subject: [PATCH 11/19] add comment --- src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in | 1 + src/coreclr/debug/datadescriptor-shared/contractdescriptorstub.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in b/src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in index 2c01200926e5d9..53c2450d11d775 100644 --- a/src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in +++ b/src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in @@ -21,6 +21,7 @@ struct ContractDescriptor const uintptr_t *pointer_data; }; +// POINTER_DATA_NAME and CONTRACT_NAME are macros provided by contractconfiguration.h extern const uintptr_t POINTER_DATA_NAME[]; #if EXPORT_CONTRACT diff --git a/src/coreclr/debug/datadescriptor-shared/contractdescriptorstub.c b/src/coreclr/debug/datadescriptor-shared/contractdescriptorstub.c index bc82ff0ab67536..3848d03a3d7a56 100644 --- a/src/coreclr/debug/datadescriptor-shared/contractdescriptorstub.c +++ b/src/coreclr/debug/datadescriptor-shared/contractdescriptorstub.c @@ -21,6 +21,7 @@ struct ContractDescriptor const uintptr_t *pointer_data; }; +// POINTER_DATA_NAME and CONTRACT_NAME are macros provided by contractconfiguration.h extern const uintptr_t POINTER_DATA_NAME[]; // just the placeholder pointer From 8a6a118fe380eb6e5dbe54a0df87a0828741f435 Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 14:50:33 -0400 Subject: [PATCH 12/19] rename add_interface_library -> _add_interface_library_before --- src/coreclr/clrdatadescriptors.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreclr/clrdatadescriptors.cmake b/src/coreclr/clrdatadescriptors.cmake index 4b9ddcddb6188b..e44089284c5e93 100644 --- a/src/coreclr/clrdatadescriptors.cmake +++ b/src/coreclr/clrdatadescriptors.cmake @@ -49,7 +49,7 @@ function(generate_data_descriptors) endif() # inherit definitions, include directories, and dependencies from the INTERFACE target - add_interface_library(${INTERMEDIARY_LIBRARY} ${DATA_DESCRIPTORS_INTERFACE_TARGET}) + _add_interface_library_before(${INTERMEDIARY_LIBRARY} ${DATA_DESCRIPTORS_INTERFACE_TARGET}) set(CONTRACT_BASELINE_DIR "${CLR_REPO_ROOT_DIR}/docs/design/datacontracts/data") set(CONTRACT_DESCRIPTOR_INPUT "${DATA_DESCRIPTOR_SHARED_SOURCE_DIR}/contract-descriptor.c.in") @@ -81,17 +81,17 @@ function(generate_data_descriptors) ) # inherit definitions, include directories, and dependencies from the INTERFACE target - add_interface_library(${LIBRARY} ${DATA_DESCRIPTORS_INTERFACE_TARGET}) + _add_interface_library_before(${LIBRARY} ${DATA_DESCRIPTORS_INTERFACE_TARGET}) endif() endfunction(generate_data_descriptors) # Links in an interface to a target with the interface include directories included # before the targets include directories. -function(add_interface_library target_name interface_name) +function(_add_interface_library_before target_name interface_name) get_target_property(target_includes ${target_name} INCLUDE_DIRECTORIES) target_link_libraries(${target_name} PRIVATE ${interface_name}) set_target_properties(${target_name} PROPERTIES INCLUDE_DIRECTORIES "${target_includes}") get_target_property(interface_includes ${interface_name} INTERFACE_INCLUDE_DIRECTORIES) target_include_directories(${target_name} BEFORE PRIVATE ${interface_includes}) -endfunction(add_interface_library) +endfunction(_add_interface_library_before) From e61c682e847e1fe1f326fc9e788663a5fa9b07d8 Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 14:51:46 -0400 Subject: [PATCH 13/19] remove sub_descriptor reference from PR --- .../debug/datadescriptor-shared/wrappeddatadescriptor.inc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/coreclr/debug/datadescriptor-shared/wrappeddatadescriptor.inc b/src/coreclr/debug/datadescriptor-shared/wrappeddatadescriptor.inc index abb73293885cb9..7500ac93388803 100644 --- a/src/coreclr/debug/datadescriptor-shared/wrappeddatadescriptor.inc +++ b/src/coreclr/debug/datadescriptor-shared/wrappeddatadescriptor.inc @@ -40,9 +40,6 @@ #ifndef CDAC_GLOBAL_STRING #define CDAC_GLOBAL_STRING(globalname,stringval) #endif -#ifndef CDAC_GLOBAL_SUB_DESCRIPTOR -#define CDAC_GLOBAL_SUB_DESCRIPTOR(globalname,addr) -#endif #ifndef CDAC_GLOBALS_END #define CDAC_GLOBALS_END() #endif @@ -61,5 +58,4 @@ #undef CDAC_GLOBAL #undef CDAC_GLOBAL_POINTER #undef CDAC_GLOBAL_STRING -#undef CDAC_GLOBAL_SUB_DESCRIPTOR #undef CDAC_GLOBALS_END From 0770a04f4c8bbaaf1e78563d7e6c54770499a600 Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 14:53:26 -0400 Subject: [PATCH 14/19] improve comment --- .../debug/datadescriptor-shared/contract-descriptor.c.in | 3 ++- .../debug/datadescriptor-shared/contractdescriptorstub.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in b/src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in index 53c2450d11d775..a728afc10dcb33 100644 --- a/src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in +++ b/src/coreclr/debug/datadescriptor-shared/contract-descriptor.c.in @@ -21,7 +21,8 @@ struct ContractDescriptor const uintptr_t *pointer_data; }; -// POINTER_DATA_NAME and CONTRACT_NAME are macros provided by contractconfiguration.h +// POINTER_DATA_NAME and CONTRACT_NAME are macros provided by +// contractconfiguration.h which is configured by CMake extern const uintptr_t POINTER_DATA_NAME[]; #if EXPORT_CONTRACT diff --git a/src/coreclr/debug/datadescriptor-shared/contractdescriptorstub.c b/src/coreclr/debug/datadescriptor-shared/contractdescriptorstub.c index 3848d03a3d7a56..6bcabd2c829618 100644 --- a/src/coreclr/debug/datadescriptor-shared/contractdescriptorstub.c +++ b/src/coreclr/debug/datadescriptor-shared/contractdescriptorstub.c @@ -21,7 +21,8 @@ struct ContractDescriptor const uintptr_t *pointer_data; }; -// POINTER_DATA_NAME and CONTRACT_NAME are macros provided by contractconfiguration.h +// POINTER_DATA_NAME and CONTRACT_NAME are macros provided by +// contractconfiguration.h which is configured by CMake extern const uintptr_t POINTER_DATA_NAME[]; // just the placeholder pointer From 291fe1941520708ac0377fc7672938b39dd08c11 Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 15:18:47 -0400 Subject: [PATCH 15/19] move datadescriptors from src/debug -> src/vm --- src/coreclr/clrdatadescriptors.cmake | 15 ++---------- src/coreclr/debug/runtimeinfo/CMakeLists.txt | 23 ------------------- src/coreclr/vm/CMakeLists.txt | 2 ++ .../datadescriptor}/.editorconfig | 0 src/coreclr/vm/datadescriptor/CMakeLists.txt | 18 +++++++++++++++ .../datadescriptor}/configure.h.in | 0 .../datadescriptor}/contracts.jsonc | 0 .../datadescriptor}/datadescriptor.h | 0 .../datadescriptor}/datadescriptor.inc | 0 9 files changed, 22 insertions(+), 36 deletions(-) rename src/coreclr/{debug/runtimeinfo => vm/datadescriptor}/.editorconfig (100%) create mode 100644 src/coreclr/vm/datadescriptor/CMakeLists.txt rename src/coreclr/{debug/runtimeinfo => vm/datadescriptor}/configure.h.in (100%) rename src/coreclr/{debug/runtimeinfo => vm/datadescriptor}/contracts.jsonc (100%) rename src/coreclr/{debug/runtimeinfo => vm/datadescriptor}/datadescriptor.h (100%) rename src/coreclr/{debug/runtimeinfo => vm/datadescriptor}/datadescriptor.inc (100%) diff --git a/src/coreclr/clrdatadescriptors.cmake b/src/coreclr/clrdatadescriptors.cmake index e44089284c5e93..b24019ff6c3a3e 100644 --- a/src/coreclr/clrdatadescriptors.cmake +++ b/src/coreclr/clrdatadescriptors.cmake @@ -49,7 +49,7 @@ function(generate_data_descriptors) endif() # inherit definitions, include directories, and dependencies from the INTERFACE target - _add_interface_library_before(${INTERMEDIARY_LIBRARY} ${DATA_DESCRIPTORS_INTERFACE_TARGET}) + target_link_libraries(${INTERMEDIARY_LIBRARY} PRIVATE ${DATA_DESCRIPTORS_INTERFACE_TARGET}) set(CONTRACT_BASELINE_DIR "${CLR_REPO_ROOT_DIR}/docs/design/datacontracts/data") set(CONTRACT_DESCRIPTOR_INPUT "${DATA_DESCRIPTOR_SHARED_SOURCE_DIR}/contract-descriptor.c.in") @@ -81,17 +81,6 @@ function(generate_data_descriptors) ) # inherit definitions, include directories, and dependencies from the INTERFACE target - _add_interface_library_before(${LIBRARY} ${DATA_DESCRIPTORS_INTERFACE_TARGET}) + target_link_libraries(${LIBRARY} PRIVATE ${DATA_DESCRIPTORS_INTERFACE_TARGET}) endif() endfunction(generate_data_descriptors) - -# Links in an interface to a target with the interface include directories included -# before the targets include directories. -function(_add_interface_library_before target_name interface_name) - get_target_property(target_includes ${target_name} INCLUDE_DIRECTORIES) - target_link_libraries(${target_name} PRIVATE ${interface_name}) - set_target_properties(${target_name} PROPERTIES INCLUDE_DIRECTORIES "${target_includes}") - - get_target_property(interface_includes ${interface_name} INTERFACE_INCLUDE_DIRECTORIES) - target_include_directories(${target_name} BEFORE PRIVATE ${interface_includes}) -endfunction(_add_interface_library_before) diff --git a/src/coreclr/debug/runtimeinfo/CMakeLists.txt b/src/coreclr/debug/runtimeinfo/CMakeLists.txt index 0f00e86523284e..b825d45cbf4747 100644 --- a/src/coreclr/debug/runtimeinfo/CMakeLists.txt +++ b/src/coreclr/debug/runtimeinfo/CMakeLists.txt @@ -37,26 +37,3 @@ endif() # publish runtimeinfo lib install_clr(TARGETS runtimeinfo DESTINATIONS lib COMPONENT runtime) - - -# cDAC contract descriptor - -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(runtime_descriptor_interface INTERFACE) -target_include_directories(runtime_descriptor_interface INTERFACE - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR} - ${VM_DIR} - ${VM_DIR}/${ARCH_SOURCES_DIR} - ${CLR_DIR}/interop/inc) -add_dependencies(runtime_descriptor_interface cee_wks_core) -generate_data_descriptors( - LIBRARY_NAME cdac_contract_descriptor - CONTRACT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/contracts.jsonc" - CONTRACT_NAME "DotNetRuntimeContractDescriptor" - INTERFACE_TARGET runtime_descriptor_interface - EXPORT_VISIBLE) diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index 07a5a36ab39e80..4baca1c50f362b 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -1013,3 +1013,5 @@ add_subdirectory(wks) if(FEATURE_PERFTRACING) add_subdirectory(eventing) endif(FEATURE_PERFTRACING) + +add_subdirectory(datadescriptor) \ No newline at end of file diff --git a/src/coreclr/debug/runtimeinfo/.editorconfig b/src/coreclr/vm/datadescriptor/.editorconfig similarity index 100% rename from src/coreclr/debug/runtimeinfo/.editorconfig rename to src/coreclr/vm/datadescriptor/.editorconfig diff --git a/src/coreclr/vm/datadescriptor/CMakeLists.txt b/src/coreclr/vm/datadescriptor/CMakeLists.txt new file mode 100644 index 00000000000000..3114d94b23d3b7 --- /dev/null +++ b/src/coreclr/vm/datadescriptor/CMakeLists.txt @@ -0,0 +1,18 @@ +# cDAC contract descriptor + +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(runtime_descriptor_interface INTERFACE) +target_include_directories(runtime_descriptor_interface INTERFACE + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}) +add_dependencies(runtime_descriptor_interface cee_wks_core) +generate_data_descriptors( + LIBRARY_NAME cdac_contract_descriptor + CONTRACT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/contracts.jsonc" + CONTRACT_NAME "DotNetRuntimeContractDescriptor" + INTERFACE_TARGET runtime_descriptor_interface + EXPORT_VISIBLE) diff --git a/src/coreclr/debug/runtimeinfo/configure.h.in b/src/coreclr/vm/datadescriptor/configure.h.in similarity index 100% rename from src/coreclr/debug/runtimeinfo/configure.h.in rename to src/coreclr/vm/datadescriptor/configure.h.in diff --git a/src/coreclr/debug/runtimeinfo/contracts.jsonc b/src/coreclr/vm/datadescriptor/contracts.jsonc similarity index 100% rename from src/coreclr/debug/runtimeinfo/contracts.jsonc rename to src/coreclr/vm/datadescriptor/contracts.jsonc diff --git a/src/coreclr/debug/runtimeinfo/datadescriptor.h b/src/coreclr/vm/datadescriptor/datadescriptor.h similarity index 100% rename from src/coreclr/debug/runtimeinfo/datadescriptor.h rename to src/coreclr/vm/datadescriptor/datadescriptor.h diff --git a/src/coreclr/debug/runtimeinfo/datadescriptor.inc b/src/coreclr/vm/datadescriptor/datadescriptor.inc similarity index 100% rename from src/coreclr/debug/runtimeinfo/datadescriptor.inc rename to src/coreclr/vm/datadescriptor/datadescriptor.inc From 0461bb380a9fe8167f4d09b2fb06542fde8e59a1 Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 15:23:23 -0400 Subject: [PATCH 16/19] undo change --- src/coreclr/debug/runtimeinfo/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coreclr/debug/runtimeinfo/CMakeLists.txt b/src/coreclr/debug/runtimeinfo/CMakeLists.txt index b825d45cbf4747..a31d4b6f9812c3 100644 --- a/src/coreclr/debug/runtimeinfo/CMakeLists.txt +++ b/src/coreclr/debug/runtimeinfo/CMakeLists.txt @@ -1,9 +1,10 @@ +set(CMAKE_INCLUDE_CURRENT_DIR ON) + set(RUNTIMEINFO_SOURCES runtimeinfo.cpp ) add_library_clr(runtimeinfo STATIC ${RUNTIMEINFO_SOURCES}) -target_include_directories(runtimeinfo PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) function(generate_module_index Target ModuleIndexFile) # Win32 may be false when cross compiling From 9182cab34b3c1471aa803ef8ece6994ffa30f373 Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 15:23:35 -0400 Subject: [PATCH 17/19] nit spacing --- src/coreclr/vm/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index 4baca1c50f362b..37f1a76d4f73a3 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -1014,4 +1014,4 @@ if(FEATURE_PERFTRACING) add_subdirectory(eventing) endif(FEATURE_PERFTRACING) -add_subdirectory(datadescriptor) \ No newline at end of file +add_subdirectory(datadescriptor) From 948efd72c4b1e193673df502be8cb33e1f54958b Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 15:24:18 -0400 Subject: [PATCH 18/19] update doc --- src/coreclr/debug/datadescriptor-shared/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/debug/datadescriptor-shared/README.md b/src/coreclr/debug/datadescriptor-shared/README.md index 41fba1319161fe..b0bb9e8e3dc1d3 100644 --- a/src/coreclr/debug/datadescriptor-shared/README.md +++ b/src/coreclr/debug/datadescriptor-shared/README.md @@ -86,7 +86,7 @@ The build system uses a two-phase approach: ## Current Implementation For reference, see the current implementation in: -- **`src/coreclr/debug/runtimeinfo/`** - Complete real-world implementation +- **`src/coreclr/vm/datadescriptor/`** - Complete real-world implementation - `datadescriptor.h` - Headers and includes - `datadescriptor.inc` - Full type definitions for runtime objects - `contracts.jsonc` - Contract definitions From 56e49ef008d744453647a3edfea4e108c5fc9ea0 Mon Sep 17 00:00:00 2001 From: maxcharlamb Date: Wed, 6 Aug 2025 15:33:40 -0400 Subject: [PATCH 19/19] remove unused includes --- src/coreclr/clrdatadescriptors.cmake | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/coreclr/clrdatadescriptors.cmake b/src/coreclr/clrdatadescriptors.cmake index b24019ff6c3a3e..21f7b1600e830b 100644 --- a/src/coreclr/clrdatadescriptors.cmake +++ b/src/coreclr/clrdatadescriptors.cmake @@ -37,7 +37,6 @@ function(generate_data_descriptors) endif() add_library(${INTERMEDIARY_LIBRARY} OBJECT "${DATA_DESCRIPTOR_SHARED_SOURCE_DIR}/datadescriptor.cpp") - target_include_directories(${INTERMEDIARY_LIBRARY} PRIVATE ${DATA_DESCRIPTOR_SHARED_SOURCE_DIR}) if(CLR_CMAKE_TARGET_WIN32) # turn off whole program optimization: @@ -75,10 +74,7 @@ function(generate_data_descriptors) ) add_dependencies(${LIBRARY} ${INTERMEDIARY_LIBRARY}) - target_include_directories(${LIBRARY} PRIVATE - ${DATA_DESCRIPTOR_SHARED_SOURCE_DIR} - ${GENERATED_CDAC_DESCRIPTOR_DIR} - ) + target_include_directories(${LIBRARY} PRIVATE ${GENERATED_CDAC_DESCRIPTOR_DIR}) # inherit definitions, include directories, and dependencies from the INTERFACE target target_link_libraries(${LIBRARY} PRIVATE ${DATA_DESCRIPTORS_INTERFACE_TARGET})