Skip to content
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

Portable Data Contract-based DAC in .NET 9+ #99298

Open
13 of 35 tasks
lambdageek opened this issue Mar 5, 2024 · 2 comments
Open
13 of 35 tasks

Portable Data Contract-based DAC in .NET 9+ #99298

lambdageek opened this issue Mar 5, 2024 · 2 comments
Assignees
Labels
area-Diagnostics-coreclr Epic Groups multiple user stories. Can be grouped under a theme. tracking This issue is tracking the completion of other related issues.
Milestone

Comments

@lambdageek
Copy link
Member

lambdageek commented Mar 5, 2024

Summary

The DAC is a .NET runtime component responsible for helping debuggers and other diagnostic tools to make sense of
the memory of a .NET runtime process. In the current design, each instance of the .NET runtime is tightly coupled to a DAC:
a runtime running on a a 32-bit little endian architecture can only be accessed by a 32-bit LE DAC, 64-bit with a 64-bit DAC,
etc. Although the current runtime data structures are carefully designed so that a DAC hosted on Windows can make sense
of a Linux or Mac .NET runtime, this is fragile and hard to maintain. This is because the current DAC implementation is actually a special build of the .NET runtime that uses C++ smart pointers to hide the fact
that it is not accessing the memory of the host process, but rather the memory of a remote debuggee .NET process.

Additionally, the current DAC is not version-resilient. When a new verson of the .NET runtime is released, it ships with a DAC that can access that versions' memory and nothing else. This means that debuggers need to be able to locate, load and run a DAC corresponding to each runtime version. While this might be possible for official releases, it may create complications for source-built .NET runtimes, for unsupported/community-supported platforms etc.

Portable Data Contract-based DAC

An alternate approach is for the .NET runtime to include a data stream that encodes information about itself: the size and endianness of machine words, the size and offsets of important fields in interesting runtime data structures, the locations of globals that are relevant for diagnostic tools.

With access to a data stream, the DAC can be a separate implementation that can abstract over the details of a particular version of the runtime and implement an abstract data contract based diagnostic tooling. (This is abbreviated cDAC)

.NET 10 Plan

In .NET 10 we will begin to move the DAC toward a data-contract based approach by enabling the existing DAC to delegate some operations to the cDAC. Our initial focus will be the SOS tool used by the .NET LLDB plugin and by Windbg. Our initial milestone will be the implementation of the !PrintException SOS command. Followed by the DAC interfaces used by CLRMA

A goal for the cDAC implementation is to maintain backward- and platform- compatability with each release: the each future release of the cDAC will be able to access each .NET runtime version >= .NET 9. We do not intend to support .NET <= 8 or .NET Framework using the cDAC.

The focus for .NET 9 is to host the DAC on 64-bit desktop platforms - Linux (glibc), MacOS and Windows - but to be able to access a debuggee or crash dump from 32-bit and 64-bit processes on all supported (and ideally community-supported) platforms (including musl-based Linux, arm32, win-x86, etc).

First milestone

The first milestone is a working !PrintException command based on the cDAC in windbg/SOS

Post-.NET 10 work

The overall goal is to implement a subset of the ISOSDacInterfaceNN IDL interfaces in sospriv.idl via the cDAC

Other closed issues

.NET 9 backports

We maintain a branch feature/9.0-cdac-backports that has selected data descriptor and contract changes necessary for the cdacreader to interrogate a net9.0 runtime. The backports to this branch are tracked on #99302.

Future work

The initial cDAC plan will not reduce the complexity of the current design. However once the existing DAC delegates all commands to the cDAC, we may simplify the packaging and distribution of the cDAC - allowing diagnostics tools to obtain a single library that works with all versions of CoreCLR >= .NET 9, as well as other .NET runtimes including NativeAOT and Mono.

Special attention needs to be paid to the crashdump tool. This ships with CoreCLR and NativeAOT and runs on the same host as the .NET runtime. It uses a subset of the DAC in order to save a copy

  • [cdac] Full parity with smart-pointer DAC
  • [cdac] Publish cDAC as a separate nuget
  • Infrastructure for data descriptor of managed types without mirrors in the unmananged runtime ([cdac] Implement ISOSDacInterface2::GetObjectExceptionData #104343 (comment))
  • [cdac] support for NativeAOT
  • [cdac] support to Mono
  • [cdac] Implement a simplified cDAC for crashdump
  • Define a new public contract-based diagnostics API
@ghost
Copy link

ghost commented Mar 5, 2024

Tagging subscribers to this area: @tommcdon
See info in area-owners.md if you want to be subscribed.

Issue Details

Summary

The DAC is a .NET runtime component responsible for helping debuggers and other diagnostic tools to make sense of
the memory of a .NET runtime process. In the current design, each instance of the .NET runtime is tightly coupled to a DAC:
a runtime running on a a 32-bit LE architecture can only be accessed by a 32-bit LE DAC, 64-bit with a 64-bit DAC,
etc. Although the current runtime data structures are carefully designed so that a DAC hosted on Windows can make sense
of a Linux or MAC .NET runtime, this is fragile and hard to maintain. This is because the current DAC implementation is actually a special build of the .NET runtime that uses C++ smart pointers to hide the fact
that it is not accessing the memory of the host process, but rather the memory of a remote debuggee .NET process.

Additionally, the current DAC is not version-resilient. When a new verson of the .NET runtime is release, it ships with a DAC that can access that versions' memory and nothing else. This means that debuggers need to be able to locate, load and run a DAC corresponding to each runtime version. While this might be possible for official releases, it may create complications for source-built .NET runtimes, for unsupported/community-supported platforms etc.

Portable Data Contract-based DAC

An alternate approach is for the .NET runtime to include a data stream that encodes information about itself: the size and endianness of machine words, the size and offsets of important fields in interesting runtime data structures, the locations of globals that are relevant for diagnostic tools.

With access to a data stream, the DAC can be a separate implementation that can abstract over the details of a particular version of the runtime and implement an abstract data contract based diagnostic tooling. (This is abbreviated cDAC)

.NET 9 Plan

In .NET 9 we will begin to move the DAC toward a data-contract based approach by enabling the existing DAC to delegate some operations to the cDAC. Our initial focus will be the SOS tool used by the .NET LLDB plugin and by Windbg. Our initial milestone will be the implementation of the !PrintException SOS command.

A goal for the cDAC implementation is to maintain backward- and platform- compatability with each release: the each future release of the cDAC will be able to access each .NET runtime version >= .NET 9. We do not intend to support .NET <= 8 or .NET Framework using the cDAC.

The focus for .NET 9 is to host the DAC on 64-bit desktop platforms - Linux (glibc), MacOS and Windows - but to be able to access a debuggee or crash dump from 32-bit and 64-bit processes on all supported (and ideally community-supported) platforms (including musl-based Linux, arm32, win-x86, etc).

  • Publish data stream spec
  • Implement basic data stream reader and writer in C
  • Enable the DAC to delegate operations to the cDAC
  • Implement !PrintException
  • Implement additional commands (TBD)

Future plans

The initial cDAC plan will not reduce the complexity of the current design. However once the existing DAC delegates all commands to the cDAC, we may simplify the packaging and distribution of the cDAC - allowing diagnostics tools to obtain a single library that works with all versions of CoreCLR >= .NET 9, as well as other .NET runtimes including NativeAOT and Mono.

Special attention needs to be paid to the crashdump tool. This ships with CoreCLR and NativeAOT and runs on the same host as the .NET runtime. It uses a subset of the DAC in order to save a copy

  • Full cDAC parity
  • Publish cDAC as a separate nuget
  • cDAC support for NativeAOT
  • cDAC support to Mono
  • Implement a simplified cDAC for crashdump
Author: lambdageek
Assignees: lambdageek, elinor-fung
Labels:

area-Diagnostics-coreclr

Milestone: 9.0.0

@lambdageek
Copy link
Member Author

@steveisok steveisok added the Epic Groups multiple user stories. Can be grouped under a theme. label Mar 5, 2024
@agocke agocke added this to AppModel Mar 11, 2024
lambdageek added a commit that referenced this issue Mar 29, 2024
Contributes to #100162 which is part of #99298

Follow-up to #99936 that removes "type layout" and "global value" contracts and instead replaces them with a "data descriptor" blob.

Conceptually a particular target runtime provides a pair of a logical data descriptor together with a set of algorithmic contract versions. The logical data descriptor is just a single model that defines all the globals and type layouts relevant to the set of algorithmic contract versions.

A logical data descriptor is realized by merging two physical data descriptors in a proscribed order.

The physical data descriptors provide some subset of the type layouts or global values.

The physical data descriptors come in two flavors:

- baseline descriptors that are checked into the dotnet/runtime repo and have well -known names
- in-proc descriptors that get embedded into a target runtime.

Each in-proc descriptor may refer to a baseline and represents a delta applied on top of the baseline.
The data contract model works on top of a flattened logical data descriptor.


Co-authored-by: Aaron Robinson <arobins@microsoft.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Co-authored-by: Noah Falk <noahfalk@users.noreply.github.com>
lambdageek added a commit that referenced this issue Apr 4, 2024
Building on #100253 , describe an in-memory representation of the toplevel contract descriptor, comprisied of:
* some target architecture properties
* a data descriptor
* a collection of compatible contracts

Contributes to #99298 
Fixes #99299

---


* [cdac] Physical contract descriptor spec

* Add "contracts" to the data descriptor

*  one runtime per module

   if there are multiple hosted runtimes, diagnostic tooling should look in each loaded module to discover the contract descriptor

* Apply suggestions from code review

* Review feedback

   - put the aux data and descriptor sizes closer to the pointers

   - Don't include trailing nul `descriptor_size`.  Clarify it is counting bytes and that `descriptor` is in UTF-8

   - Simplify `DotNetRuntimeContractDescriptor` naming discussion

---------

Co-authored-by: Elinor Fung <elfung@microsoft.com>
matouskozak pushed a commit to matouskozak/runtime that referenced this issue Apr 30, 2024
Contributes to dotnet#100162 which is part of dotnet#99298

Follow-up to dotnet#99936 that removes "type layout" and "global value" contracts and instead replaces them with a "data descriptor" blob.

Conceptually a particular target runtime provides a pair of a logical data descriptor together with a set of algorithmic contract versions. The logical data descriptor is just a single model that defines all the globals and type layouts relevant to the set of algorithmic contract versions.

A logical data descriptor is realized by merging two physical data descriptors in a proscribed order.

The physical data descriptors provide some subset of the type layouts or global values.

The physical data descriptors come in two flavors:

- baseline descriptors that are checked into the dotnet/runtime repo and have well -known names
- in-proc descriptors that get embedded into a target runtime.

Each in-proc descriptor may refer to a baseline and represents a delta applied on top of the baseline.
The data contract model works on top of a flattened logical data descriptor.


Co-authored-by: Aaron Robinson <arobins@microsoft.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Co-authored-by: Noah Falk <noahfalk@users.noreply.github.com>
matouskozak pushed a commit to matouskozak/runtime that referenced this issue Apr 30, 2024
Building on dotnet#100253 , describe an in-memory representation of the toplevel contract descriptor, comprisied of:
* some target architecture properties
* a data descriptor
* a collection of compatible contracts

Contributes to dotnet#99298 
Fixes dotnet#99299

---


* [cdac] Physical contract descriptor spec

* Add "contracts" to the data descriptor

*  one runtime per module

   if there are multiple hosted runtimes, diagnostic tooling should look in each loaded module to discover the contract descriptor

* Apply suggestions from code review

* Review feedback

   - put the aux data and descriptor sizes closer to the pointers

   - Don't include trailing nul `descriptor_size`.  Clarify it is counting bytes and that `descriptor` is in UTF-8

   - Simplify `DotNetRuntimeContractDescriptor` naming discussion

---------

Co-authored-by: Elinor Fung <elfung@microsoft.com>
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this issue May 30, 2024
Contributes to dotnet#100162 which is part of dotnet#99298

Follow-up to dotnet#99936 that removes "type layout" and "global value" contracts and instead replaces them with a "data descriptor" blob.

Conceptually a particular target runtime provides a pair of a logical data descriptor together with a set of algorithmic contract versions. The logical data descriptor is just a single model that defines all the globals and type layouts relevant to the set of algorithmic contract versions.

A logical data descriptor is realized by merging two physical data descriptors in a proscribed order.

The physical data descriptors provide some subset of the type layouts or global values.

The physical data descriptors come in two flavors:

- baseline descriptors that are checked into the dotnet/runtime repo and have well -known names
- in-proc descriptors that get embedded into a target runtime.

Each in-proc descriptor may refer to a baseline and represents a delta applied on top of the baseline.
The data contract model works on top of a flattened logical data descriptor.


Co-authored-by: Aaron Robinson <arobins@microsoft.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Co-authored-by: Noah Falk <noahfalk@users.noreply.github.com>
Ruihan-Yin pushed a commit to Ruihan-Yin/runtime that referenced this issue May 30, 2024
Building on dotnet#100253 , describe an in-memory representation of the toplevel contract descriptor, comprisied of:
* some target architecture properties
* a data descriptor
* a collection of compatible contracts

Contributes to dotnet#99298 
Fixes dotnet#99299

---


* [cdac] Physical contract descriptor spec

* Add "contracts" to the data descriptor

*  one runtime per module

   if there are multiple hosted runtimes, diagnostic tooling should look in each loaded module to discover the contract descriptor

* Apply suggestions from code review

* Review feedback

   - put the aux data and descriptor sizes closer to the pointers

   - Don't include trailing nul `descriptor_size`.  Clarify it is counting bytes and that `descriptor` is in UTF-8

   - Simplify `DotNetRuntimeContractDescriptor` naming discussion

---------

Co-authored-by: Elinor Fung <elfung@microsoft.com>
@tommcdon tommcdon modified the milestones: 9.0.0, 10.0.0 Jul 23, 2024
@lambdageek lambdageek changed the title Portable Data Contract-based DAC in .NET 9 Portable Data Contract-based DAC in .NET 9+ Aug 15, 2024
@lambdageek lambdageek added the tracking This issue is tracking the completion of other related issues. label Oct 9, 2024
@lambdageek lambdageek assigned steveisok and unassigned lambdageek Nov 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-Diagnostics-coreclr Epic Groups multiple user stories. Can be grouped under a theme. tracking This issue is tracking the completion of other related issues.
Projects
Status: No status
Development

No branches or pull requests

4 participants