-
Notifications
You must be signed in to change notification settings - Fork 5.2k
[cDAC] Refactor datadescriptor infrastructure #118453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
max-charlamb
merged 19 commits into
dotnet:main
from
max-charlamb:datadescriptor-refactor
Aug 7, 2025
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
50f2431
refactor
max-charlamb 0216767
change name
max-charlamb e00088c
remove docs
max-charlamb 823379a
clean-up
max-charlamb 5f77536
clean up
max-charlamb bec16e6
trim docs
max-charlamb 61698e1
fix
max-charlamb 9728139
doc
max-charlamb 4698361
rename DLLEXPORT -> EXPORT_VISIBLE
max-charlamb 378a71f
fix license
max-charlamb 8f13833
add comment
max-charlamb 8a6a118
rename add_interface_library -> _add_interface_library_before
max-charlamb e61c682
remove sub_descriptor reference from PR
max-charlamb 0770a04
improve comment
max-charlamb 291fe19
move datadescriptors from src/debug -> src/vm
max-charlamb 0461bb3
undo change
max-charlamb 9182cab
nit spacing
max-charlamb 948efd7
update doc
max-charlamb 56e49ef
remove unused includes
max-charlamb File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| # cDAC contract descriptor | ||
|
|
||
| function(generate_data_descriptors) | ||
| 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}) | ||
|
|
||
| # 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_EXPORT_VISIBLE) | ||
| 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") | ||
|
|
||
| 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 | ||
| 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") | ||
| 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}" $<TARGET_OBJECTS:${INTERMEDIARY_LIBRARY}> | ||
| DEPENDS ${INTERMEDIARY_LIBRARY} ${DATA_DESCRIPTORS_DEPENDENCIES} $<TARGET_OBJECTS:${INTERMEDIARY_LIBRARY}> "${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 | ||
| # ${CONTRACT_NAME} 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 ${GENERATED_CDAC_DESCRIPTOR_DIR}) | ||
|
|
||
| # inherit definitions, include directories, and dependencies from the INTERFACE target | ||
| target_link_libraries(${LIBRARY} PRIVATE ${DATA_DESCRIPTORS_INTERFACE_TARGET}) | ||
| endif() | ||
| endfunction(generate_data_descriptors) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| # 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. | ||
|
|
||
| ## 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 | ||
| * **`EXPORT_VISIBLE`** (Optional) - Controls if the `CONTRACT_NAME` will be exported from the DLL | ||
|
|
||
| ### Two-Phase Build Process | ||
|
|
||
| The build system uses a 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<T>::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 | ||
|
|
||
|
|
||
| ## Current Implementation | ||
|
|
||
| For reference, see the current implementation in: | ||
| - **`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 | ||
| - `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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
src/coreclr/debug/datadescriptor-shared/contractconfiguration.h.in
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| #pragma once | ||
|
|
||
| #define POINTER_DATA_NAME @POINTER_DATA_NAME@ | ||
| #define CONTRACT_NAME @CONTRACT_NAME@ | ||
|
|
||
| #define EXPORT_CONTRACT @EXPORT_CONTRACT@ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 6 additions & 12 deletions
18
...debug/runtimeinfo/contractpointerdata.cpp → ...descriptor-shared/contractpointerdata.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 <stddef.h> | ||
| #include <stdint.h> | ||
|
|
||
| #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 "wrappeddatadescriptor.inc" | ||
| }; | ||
|
|
||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.