From 2294a557ca7e01ca65bfde59de88d5b4375bad52 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Tue, 16 Jun 2026 14:18:00 -0400
Subject: [PATCH 1/2] Forward ICLRSymbolProvider calls to a host-supplied
symbol resolver
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>
---
.../HostSymbolProvider.cs | 123 ++++++++++++++++
.../Runtime.cs | 28 ++--
.../RuntimeProvider.cs | 3 +-
.../ServiceManager.cs | 20 +++
.../IHostExtension.cs | 23 +++
src/SOS/SOS.Hosting/DataTargetWrapper.cs | 131 ++++++++++++++++++
6 files changed, 318 insertions(+), 10 deletions(-)
create mode 100644 src/Microsoft.Diagnostics.DebugServices.Implementation/HostSymbolProvider.cs
create mode 100644 src/Microsoft.Diagnostics.DebugServices/IHostExtension.cs
diff --git a/src/Microsoft.Diagnostics.DebugServices.Implementation/HostSymbolProvider.cs b/src/Microsoft.Diagnostics.DebugServices.Implementation/HostSymbolProvider.cs
new file mode 100644
index 0000000000..8103e37847
--- /dev/null
+++ b/src/Microsoft.Diagnostics.DebugServices.Implementation/HostSymbolProvider.cs
@@ -0,0 +1,123 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.IO;
+using Microsoft.Diagnostics.Runtime;
+
+namespace Microsoft.Diagnostics.DebugServices.Implementation
+{
+ ///
+ /// Adapter exposing the host's /
+ /// through ClrMD's
+ /// contract. Registered as a per-target
+ /// service so both ClrMD (via )
+ /// and SOS's data-target CCW can resolve symbols through one shared
+ /// implementation. Returns symbols in "Module!Symbol" form.
+ ///
+ [ServiceExport(Type = typeof(IClrSymbolProvider), Scope = ServiceScope.Target)]
+ public sealed class HostSymbolProvider : IClrSymbolProvider
+ {
+ private readonly IModuleService _moduleService;
+
+ public HostSymbolProvider(IModuleService moduleService)
+ {
+ _moduleService = moduleService ?? throw new ArgumentNullException(nameof(moduleService));
+ }
+
+ public bool TryGetSymbolName(ulong address, out string symbolName, out ulong displacement)
+ {
+ symbolName = null;
+ displacement = 0;
+
+ IModule module;
+ try
+ {
+ module = _moduleService.GetModuleFromAddress(address);
+ }
+ catch (DiagnosticsException)
+ {
+ return false;
+ }
+ if (module is null)
+ {
+ return false;
+ }
+
+ IModuleSymbols symbols = module.Services.GetService();
+ if (symbols is null)
+ {
+ return false;
+ }
+
+ if (!symbols.TryGetSymbolName(address, out string bareName, out displacement)
+ || string.IsNullOrEmpty(bareName))
+ {
+ return false;
+ }
+
+ // Strip any module! qualifier the lower-level service might have
+ // prepended — the new contract returns bare names only.
+ int bang = bareName.IndexOf('!');
+ symbolName = bang >= 0 && bang + 1 < bareName.Length ? bareName.Substring(bang + 1) : bareName;
+ return true;
+ }
+
+ public bool TryGetSymbolAddress(ulong moduleBase, string name, out ulong address)
+ {
+ address = 0;
+ if (string.IsNullOrEmpty(name))
+ {
+ return false;
+ }
+
+ // moduleBase != 0 restricts the search to a single module.
+ if (moduleBase != 0)
+ {
+ IModule scopedModule;
+ try
+ {
+ scopedModule = _moduleService.GetModuleFromBaseAddress(moduleBase);
+ }
+ catch (DiagnosticsException)
+ {
+ return false;
+ }
+ if (scopedModule is null)
+ {
+ return false;
+ }
+
+ IModuleSymbols scopedSymbols = scopedModule.Services.GetService();
+ if (scopedSymbols is null)
+ {
+ return false;
+ }
+
+ if (scopedSymbols.TryGetSymbolAddress(name, out ulong scopedAddr) && scopedAddr != 0)
+ {
+ address = scopedAddr;
+ return true;
+ }
+ return false;
+ }
+
+ foreach (IModule module in _moduleService.EnumerateModules())
+ {
+ IModuleSymbols symbols = module.Services.GetService();
+ if (symbols is null)
+ {
+ continue;
+ }
+
+ if (symbols.TryGetSymbolAddress(name, out ulong addr) && addr != 0)
+ {
+ address = addr;
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.cs b/src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.cs
index 05db19b715..9cdfc03022 100644
--- a/src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.cs
+++ b/src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.cs
@@ -39,15 +39,7 @@ public Runtime(IServiceProvider services, int id, ClrInfo clrInfo)
_settingsService = services.GetService() ?? throw new ArgumentException("ISettingsService required");
_symbolService = services.GetService() ?? throw new ArgumentException("ISymbolService required");
- RuntimeType = RuntimeType.Unknown;
- if (clrInfo.Flavor == ClrFlavor.Core)
- {
- RuntimeType = RuntimeType.NetCore;
- }
- else if (clrInfo.Flavor == ClrFlavor.Desktop)
- {
- RuntimeType = RuntimeType.Desktop;
- }
+ RuntimeType = GetRuntimeType(clrInfo.Flavor);
RuntimeModule = services.GetService().GetModuleFromBaseAddress(clrInfo.ModuleInfo.ImageBase);
ServiceContainerFactory containerFactory = services.GetService().CreateServiceContainerFactory(ServiceScope.Runtime, services);
@@ -129,6 +121,15 @@ public string GetDacFilePath(out bool verifySignature)
_verifySignature = _settingsService.DacSignatureVerificationEnabled;
}
}
+ if (_dacFilePath is null)
+ {
+ _cdacFilePath ??= GetLibraryPath(DebugLibraryKind.CDac);
+ if (_cdacFilePath is not null)
+ {
+ verifySignature = false;
+ return _cdacFilePath;
+ }
+ }
verifySignature = _verifySignature;
return _dacFilePath;
}
@@ -318,9 +319,18 @@ public override int GetHashCode()
"Desktop .NET Framework",
".NET Core",
".NET Core (single-file)",
+ "Native AOT",
"Other"
};
+ private static RuntimeType GetRuntimeType(ClrFlavor flavor) => flavor switch
+ {
+ ClrFlavor.Core => RuntimeType.NetCore,
+ ClrFlavor.Desktop => RuntimeType.Desktop,
+ ClrFlavor.NativeAOT => RuntimeType.NativeAOT,
+ _ => RuntimeType.Unknown,
+ };
+
public override string ToString()
{
StringBuilder sb = new();
diff --git a/src/Microsoft.Diagnostics.DebugServices.Implementation/RuntimeProvider.cs b/src/Microsoft.Diagnostics.DebugServices.Implementation/RuntimeProvider.cs
index 00eb74c6cd..2994f71a18 100644
--- a/src/Microsoft.Diagnostics.DebugServices.Implementation/RuntimeProvider.cs
+++ b/src/Microsoft.Diagnostics.DebugServices.Implementation/RuntimeProvider.cs
@@ -36,7 +36,8 @@ public IEnumerable EnumerateRuntimes(int startingRuntimeId, RuntimeEnu
DataTarget dataTarget = new(_services.GetService(), new DataTargetOptions()
{
ForceCompleteRuntimeEnumeration = (flags & RuntimeEnumerationFlags.All) != 0,
- VerifyDacOnWindows = settingsService?.DacSignatureVerificationEnabled ?? true
+ VerifyDacOnWindows = settingsService?.DacSignatureVerificationEnabled ?? true,
+ SymbolProvider = _services.GetService(),
});
for (int i = 0; i < dataTarget.ClrVersions.Length; i++)
{
diff --git a/src/Microsoft.Diagnostics.DebugServices.Implementation/ServiceManager.cs b/src/Microsoft.Diagnostics.DebugServices.Implementation/ServiceManager.cs
index ae69ea69ef..d088a2fdb0 100644
--- a/src/Microsoft.Diagnostics.DebugServices.Implementation/ServiceManager.cs
+++ b/src/Microsoft.Diagnostics.DebugServices.Implementation/ServiceManager.cs
@@ -121,6 +121,12 @@ public void RegisterExportedServices(Type serviceType)
{
throw new InvalidOperationException();
}
+
+ if (typeof(IHostExtension).IsAssignableFrom(serviceType))
+ {
+ InvokeHostExtension(serviceType);
+ }
+
for (Type currentType = serviceType; currentType is not null; currentType = currentType.BaseType)
{
if (currentType == typeof(object) || currentType == typeof(ValueType))
@@ -185,6 +191,20 @@ or FileLoadException
}
}
+ private static void InvokeHostExtension(Type type)
+ {
+ if (type.IsAbstract)
+ {
+ return;
+ }
+ if (type.GetConstructor(Type.EmptyTypes) is null)
+ {
+ throw new InvalidOperationException($"IHostExtension implementation '{type.FullName}' must have a public parameterless constructor.");
+ }
+ IHostExtension extension = (IHostExtension)Activator.CreateInstance(type);
+ extension.Initialize();
+ }
+
///
/// Add service factory for the specific scope.
///
diff --git a/src/Microsoft.Diagnostics.DebugServices/IHostExtension.cs b/src/Microsoft.Diagnostics.DebugServices/IHostExtension.cs
new file mode 100644
index 0000000000..71bf63f3ca
--- /dev/null
+++ b/src/Microsoft.Diagnostics.DebugServices/IHostExtension.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.Diagnostics.DebugServices
+{
+ ///
+ /// Implemented by extension assemblies to perform process-wide initialization
+ /// (for example registering an IClrInfoProvider) when the extension
+ /// is loaded.
+ ///
+ /// Implementations must have a public parameterless constructor. They are
+ /// discovered and invoked exactly once per extension assembly during
+ /// assembly registration, before any other
+ /// service or provider exports from the assembly are consumed.
+ ///
+ public interface IHostExtension
+ {
+ ///
+ /// Performs one-time initialization for the extension.
+ ///
+ void Initialize();
+ }
+}
diff --git a/src/SOS/SOS.Hosting/DataTargetWrapper.cs b/src/SOS/SOS.Hosting/DataTargetWrapper.cs
index 0a01ceea22..fda02b6202 100644
--- a/src/SOS/SOS.Hosting/DataTargetWrapper.cs
+++ b/src/SOS/SOS.Hosting/DataTargetWrapper.cs
@@ -19,6 +19,7 @@ internal sealed unsafe class DataTargetWrapper : COMCallableIUnknown
private static readonly Guid IID_ICLRMetadataLocator = new("aa8fa804-bc05-4642-b2c5-c353ed22fc63");
private static readonly Guid IID_ICLRRuntimeLocator = new("b760bf44-9377-4597-8be7-58083bdc5146");
private static readonly Guid IID_ICLRContractLocator = new("17d5b8c6-34a9-407f-af4f-a930201d4e02");
+ private static readonly Guid IID_ICLRSymbolProvider = new("c4f8b7e2-9d3a-4f6c-b1e5-8a2d7c3f9b1e");
// For ClrMD's magic hand shake
private const ulong MagicCallbackConstant = 0x43;
@@ -31,6 +32,7 @@ internal sealed unsafe class DataTargetWrapper : COMCallableIUnknown
private readonly IModuleService _moduleService;
private readonly IThreadUnwindService _threadUnwindService;
private readonly IRemoteMemoryService _remoteMemoryService;
+ private readonly IClrSymbolProvider _symbolProvider;
private readonly ulong _ignoreAddressBitsMask;
public IntPtr IDataTarget { get; }
@@ -47,6 +49,7 @@ public DataTargetWrapper(IServiceProvider services, IRuntime runtime)
_threadUnwindService = services.GetService();
_moduleService = services.GetService();
_remoteMemoryService = services.GetService();
+ _symbolProvider = services.GetService();
_ignoreAddressBitsMask = _memoryService.SignExtensionMask();
VTableBuilder builder = AddInterface(IID_ICLRDataTarget, false);
@@ -73,6 +76,11 @@ public DataTargetWrapper(IServiceProvider services, IRuntime runtime)
builder.AddMethod(new GetContractDescriptorDelegate(GetContractDescriptor));
builder.Complete();
+ builder = AddInterface(IID_ICLRSymbolProvider, false);
+ builder.AddMethod(new TryGetSymbolNameDelegate(TryGetSymbolName));
+ builder.AddMethod(new TryGetSymbolAddressDelegate(TryGetSymbolAddress));
+ builder.Complete();
+
AddRef();
}
@@ -378,6 +386,109 @@ private int GetContractDescriptor(
#endregion
+ #region ICLRSymbolProvider
+
+ private int TryGetSymbolName(
+ IntPtr self,
+ ulong address,
+ uint cchName,
+ char* pName,
+ uint* pcchNameActual,
+ ulong* pDisplacement)
+ {
+ if (cchName > int.MaxValue)
+ {
+ return HResult.E_INVALIDARG;
+ }
+
+ try
+ {
+ if (_symbolProvider is null)
+ {
+ return HResult.E_NOTIMPL;
+ }
+
+ if (!_symbolProvider.TryGetSymbolName(address, out string symbolName, out ulong displacement)
+ || string.IsNullOrEmpty(symbolName))
+ {
+ return HResult.E_FAIL;
+ }
+
+ if (pcchNameActual != null)
+ {
+ *pcchNameActual = (uint)symbolName.Length + 1;
+ }
+ if (pDisplacement != null)
+ {
+ *pDisplacement = displacement;
+ }
+
+ if (cchName == 0 || pName == null)
+ {
+ return HResult.S_OK;
+ }
+
+ int copy = Math.Min(symbolName.Length, (int)cchName - 1);
+ for (int i = 0; i < copy; i++)
+ {
+ pName[i] = symbolName[i];
+ }
+ pName[copy] = '\0';
+ return copy < symbolName.Length ? HResult.S_FALSE : HResult.S_OK;
+ }
+ catch
+ {
+ return HResult.E_FAIL;
+ }
+ }
+
+ private int TryGetSymbolAddress(
+ IntPtr self,
+ ulong moduleBase,
+ string name,
+ ulong* pAddress)
+ {
+ if (pAddress == null)
+ {
+ return HResult.E_INVALIDARG;
+ }
+ *pAddress = 0;
+
+ try
+ {
+ if (_symbolProvider is null)
+ {
+ return HResult.E_NOTIMPL;
+ }
+
+ if (string.IsNullOrEmpty(name))
+ {
+ return HResult.E_INVALIDARG;
+ }
+
+ // Bare symbol names only — '!' is reserved as the SOS module
+ // separator and is not produced by any of the mangling toolchains
+ // we target.
+ if (name.IndexOf('!') >= 0)
+ {
+ return HResult.E_INVALIDARG;
+ }
+
+ if (_symbolProvider.TryGetSymbolAddress(moduleBase, name, out ulong address) && address != 0)
+ {
+ *pAddress = address;
+ return HResult.S_OK;
+ }
+ return HResult.E_FAIL;
+ }
+ catch
+ {
+ return HResult.E_FAIL;
+ }
+ }
+
+ #endregion
+
#region ICLRDataTarget delegates
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
@@ -522,5 +633,25 @@ private delegate int GetContractDescriptorDelegate(
[Out] out ulong address);
#endregion
+
+ #region ICLRSymbolProvider delegates
+
+ [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+ private delegate int TryGetSymbolNameDelegate(
+ [In] IntPtr self,
+ [In] ulong address,
+ [In] uint cchName,
+ [Out] char* pName,
+ [Out] uint* pcchNameActual,
+ [Out] ulong* pDisplacement);
+
+ [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+ private delegate int TryGetSymbolAddressDelegate(
+ [In] IntPtr self,
+ [In] ulong moduleBase,
+ [In][MarshalAs(UnmanagedType.LPWStr)] string name,
+ [Out] ulong* pAddress);
+
+ #endregion
}
}
From 139973572bc26b3d955b75719ed5f40a6166e697 Mon Sep 17 00:00:00 2001
From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com>
Date: Wed, 17 Jun 2026 10:15:56 -0400
Subject: [PATCH 2/2] Address PR review feedback
- 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>
---
.../HostSymbolProvider.cs | 14 ++++++++------
.../ServiceManager.cs | 11 +++++++++--
.../IHostExtension.cs | 12 ++++++++----
src/SOS/SOS.Hosting/DataTargetWrapper.cs | 4 ++++
4 files changed, 29 insertions(+), 12 deletions(-)
diff --git a/src/Microsoft.Diagnostics.DebugServices.Implementation/HostSymbolProvider.cs b/src/Microsoft.Diagnostics.DebugServices.Implementation/HostSymbolProvider.cs
index 8103e37847..5ab9ffc3e7 100644
--- a/src/Microsoft.Diagnostics.DebugServices.Implementation/HostSymbolProvider.cs
+++ b/src/Microsoft.Diagnostics.DebugServices.Implementation/HostSymbolProvider.cs
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.IO;
using Microsoft.Diagnostics.Runtime;
namespace Microsoft.Diagnostics.DebugServices.Implementation
@@ -10,19 +9,18 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
///
/// Adapter exposing the host's /
/// through ClrMD's
- /// contract. Registered as a per-target
- /// service so both ClrMD (via )
- /// and SOS's data-target CCW can resolve symbols through one shared
- /// implementation. Returns symbols in "Module!Symbol" form.
+ /// contract.
///
[ServiceExport(Type = typeof(IClrSymbolProvider), Scope = ServiceScope.Target)]
public sealed class HostSymbolProvider : IClrSymbolProvider
{
private readonly IModuleService _moduleService;
+ private readonly ulong _signExtensionMask;
- public HostSymbolProvider(IModuleService moduleService)
+ public HostSymbolProvider(IModuleService moduleService, IMemoryService memoryService)
{
_moduleService = moduleService ?? throw new ArgumentNullException(nameof(moduleService));
+ _signExtensionMask = memoryService?.SignExtensionMask() ?? ulong.MaxValue;
}
public bool TryGetSymbolName(ulong address, out string symbolName, out ulong displacement)
@@ -30,6 +28,8 @@ public bool TryGetSymbolName(ulong address, out string symbolName, out ulong dis
symbolName = null;
displacement = 0;
+ address &= _signExtensionMask;
+
IModule module;
try
{
@@ -71,6 +71,8 @@ public bool TryGetSymbolAddress(ulong moduleBase, string name, out ulong address
return false;
}
+ moduleBase &= _signExtensionMask;
+
// moduleBase != 0 restricts the search to a single module.
if (moduleBase != 0)
{
diff --git a/src/Microsoft.Diagnostics.DebugServices.Implementation/ServiceManager.cs b/src/Microsoft.Diagnostics.DebugServices.Implementation/ServiceManager.cs
index d088a2fdb0..d4375b2f02 100644
--- a/src/Microsoft.Diagnostics.DebugServices.Implementation/ServiceManager.cs
+++ b/src/Microsoft.Diagnostics.DebugServices.Implementation/ServiceManager.cs
@@ -201,8 +201,15 @@ private static void InvokeHostExtension(Type type)
{
throw new InvalidOperationException($"IHostExtension implementation '{type.FullName}' must have a public parameterless constructor.");
}
- IHostExtension extension = (IHostExtension)Activator.CreateInstance(type);
- extension.Initialize();
+ try
+ {
+ IHostExtension extension = (IHostExtension)Activator.CreateInstance(type);
+ extension.Initialize();
+ }
+ catch (Exception ex) when (ex is not DiagnosticsException)
+ {
+ throw new DiagnosticsException($"IHostExtension '{type.FullName}' initialization failed: {ex.Message}", ex);
+ }
}
///
diff --git a/src/Microsoft.Diagnostics.DebugServices/IHostExtension.cs b/src/Microsoft.Diagnostics.DebugServices/IHostExtension.cs
index 71bf63f3ca..c6dedee9f6 100644
--- a/src/Microsoft.Diagnostics.DebugServices/IHostExtension.cs
+++ b/src/Microsoft.Diagnostics.DebugServices/IHostExtension.cs
@@ -8,10 +8,14 @@ namespace Microsoft.Diagnostics.DebugServices
/// (for example registering an IClrInfoProvider) when the extension
/// is loaded.
///
- /// Implementations must have a public parameterless constructor. They are
- /// discovered and invoked exactly once per extension assembly during
- /// assembly registration, before any other
- /// service or provider exports from the assembly are consumed.
+ /// Implementations must have a public parameterless constructor. Every
+ /// concrete implementation discovered in an
+ /// extension assembly is instantiated and its
+ /// method invoked once during assembly
+ /// registration, before any other service or provider exports from the
+ /// assembly are consumed. An assembly may contain multiple
+ /// implementations; invocation order across implementations is
+ /// unspecified.
///
public interface IHostExtension
{
diff --git a/src/SOS/SOS.Hosting/DataTargetWrapper.cs b/src/SOS/SOS.Hosting/DataTargetWrapper.cs
index fda02b6202..0a6690a9b2 100644
--- a/src/SOS/SOS.Hosting/DataTargetWrapper.cs
+++ b/src/SOS/SOS.Hosting/DataTargetWrapper.cs
@@ -401,6 +401,8 @@ private int TryGetSymbolName(
return HResult.E_INVALIDARG;
}
+ address &= _ignoreAddressBitsMask;
+
try
{
if (_symbolProvider is null)
@@ -454,6 +456,8 @@ private int TryGetSymbolAddress(
}
*pAddress = 0;
+ moduleBase &= _ignoreAddressBitsMask;
+
try
{
if (_symbolProvider is null)