') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); [cDAC] Adds DAC like entrypoint with new COM interface by max-charlamb · Pull Request #113899 · dotnet/runtime · GitHub
Skip to content

[cDAC] Adds DAC like entrypoint with new COM interface - #113899

Merged
max-charlamb merged 34 commits into
dotnet:mainfrom
max-charlamb:cdac-new-entrypoint
Apr 10, 2025
Merged

[cDAC] Adds DAC like entrypoint with new COM interface#113899
max-charlamb merged 34 commits into
dotnet:mainfrom
max-charlamb:cdac-new-entrypoint

Conversation

@max-charlamb

@max-charlambmax-charlamb commented Mar 25, 2025

Copy link
Copy Markdown
Member

Resolves#112583

New Entrypoint

Will be invoked by SOS as in dotnet/diagnostics#5373

The DAC uses a shim layer to convert the host's ICLRDataTarget into a ICorDebugDataTarget using defines based on the target platform. Previously, the cDAC was only invoked through the DAC and used the ICorDebugDataTarget API.
Now that we depend directly on ICLRDataTarget, it is not possible to get the target's OS configuration. Therefore, I have included a new contract IRuntimeInfo which encapsulates information about the target runtime.

Currently the contract has two methods:

RuntimeInfoArchitectureGetTargetArchitecture();RuntimeInfoOperatingSystemGetTargetOperatingSystem();

If we decide to store the build id/information in the contract, this would be a logical place to include it.

// Same export name and signature as existing DAC entrypoint[UnmanagedCallersOnly(EntryPoint="CLRDataCreateInstance")]privatestaticunsafeintCLRDataCreateInstance(Guid*pIID,IntPtr/*ICLRDataTarget*/pLegacyTarget,void**iface);// Additional entrypoint to allow passing in callback[UnmanagedCallersOnly(EntryPoint="CLRDataCreateInstanceWithFallback")]privatestaticunsafeintCLRDataCreateInstanceWithFallback(Guid*pIID,IntPtr/*ICLRDataTarget*/pLegacyTarget,IntPtrpLegacyImpl,void**iface);

Data Contract Global Strings

To support passing global strings (for the RuntimeInfo contract), I have modified the data descriptor spec. Previously globals were of the form

[ VALUE | [int], "type name" ]
or
VALUE | [int]

Where the VALUE may be a JSON numeric constant integer or a string containing a signed or unsigned decimal or hex (with prefix 0x or 0X) integer constant.

I have modified VALUE to be less constrained: VALUE may be either a number or a string. JSON numeric constants are always parsed as numbers. JSON strings are always parsed as strings and may additionally parse as a hex (with prefix 0x or 0X) or decimal number.

To fit the new spec, the cDAC data contract implementation was modified in three main:

  • The datadescriptor.h and datadescriptor.cpp in the runtime.
    • Added mechanism CDAC_GLOBAL_STRING(name, value) to pass global strings which are a mapping of a string (name) to string (value). Both strings exist in the existing string pool.
  • The cdac-build-tool which takes the obj file and converts it to a JSON human readable contract.
    • Modified to parse global strings from the obj and properly convert to JSON.
  • The parser inside of cdacreader which reads the JSON into a Target.
    • Modified to parse global strings and allow fetching existing stringy number globals as strings.

With this change existing stringy numbers can be parsed as either a number or a string.

Example:

{
"globals": {
"stringValue" : "Hello world",
"stringyInt" : "1234",
"stringyHex" : "0x1234",
"int" : 1234
}
}
target.ReadGlobalString("stringValue");// "Hello world"target.ReadGlobal<ulong>("stringValue");// Exception!! cannot be parsed as a numbertarget.ReadGlobalString("stringyInt");// "1234"target.ReadGlobal<ulong>("stringyInt");// 1234target.ReadGlobalString("stringyHex");// "0x1234"target.ReadGlobal<ulong>("stringyHex");// 4660 (0x1234)target.ReadGlobalString("int");// Exception!! no string representation for JSON Numberstarget.ReadGlobal<ulong>("int");// 1234

Testing

Tested with SOS CDACCompatible tests locally.

@max-charlamb

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-diagnostics

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR removes the dependency on the outdated GetPlatform callback and introduces a new COM interface along with a RuntimeInfo contract to obtain OS/Arch information for DAC functionality. Key changes include:

  • Eliminating GetTargetPlatform callbacks and related Platform property implementations.
  • Adding new COM interfaces (ICLRDataTarget and ICLRContractLocator) and an entrypoint (CLRDataCreateInstance) to support the new data contract.
  • Introducing the RuntimeInfo contract and related factory/configuration changes to fetch target runtime architecture and operating system.

Reviewed Changes

Copilot reviewed 13 out of 17 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
src/tools/StressLogAnalyzer/src/Program.csRemoved GetTargetPlatform callback as the platform info is now provided via the new contract.
src/native/managed/cdacreader/tests/TestPlaceholderTarget.csRemoved the Platform property and added a TryReadGlobal implementation for globals.
src/native/managed/cdacreader/src/Legacy/ICLRData.csAdded new COM interface definitions for ICLRDataTarget and ICLRContractLocator.
src/native/managed/cdacreader/src/Entrypoints.csRemoved getPlatform delegate and introduced CLRDataCreateInstance with updates to error messaging.
src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader/ContractDescriptorTarget.csRemoved getTargetPlatform dependency from target creation and reader initialization.
src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader/CachingContractRegistry.csAdded a new contract factory mapping for IRuntimeInfo.
src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/IPlatformAgnosticContext.csUpdated platform context retrieval to use the new RuntimeInfo contract.
src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Abstractions/Target.csRemoved the CorDebugPlatform enum and its Platform property from the target abstraction.
src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Abstractions/ContractRegistry.csAdded RuntimeInfo access to the contract registry.
docs/design/datacontracts/RuntimeInfo.mdIntroduced documentation for the new RuntimeInfo contract.
Files not reviewed (4)
  • src/coreclr/debug/daccess/cdac.cpp: Language not supported
  • src/coreclr/debug/runtimeinfo/contracts.jsonc: Language not supported
  • src/coreclr/debug/runtimeinfo/datadescriptor.h: Language not supported
  • src/native/managed/cdacreader/inc/cdac_reader.h: Language not supported

Comment threadsrc/native/managed/cdacreader/src/Entrypoints.cs Outdated
Comment threadsrc/native/managed/cdacreader/src/Entrypoints.cs Outdated

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a DAC-like entrypoint with a new COM interface and introduces a new contract (IRuntimeInfo) to encapsulate target runtime information, replacing the previous reliance on the Platform property. Key changes include:

  • Removal of the deprecated GetTargetPlatform callback and the Platform property.
  • Addition of new COM interfaces (ICLRDataTarget and ICLRContractLocator) and corresponding entrypoint (CLRDataCreateInstance).
  • Introduction and integration of the IRuntimeInfo contract and factory, including updates in contract consumption and context determination.

Reviewed Changes

Copilot reviewed 13 out of 17 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
src/tools/StressLogAnalyzer/src/Program.csRemoved the obsolete GetTargetPlatform callback to align with the new IRuntimeInfo approach.
src/native/managed/cdacreader/tests/TestPlaceholderTarget.csRemoved the Platform property and added a new TryReadGlobal method for retrieving globals.
src/native/managed/cdacreader/src/Legacy/ICLRData.csIntroduced new COM interface definitions (ICLRDataTarget and ICLRContractLocator).
src/native/managed/cdacreader/src/Entrypoints.csUpdated the entrypoint initialization by removing getPlatform and using the new COM interfaces.
src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader/ContractDescriptorTarget.csRemoved getTargetPlatform from the reader and Platform property, reflecting the migration to IRuntimeInfo.
src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader/CachingContractRegistry.csAdded a new factory entry for IRuntimeInfo.
src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Contracts/*Added new contract definitions and factories for RuntimeInfo.
src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Abstractions/*Removed Platform from Target and added an abstract RuntimeInfo property.
docs/design/datacontracts/RuntimeInfo.mdDocumented the new RuntimeInfo contract and its APIs.
Files not reviewed (4)
  • src/coreclr/debug/daccess/cdac.cpp: Language not supported
  • src/coreclr/debug/runtimeinfo/contracts.jsonc: Language not supported
  • src/coreclr/debug/runtimeinfo/datadescriptor.h: Language not supported
  • src/native/managed/cdacreader/inc/cdac_reader.h: Language not supported
Comments suppressed due to low confidence (3)

src/native/managed/cdacreader/tests/TestPlaceholderTarget.cs:95

  • Please ensure that the new TryReadGlobal method is adequately covered by unit tests, including cases when the specified global is missing.
public override bool TryReadGlobal<T>(string name, [NotNullWhen(true)] out T? value)

src/native/managed/cdacreader/Microsoft.Diagnostics.DataContractReader.Abstractions/Target.cs:18

  • The Platform property has been removed; ensure that all consumers now reference IRuntimeInfo and its methods for retrieving target OS and architecture.
public abstract CorDebugPlatform Platform { get; }

src/native/managed/cdacreader/src/Entrypoints.cs:16

  • Since the getPlatform callback has been removed to support the new IRuntimeInfo contract, please update any related documentation or error messages to reflect this change.
- delegate* unmanaged<int*, void*, int> getPlatform,

Comment threaddocs/design/datacontracts/RuntimeInfo.md
Comment threaddocs/design/datacontracts/RuntimeInfo.md
Comment threadsrc/coreclr/debug/runtimeinfo/datadescriptor.h
Comment threadsrc/coreclr/debug/runtimeinfo/datadescriptor.h
#error TARGET_{ARCH} define is not recognized by the cDAC. Update this switch and the enum values in IRuntimeInfo.cs
#endif

CDAC_GLOBAL_STRING(RID, RID_STRING)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have looked at what the contract json looks like. OperatingSystem and Architecture looks good, but the RID is not getting substituted correctly:

"OperatingSystem":["windows","string"],"Architecture":["x64","string"],"RID":["RID_STRING","string"]},

(If it is too hard to pass the RID through, I would be ok with leaving it out for now.)

@max-charlambmax-charlambApr 9, 2025

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be an issue to resolve. To stringify the macro expansion (ex: win-x64) instead of the macro name (RID_STRING), a second layer of macro is required to expand before stringifying. For more details see: https://gcc.gnu.org/onlinedocs/gcc-4.8.5/cpp/Stringification.html

I added the second layer but missed actually invoking it instead of calling the stringification operator directly.

// used to stringify the result of a macros expansion
#define STRINGIFY(x) #x

Edit: fixed

@max-charlamb
max-charlamb merged commit 7618121 into dotnet:mainApr 10, 2025
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 11, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create cDAC entrypoint same as DAC CLRDataCreateInstance

8 participants

@max-charlamb@kg@steveisok@jkoritzinsky@jkotas@mikem8361@davidwrighton