Skip to content

Commit 2999b70

Browse files
lambdageekelinor-fungAaronRobinsonMSFT
authored andcommitted
[cdac] cdac-build-tool (dotnet#100650)
# cDAC Build Tool ## Summary The purpose of `cdac-build-tool` is to generate a `.c` file that contains a JSON cDAC contract descriptor. It works by processing one or more object files containing data descriptors and zero or more text files that specify contracts. ## Running ```console % cdac-build-tool compose [-v] -o contractdescriptor.c -c contracts.txt datadescriptor.o ``` ## .NET runtime build integration `cdac-build-tool` is meant to run as a CMake custom command. It consumes a target platform object file and emits a C source file that contains a JSON contract descriptor. The C source is the included in the normal build and link steps to create the runtime. The contract descriptor source file depends on `contract-aux-data.c` which is a source file that contains the definitions of the "indirect pointer data" that is referenced by the data descriptor. This is typically the addresses of important global variables in the runtime. Constants and build flags are embedded directly in the JSON payload. Multiple data descriptor source files may be specified (for example if they are produced by different components of the runtime, or by different source languages). The final JSON payload will be a composition of all the data descriptors. Multiple contracts text files may be specified. This may be useful if some contracts are conditionally included (for example if they are platform-specific). The final JSON payload will be a composition of all the contracts files. ```mermaid flowchart TB headers("runtime headers") data_header("datadescriptor.h") data_src("datadescriptor.c") compile_data["clang"] data_obj("datadescriptor.o") contracts("contracts.txt") globals("contractpointerdata.c") build[["cdac-build-tool"]] descriptor_src("contractdescriptor.c") vm("runtime sources") compile_runtime["clang"] runtime_lib(["libcoreclr.so"]) headers -.-> data_src headers ~~~ data_header data_header -.-> data_src headers -.-> globals headers -.-> vm data_src --> compile_data --> data_obj --> build contracts ---> build build --> descriptor_src descriptor_src --> compile_runtime data_header -.-> globals ----> compile_runtime vm ----> compile_runtime --> runtime_lib ``` --- * add implementation note notes * add an emitter * read in the directory header * contract parsing * indirect pointer value support * move sample to tool dir * Take baselines from the docs/design/datacontracts/data dir We don't parse them yet, however * Add README * fix BE Store the magic as a uint64_t so that it will follow the platform endianness. Store endmagic as bytes so that it directly follows the name pool - and fix the endmagic check not to look at the endianness * hook up cdac-build-tool to the coreclr build; export DotNetRuntimeContractDescriptor * cleanup; add contracts.txt * add diagram to README * move implementation notes * better verbose output from ObjectFileScraper * turn off whole program optimizations for data-descriptor.obj On windows /GL creates object files that cdac-build-tool cannot read It's ok to do this because we don't ship data-descriptor.obj as part of the product - it's only used to generate the cDAC descriptor * C++-ify and add real Thread offsets * no C99 designated initializers in C++ until C++20 * build data descriptor after core runtime * fix gcc build * simplify ObjectFileScraper just read the whole file into memory * invoke 'dotnet cmake-build-tool.dll' instead of 'dotnet run --project' * clean up macro boilerplate * platform flags * turn off verbose output * can't use constexpr function in coreclr because debugreturn.h defines a `return` macro that expands to something that is not c++11 constexpr * Rename "aux data" to "pointer data" * rename "data-descriptor" to "datadescriptor" * simplify linking * cdac-build-tool don't build dotnet tool; turn on analyzers * rationalize naming; update docs; add some inline comments * renamce cdac.h to cdacoffsets.h * improve output: hex offsets; improved formatting * don't throw in ParseContracts; add line numbers to errors * change input format for contracts to jsonc * add custom JsonConverter instances for the compact json representation * simplify; bug fix - PointerDataCount include placeholder * one more set of feedback changes: simpler json converters * set _RequiresLiveILLink=false for cdac-build-tool.csproj fixes windows builds: error MSB3026: (NETCORE_ENGINEERING_TELEMETRY=Build) Could not copy "D:\a\_work\1\s\artifacts\obj\ILLink.Tasks\Debug\net9.0\ILLink.Tasks.dll" to "D:\a\_work\1\s\artifacts\bin\ILLink.Tasks\Debug\net9.0\ILLink.Tasks.dll". Beginning retry 1 in 1000ms. The process cannot access the file 'D:\a\_work\1\s\artifacts\bin\ILLink.Tasks\Debug\net9.0\ILLink.Tasks.dll' because it is being used by another process. --------- Co-authored-by: Elinor Fung <elfung@microsoft.com> Co-authored-by: Aaron Robinson <arobins@microsoft.com>
1 parent eb344fe commit 2999b70

37 files changed

+2880
-2
lines changed

docs/design/datacontracts/contract-descriptor.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ struct DotNetRuntimeContractDescriptor
2424
uint32_t flags;
2525
uint32_t descriptor_size;
2626
const char *descriptor;
27-
uint32_t aux_data_count;
27+
uint32_t pointer_data_count;
2828
uint32_t pad0;
29-
uintptr_t *aux_data;
29+
uintptr_t *pointer_data;
3030
};
3131
```
3232

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// the empty baseline data descriptor
2+
{
3+
"version": 0
4+
}

eng/Subsets.props

+2
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,8 @@
360360
<ProjectToBuild Include="$(CoreClrProjectRoot)tools\aot\crossgen2\crossgen2_inbuild.csproj" Category="clr" />
361361

362362
<ProjectToBuild Condition="'$(TargetOS)' == 'windows' or ('$(TargetOS)' == 'linux' and ('$(TargetArchitecture)' == 'x64' or '$(TargetArchitecture)' == 'arm64')) or '$(TargetOS)' == 'osx'" Include="$(CoreClrProjectRoot)tools\SuperFileCheck\SuperFileCheck.csproj" Category="clr" />
363+
364+
<ProjectToBuild Include="$(CoreClrProjectRoot)tools\cdac-build-tool\cdac-build-tool.csproj" Category="clr" />
363365
</ItemGroup>
364366

365367
<ItemGroup Condition="$(_subset.Contains('+clr.toolstests+'))">

src/coreclr/debug/runtimeinfo/CMakeLists.txt

+43
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,46 @@ endif()
3737

3838
# publish runtimeinfo lib
3939
install_clr(TARGETS runtimeinfo DESTINATIONS lib COMPONENT runtime)
40+
41+
add_library(cdac_data_descriptor OBJECT datadescriptor.cpp)
42+
# don't build the data descriptor before the VM (and any of its dependencies' generated headers)
43+
add_dependencies(cdac_data_descriptor cee_wks_core)
44+
if(CLR_CMAKE_TARGET_WIN32)
45+
# turn off whole program optimization:
46+
# 1. it creates object files that cdac-build-tool can't read
47+
# 2. we never link cdac_data_descriptor into the final product - it's only job is to be scraped
48+
target_compile_options(cdac_data_descriptor PRIVATE /GL-)
49+
endif()
50+
target_include_directories(cdac_data_descriptor BEFORE PRIVATE ${VM_DIR})
51+
target_include_directories(cdac_data_descriptor BEFORE PRIVATE ${VM_DIR}/${ARCH_SOURCES_DIR})
52+
target_include_directories(cdac_data_descriptor PRIVATE ${CLR_DIR}/interop/inc)
53+
54+
set(GENERATED_CDAC_DESCRIPTOR_DIR "${CMAKE_CURRENT_BINARY_DIR}/cdac")
55+
set(CONTRACT_DESCRIPTOR_OUTPUT "${GENERATED_CDAC_DESCRIPTOR_DIR}/contract-descriptor.c")
56+
if("${CDAC_BUILD_TOOL_BINARY_PATH}" STREQUAL "" OR NOT EXISTS "${CDAC_BUILD_TOOL_BINARY_PATH}")
57+
message(FATAL_ERROR "No cdac-build-tool set or ${CDAC_BUILD_TOOL_BINARY_PATH} does not exist")
58+
endif()
59+
60+
set(CONTRACT_FILE "${CMAKE_CURRENT_SOURCE_DIR}/contracts.jsonc")
61+
62+
# generate the contract descriptor by running cdac-build-tool
63+
# n.b. this just uses `dotnet` from the PATH. InitializeDotNetCli adds the apropropriate directory
64+
add_custom_command(
65+
OUTPUT "${CONTRACT_DESCRIPTOR_OUTPUT}"
66+
VERBATIM
67+
COMMAND dotnet ${CDAC_BUILD_TOOL_BINARY_PATH} compose -o "${CONTRACT_DESCRIPTOR_OUTPUT}" -c "${CONTRACT_FILE}" $<TARGET_OBJECTS:cdac_data_descriptor>
68+
DEPENDS cdac_data_descriptor cee_wks_core $<TARGET_OBJECTS:cdac_data_descriptor> "${CONTRACT_FILE}"
69+
USES_TERMINAL
70+
)
71+
72+
# It is important that cdac_contract_descriptor is an object library;
73+
# if it was static, linking it into the final dll would not export
74+
# DotNetRuntimeContractDescriptor since it is not referenced anywhere.
75+
add_library_clr(cdac_contract_descriptor OBJECT
76+
"${CONTRACT_DESCRIPTOR_OUTPUT}"
77+
contractpointerdata.cpp
78+
)
79+
target_include_directories(cdac_contract_descriptor BEFORE PRIVATE ${VM_DIR})
80+
target_include_directories(cdac_contract_descriptor BEFORE PRIVATE ${VM_DIR}/${ARCH_SOURCES_DIR})
81+
target_include_directories(cdac_contract_descriptor PRIVATE ${CLR_DIR}/interop/inc)
82+
add_dependencies(cdac_contract_descriptor cdac_data_descriptor cee_wks_core)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
#include "common.h"
5+
6+
#include <stddef.h>
7+
#include <stdint.h>
8+
9+
#include "threads.h"
10+
11+
extern "C"
12+
{
13+
14+
// without an extern declaration, clang does not emit this global into the object file
15+
extern const uintptr_t contractDescriptorPointerData[];
16+
17+
const uintptr_t contractDescriptorPointerData[] = {
18+
(uintptr_t)0, // placeholder
19+
#define CDAC_GLOBAL_POINTER(name,value) (uintptr_t)(value),
20+
#include "datadescriptor.h"
21+
};
22+
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//algorithmic contracts for coreclr
2+
// The format of this file is: JSON with comments
3+
// {
4+
// "CONTRACT NAME": VERSION,
5+
// ...
6+
// }
7+
// CONTRACT NAME is an arbitrary string, VERSION is an integer
8+
//
9+
// cdac-build-tool can take multiple "-c contract_file" arguments
10+
// so to conditionally include contracts, put additional contracts in a separate file
11+
{
12+
"SOSBreakingChangeVersion": 1 // example contract: "runtime exports an SOS breaking change version global"
13+
}
14+

0 commit comments

Comments
 (0)