Skip to content

Forward ICLRSymbolProvider calls to a host-supplied symbol resolver#5877

Open
max-charlamb wants to merge 2 commits into
dotnet:mainfrom
max-charlamb:max-charlamb/symbol-provider
Open

Forward ICLRSymbolProvider calls to a host-supplied symbol resolver#5877
max-charlamb wants to merge 2 commits into
dotnet:mainfrom
max-charlamb:max-charlamb/symbol-provider

Conversation

@max-charlamb

Copy link
Copy Markdown
Member

Requires: microsoft/clrmd#1482

Plumbs ClrMD's IClrSymbolProvider hook through the diagnostics host so the (c)DAC can map runtime addresses back to module-qualified symbols via the host's IModuleService / IModuleSymbols. Also unifies SOS's existing legacy-DAC symbol-provider thunks onto the same shared adapter.

  • HostSymbolProvider (new): IClrSymbolProvider adapter over IModuleService; registered as a per-target service via [ServiceExport].

  • RuntimeProvider: sets DataTargetOptions.SymbolProvider from the registered service so ClrMD's COM data target wrapper forwards ICLRSymbolProvider calls to the host.

  • SOS.Hosting/DataTargetWrapper: exposes ICLRSymbolProvider on the legacy-DAC CCW (was missing), delegating to the same IClrSymbolProvider service for a single resolver code path.

  • Runtime: extracts the ClrFlavor -> RuntimeType mapping into a single GetRuntimeType helper; adds a generic GetDacFilePath fallback so runtimes that ship only a cDAC (no legacy DAC binary) load via the cDAC without the user having to set ForceUseContractReader.

  • ServiceManager: invokes RuntimeHelpers.RunModuleConstructor on each loaded extension so module initializers fire at load time, allowing extensions to register process-wide state (e.g. ClrMD IClrInfoProvider) before any provider factory is invoked.

Depends on a ClrMD package that contains IClrSymbolProvider and DataTargetOptions.SymbolProvider (microsoft/clrmd PR pending; the corresponding package-version bump in eng/Version.Details.xml will land via darc once the upstream PR merges).

@max-charlamb max-charlamb requested a review from hoyosjs June 12, 2026 15:46
@max-charlamb max-charlamb requested a review from a team as a code owner June 12, 2026 15:46
Copilot AI review requested due to automatic review settings June 12, 2026 15:46

Copilot AI 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 plumbs ClrMD’s symbol-resolution hook through the diagnostics host so both ClrMD’s data target and SOS’s legacy-DAC COM data target can resolve module-qualified symbols via a host-provided implementation. It also adjusts extension loading to proactively run module initializers and refactors some runtime-type/DAC selection logic.

Changes:

  • Add a per-target IClrSymbolProvider adapter over the host’s module/symbol services and pass it into ClrMD via DataTargetOptions.SymbolProvider.
  • Expose ICLRSymbolProvider on SOS’s legacy-DAC data-target CCW and forward calls to the shared IClrSymbolProvider service.
  • Run extension module initializers at load time; refactor runtime flavor→type mapping and add a CDAC fallback in GetDacFilePath.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/SOS/SOS.Hosting/DataTargetWrapper.cs Implements ICLRSymbolProvider on the legacy-DAC data target CCW and forwards symbol queries to a managed provider.
src/Microsoft.Diagnostics.DebugServices.Implementation/ServiceManager.cs Forces module initializers to run when registering an extension assembly.
src/Microsoft.Diagnostics.DebugServices.Implementation/RuntimeProvider.cs Supplies DataTargetOptions.SymbolProvider from the host service container when creating ClrMD DataTarget.
src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.cs Centralizes flavor→RuntimeType mapping and adds a CDAC fallback path in GetDacFilePath.
src/Microsoft.Diagnostics.DebugServices.Implementation/HostSymbolProvider.cs New adapter implementing ClrMD’s IClrSymbolProvider on top of IModuleService/IModuleSymbols.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/SOS/SOS.Hosting/DataTargetWrapper.cs Outdated
Comment thread src/SOS/SOS.Hosting/DataTargetWrapper.cs Outdated
Comment thread src/SOS/SOS.Hosting/DataTargetWrapper.cs Outdated
Comment thread src/Microsoft.Diagnostics.DebugServices.Implementation/HostSymbolProvider.cs Outdated
Comment thread src/Microsoft.Diagnostics.DebugServices.Implementation/ServiceManager.cs Outdated
Comment thread src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.cs
Plumbs ClrMD's IClrSymbolProvider hook through the diagnostics host so the (c)DAC can map runtime addresses back to module-qualified symbols via the host's IModuleService / IModuleSymbols. Also unifies SOS's existing legacy-DAC symbol-provider thunks onto the same shared adapter.

* HostSymbolProvider (new): IClrSymbolProvider adapter over IModuleService; registered as a per-target service via [ServiceExport].

* RuntimeProvider: sets DataTargetOptions.SymbolProvider from the registered service so ClrMD's COM data target wrapper forwards ICLRSymbolProvider calls to the host.

* SOS.Hosting/DataTargetWrapper: exposes ICLRSymbolProvider on the legacy-DAC CCW (was missing), delegating to the same IClrSymbolProvider service for a single resolver code path. Aligns the CCW HRESULT contract with ClrMD's LegacyDacDataTargetWrapper (E_NOTIMPL when no provider, E_FAIL on miss, S_FALSE on truncation, null-terminated buffer, ! reserved as module separator).

* Runtime: extracts the ClrFlavor -> RuntimeType mapping into a single GetRuntimeType helper; adds a generic GetDacFilePath fallback so runtimes that ship only a cDAC (no legacy DAC binary) load via the cDAC without the user having to set ForceUseContractReader.

* IHostExtension (new) + ServiceManager: extension assemblies can implement IHostExtension to register process-wide state (e.g. a ClrMD IClrInfoProvider) at load time. Discovery is folded into the existing [ServiceExport]/[ProviderExport] type scan in RegisterExportedServices, so no new reflection pass is added.

Depends on a ClrMD package that contains IClrSymbolProvider and DataTargetOptions.SymbolProvider (microsoft/clrmd#PR-merged; the package-version bump in eng/Version.Details.xml has landed via darc).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI 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

Copilot reviewed 6 out of 6 changed files in this pull request and generated 8 comments.

Comment thread src/Microsoft.Diagnostics.DebugServices.Implementation/HostSymbolProvider.cs Outdated
Comment thread src/SOS/SOS.Hosting/DataTargetWrapper.cs
Comment thread src/SOS/SOS.Hosting/DataTargetWrapper.cs
Comment thread src/Microsoft.Diagnostics.DebugServices/IHostExtension.cs Outdated
- HostSymbolProvider: remove unused System.IO using; fix XML doc
  (bare symbol names, qualifier stripped); inject IMemoryService and
  mask address/moduleBase via SignExtensionMask for x86 targets.
- DataTargetWrapper.ICLRSymbolProvider: apply _ignoreAddressBitsMask
  to address/moduleBase for sign-extended x86 inputs (matches the
  pattern used by ReadVirtual/WriteVirtual in the same file).
- ServiceManager.InvokeHostExtension: wrap Activator+Initialize and
  rethrow non-DiagnosticsException as DiagnosticsException so an
  extension constructor/initializer failure surfaces as a load
  failure instead of escaping RegisterAssembly.
- IHostExtension: update doc to reflect per-implementing-type
  invocation (an assembly may contain multiple implementations;
  ordering is unspecified).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@leculver leculver 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.

Will take a look again tomorrow, just a quick skim so far.

return false;
}

foreach (IModule module in _moduleService.EnumerateModules())

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.

Do we even want to support moduleBase == 0? To scan everything? Once we reach here this is going to grind the entire debugger to an absolute halt, and with no cancellation token possible across com, this is going to be pure pain.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants