See the License for the specific language governing permissions and
limitations under the License.
-License notice for ParallelStacks.Runtime
------------------------------------------
-
-Source found at https://github.com/chrisnas/DebuggingExtensions
-
-MIT License
-
-Copyright (c) 2016-2019 Nasarre Christophe
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
<Uri>https://github.com/dotnet/symstore</Uri>
<Sha>3ed87724fe4e98c7ecc77617720591783ee2e676</Sha>
</Dependency>
- <Dependency Name="Microsoft.Diagnostics.Runtime" Version="2.0.216202">
+ <Dependency Name="Microsoft.Diagnostics.Runtime" Version="2.0.218001">
<Uri>https://github.com/Microsoft/clrmd</Uri>
<Sha>8b1eadaa0dd50fdd05419764f5606914da56ac9e</Sha>
</Dependency>
- <Dependency Name="Microsoft.Diagnostics.Runtime.Utilities" Version="2.0.216202">
+ <Dependency Name="Microsoft.Diagnostics.Runtime.Utilities" Version="2.0.218001">
<Uri>https://github.com/Microsoft/clrmd</Uri>
<Sha>8b1eadaa0dd50fdd05419764f5606914da56ac9e</Sha>
</Dependency>
<MicrosoftWin32PrimitivesVersion>4.3.0</MicrosoftWin32PrimitivesVersion>
<!-- Other libs -->
<MicrosoftBclAsyncInterfacesVersion>1.1.0</MicrosoftBclAsyncInterfacesVersion>
- <MicrosoftDiagnosticsRuntimeVersion>2.0.216202</MicrosoftDiagnosticsRuntimeVersion>
- <MicrosoftDiagnosticsRuntimeUtilitiesVersion>2.0.216202</MicrosoftDiagnosticsRuntimeUtilitiesVersion>
- <ParallelStacksRuntimeVersion>2.0.1</ParallelStacksRuntimeVersion>
+ <MicrosoftDiagnosticsRuntimeVersion>2.0.218001</MicrosoftDiagnosticsRuntimeVersion>
+ <MicrosoftDiagnosticsRuntimeUtilitiesVersion>2.0.218001</MicrosoftDiagnosticsRuntimeUtilitiesVersion>
<MicrosoftDiaSymReaderNativePackageVersion>1.7.0</MicrosoftDiaSymReaderNativePackageVersion>
<MicrosoftDiagnosticsTracingTraceEventVersion>2.0.64</MicrosoftDiagnosticsTracingTraceEventVersion>
<MicrosoftExtensionsLoggingVersion>2.1.1</MicrosoftExtensionsLoggingVersion>
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Microsoft.Diagnostics.Runtime;
-using Microsoft.SymbolStore;
-using Microsoft.SymbolStore.KeyGenerators;
-using System.Collections.Immutable;
-using System.Diagnostics;
-using System.Threading.Tasks;
-
-namespace Microsoft.Diagnostics.DebugServices.Implementation
-{
-#nullable enable
-
- /// <summary>
- /// A ClrMD symbol locator that search binaries based on files loaded in the live Linux target.
- /// </summary>
- internal class BinaryLocator : IBinaryLocator
- {
- private readonly ISymbolService _symbolService;
-
- public BinaryLocator(ITarget target)
- {
- _symbolService = target.Services.GetService<ISymbolService>();
- }
-
- public string? FindBinary(string fileName, int buildTimeStamp, int imageSize, bool checkProperties)
- {
- Trace.TraceInformation($"FindBinary: {fileName} buildTimeStamp {buildTimeStamp:X8} imageSize {imageSize:X8}");
-
- if (_symbolService.IsSymbolStoreEnabled)
- {
- SymbolStoreKey? key = PEFileKeyGenerator.GetKey(fileName, (uint)buildTimeStamp, (uint)imageSize);
- if (key != null)
- {
- // Now download the module from the symbol server, cache or from a directory
- return _symbolService.DownloadFile(key);
- }
- else
- {
- Trace.TraceInformation($"FindBinary: {fileName}: key not generated");
- }
- }
- else
- {
- Trace.TraceInformation($"FindBinary: {fileName}: symbol store not enabled");
- }
-
- return null;
- }
-
- public string? FindBinary(string fileName, ImmutableArray<byte> buildId, bool checkProperties)
- {
- Trace.TraceInformation($"FindBinary: {fileName} buildid {buildId}");
- return null;
- }
-
- public Task<string?> FindBinaryAsync(string fileName, ImmutableArray<byte> buildId, bool checkProperties)
- {
- Trace.TraceInformation($"FindBinaryAsync: {fileName} buildid {buildId}");
- return Task.FromResult<string?>(null);
- }
-
- public Task<string?> FindBinaryAsync(string fileName, int buildTimeStamp, int imageSize, bool checkProperties)
- {
- Trace.TraceInformation($"FindBinaryAsync: {fileName} buildTimeStamp {buildTimeStamp:X8} imageSize {imageSize:X8}");
- return Task.FromResult<string?>(null);
- }
- }
-}
data = block.GetReader().ReadBytes(size);
ApplyRelocations(module, reader, rva, data);
}
+ else
+ {
+ Trace.TraceError($"ReadMemory: FAILED rva {rva:X8}");
+ }
}
return data;
uint read = virtualAddressReader.Read(rva, data, 0, (uint)bytesRequested);
if (read == 0)
{
+ Trace.TraceError($"ReadMemory: FAILED rva {rva:X8}");
data = null;
}
return data;
_recursionProtection.Remove(module.ImageBase);
}
}
+ else
+ {
+ Trace.TraceError("ReadMemory: recursion");
+ }
}
return null;
}
}
else
{
- if (SymbolService.IsSymbolStoreEnabled)
+ if (module.IndexTimeStamp.HasValue && module.IndexFileSize.HasValue)
{
- if (module.IndexTimeStamp.HasValue && module.IndexFileSize.HasValue)
+ SymbolStoreKey key = PEFileKeyGenerator.GetKey(Path.GetFileName(module.FileName), module.IndexTimeStamp.Value, module.IndexFileSize.Value);
+ if (key is not null)
{
- SymbolStoreKey key = PEFileKeyGenerator.GetKey(Path.GetFileName(module.FileName), module.IndexTimeStamp.Value, module.IndexFileSize.Value);
- if (key != null)
- {
- // Now download the module from the symbol server
- downloadFilePath = SymbolService.DownloadFile(key);
- }
+ // Now download the module from the symbol server
+ downloadFilePath = SymbolService.DownloadFile(key);
+ }
+ else
+ {
+ Trace.TraceWarning($"GetPEReader: no index generated for module {module.FileName} ");
}
}
+ else
+ {
+ Trace.TraceWarning($"GetPEReader: module {module.FileName} has no index timestamp/filesize");
+ }
}
if (!string.IsNullOrEmpty(downloadFilePath))
reader = new PEReader(stream);
if (reader.PEHeaders == null || reader.PEHeaders.PEHeader == null)
{
+ Trace.TraceError($"GetPEReader: PEReader invalid headers");
return null;
}
}
}
else
{
- if (SymbolService.IsSymbolStoreEnabled)
+ if (!module.BuildId.IsDefaultOrEmpty)
{
- if (!module.BuildId.IsDefaultOrEmpty)
+ SymbolStoreKey key = ELFFileKeyGenerator.GetKeys(KeyTypeFlags.IdentityKey, module.FileName, module.BuildId.ToArray(), symbolFile: false, symbolFileName: null).SingleOrDefault();
+ if (key is not null)
{
- var key = ELFFileKeyGenerator.GetKeys(KeyTypeFlags.IdentityKey, module.FileName, module.BuildId.ToArray(), symbolFile: false, symbolFileName: null).SingleOrDefault();
- if (key != null)
- {
- // Now download the module from the symbol server
- downloadFilePath = SymbolService.DownloadFile(key);
- }
+ // Now download the module from the symbol server
+ downloadFilePath = SymbolService.DownloadFile(key);
+ }
+ else
+ {
+ Trace.TraceWarning($"GetELFFile: no index generated for module {module.FileName} ");
}
}
+ else
+ {
+ Trace.TraceWarning($"GetELFFile: module {module.FileName} has no build id");
+ }
}
if (!string.IsNullOrEmpty(downloadFilePath))
elfFile = new ELFFile(new StreamAddressSpace(stream), position: 0, isDataSourceVirtualAddressSpace: false);
if (!elfFile.IsValid())
{
+ Trace.TraceError($"GetELFFile: not a valid file");
return null;
}
}
}
else
{
- if (SymbolService.IsSymbolStoreEnabled)
+ if (!module.BuildId.IsDefaultOrEmpty)
{
- if (!module.BuildId.IsDefaultOrEmpty)
+ SymbolStoreKey key = MachOFileKeyGenerator.GetKeys(KeyTypeFlags.IdentityKey, module.FileName, module.BuildId.ToArray(), symbolFile: false, symbolFileName: null).SingleOrDefault();
+ if (key is not null)
{
- var key = MachOFileKeyGenerator.GetKeys(KeyTypeFlags.IdentityKey, module.FileName, module.BuildId.ToArray(), symbolFile: false, symbolFileName: null).SingleOrDefault();
- if (key != null)
- {
- // Now download the module from the symbol server
- downloadFilePath = SymbolService.DownloadFile(key);
- }
+ // Now download the module from the symbol server
+ downloadFilePath = SymbolService.DownloadFile(key);
}
+ else
+ {
+ Trace.TraceWarning($"GetMachOFile: no index generated for module {module.FileName} ");
+ }
+ }
+ else
+ {
+ Trace.TraceWarning($"GetMachOFile: module {module.FileName} has no index timestamp/filesize");
}
}
machoFile = new MachOFile(new StreamAddressSpace(stream), position: 0, dataSourceIsVirtualAddressSpace: false);
if (!machoFile.IsValid())
{
+ Trace.TraceError($"GetMachOFile: not a valid file");
return null;
}
}
/// </summary>
public class ModuleServiceFromDataReader : ModuleService
{
- class ModuleFromDataReader : Module
+ class ModuleFromDataReader : Module, IExportSymbols
{
// This is what clrmd returns for non-PE modules that don't have a timestamp
private const uint InvalidTimeStamp = 0;
private static readonly VersionInfo EmptyVersionInfo = new VersionInfo(0, 0, 0, 0);
private readonly ModuleServiceFromDataReader _moduleService;
+ private readonly IExportReader _exportReader;
private readonly ModuleInfo _moduleInfo;
private readonly ulong _imageSize;
private string _versionString;
- public ModuleFromDataReader(ModuleServiceFromDataReader moduleService, int moduleIndex, ModuleInfo moduleInfo, ulong imageSize)
+ public ModuleFromDataReader(ModuleServiceFromDataReader moduleService, IExportReader exportReader, int moduleIndex, ModuleInfo moduleInfo, ulong imageSize)
: base(moduleService.Target)
{
_moduleService = moduleService;
_moduleInfo = moduleInfo;
_imageSize = imageSize;
+ _exportReader = exportReader;
ModuleIndex = moduleIndex;
+ if (exportReader is not null)
+ {
+ ServiceProvider.AddService<IExportSymbols>(this);
+ }
}
#region IModule
#endregion
+ #region IExportSymbols
+
+ public bool TryGetSymbolAddress(string name, out ulong address)
+ {
+ if (_exportReader is not null)
+ {
+ return _exportReader.TryGetSymbolAddress(ImageBase, name, out address);
+ }
+ address = 0;
+ return false;
+ }
+
+ #endregion
+
protected override ModuleService ModuleService => _moduleService;
}
var modules = new Dictionary<ulong, IModule>();
int moduleIndex = 0;
+ IExportReader exportReader = _dataReader as IExportReader;
ModuleInfo[] moduleInfos = _dataReader.EnumerateModules().OrderBy((info) => info.ImageBase).ToArray();
for (int i = 0; i < moduleInfos.Length; i++)
{
imageSize = startNext - start;
}
}
- var module = new ModuleFromDataReader(this, moduleIndex, moduleInfo, imageSize);
+ var module = new ModuleFromDataReader(this, exportReader, moduleIndex, moduleInfo, imageSize);
try
{
modules.Add(moduleInfo.ImageBase, module);
public string GetDacFilePath()
{
- if (_dacFilePath == null)
+ if (_dacFilePath is null)
{
string dacFileName = GetDacFileName();
_dacFilePath = GetLocalDacPath(dacFileName);
- if (_dacFilePath == null)
+ if (_dacFilePath is null)
{
_dacFilePath = DownloadFile(dacFileName);
}
public string GetDbiFilePath()
{
- if (_dbiFilePath == null)
+ if (_dbiFilePath is null)
{
string dbiFileName = GetDbiFileName();
_dbiFilePath = GetLocalPath(dbiFileName);
- if (_dbiFilePath == null)
+ if (_dbiFilePath is null)
{
_dbiFilePath = DownloadFile(dbiFileName);
}
/// </summary>
private ClrRuntime CreateRuntime()
{
- if (_clrRuntime == null)
+ if (_clrRuntime is null)
{
string dacFilePath = GetDacFilePath();
- if (dacFilePath != null)
+ if (dacFilePath is not null)
{
Trace.TraceInformation($"Creating ClrRuntime #{Id} {dacFilePath}");
try
if (platform == OSPlatform.Windows)
{
- // Use the coreclr.dll's id (timestamp/filesize) to download the the dac module.
- if (RuntimeModule.IndexTimeStamp.HasValue && RuntimeModule.IndexFileSize.HasValue)
+ // It is the coreclr.dll's id (timestamp/filesize) in the DacInfo used to download the the dac module.
+ if (_clrInfo.DacInfo.IndexTimeStamp != 0 && _clrInfo.DacInfo.IndexFileSize != 0)
{
- key = PEFileKeyGenerator.GetKey(fileName, RuntimeModule.IndexTimeStamp.Value, RuntimeModule.IndexFileSize.Value);
+ key = PEFileKeyGenerator.GetKey(fileName, (uint)_clrInfo.DacInfo.IndexTimeStamp, (uint)_clrInfo.DacInfo.IndexFileSize);
}
else
{
else
{
// Use the runtime's build id to download the the dac module.
- if (!RuntimeModule.BuildId.IsDefaultOrEmpty)
+ if (!_clrInfo.DacInfo.ClrBuildId.IsDefaultOrEmpty)
{
+ byte[] buildId = _clrInfo.DacInfo.ClrBuildId.ToArray();
IEnumerable<SymbolStoreKey> keys = null;
if (platform == OSPlatform.Linux)
{
- keys = ELFFileKeyGenerator.GetKeys(KeyTypeFlags.DacDbiKeys, RuntimeModule.FileName, RuntimeModule.BuildId.ToArray(), symbolFile: false, symbolFileName: null);
+ keys = ELFFileKeyGenerator.GetKeys(KeyTypeFlags.DacDbiKeys, "libcoreclr.so", buildId, symbolFile: false, symbolFileName: null);
}
else if (platform == OSPlatform.OSX)
{
- keys = MachOFileKeyGenerator.GetKeys(KeyTypeFlags.DacDbiKeys, RuntimeModule.FileName, RuntimeModule.BuildId.ToArray(), symbolFile: false, symbolFileName: null);
+ keys = MachOFileKeyGenerator.GetKeys(KeyTypeFlags.DacDbiKeys, "libcoreclr.dylib", buildId, symbolFile: false, symbolFileName: null);
}
else
{
}
}
- if (key != null)
+ if (key is not null)
{
// Now download the DAC module from the symbol server
filePath = SymbolService.DownloadFile(key);
var sb = new StringBuilder();
string config = s_runtimeTypeNames[(int)RuntimeType];
sb.AppendLine($"#{Id} {config} runtime at {RuntimeModule.ImageBase:X16} size {RuntimeModule.ImageSize:X8}");
- sb.AppendLine($" Runtime module path: {RuntimeModule.FileName}");
- if (_dacFilePath != null) {
+ if (_clrInfo.SingleFileRuntimeInfo.HasValue) {
+ sb.AppendLine($" Single-file runtime module path: {RuntimeModule.FileName}");
+ }
+ else {
+ sb.AppendLine($" Runtime module path: {RuntimeModule.FileName}");
+ }
+ if (_dacFilePath is not null) {
sb.AppendLine($" DAC: {_dacFilePath}");
}
- if (_dbiFilePath != null) {
+ if (_dbiFilePath is not null) {
sb.AppendLine($" DBI: {_dbiFilePath}");
}
return sb.ToString();
/// <summary>
/// ClrMD runtime service implementation
/// </summary>
- public class RuntimeService : IRuntimeService, IDataReader
+ public class RuntimeService : IRuntimeService, IDataReader, IExportReader
{
private readonly ITarget _target;
private readonly IDisposable _onFlushEvent;
{
_target = target;
_onFlushEvent = target.OnFlushEvent.Register(() => {
- if (_runtimes != null && _runtimes.Count == 0)
+ if (_runtimes is not null && _runtimes.Count == 0)
{
// If there are no runtimes, try find them again when the target stops
_runtimes = null;
{
get
{
- if (_currentRuntime == null) {
+ if (_currentRuntime is null) {
_currentRuntime = FindRuntime();
}
return _currentRuntime;
/// <param name="runtimeId">runtime id</param>
public void SetCurrentRuntime(int runtimeId)
{
- if (_runtimes == null || runtimeId >= _runtimes.Count) {
+ if (_runtimes is null || runtimeId >= _runtimes.Count) {
throw new DiagnosticsException($"Invalid runtime id {runtimeId}");
}
_currentRuntime = _runtimes[runtimeId];
#endregion
+ #region IExportReader
+
+ bool IExportReader.TryGetSymbolAddress(ulong baseAddress, string name, out ulong offset)
+ {
+ try
+ {
+ IExportSymbols exportSymbols = ModuleService.GetModuleFromBaseAddress(baseAddress).Services.GetService<IExportSymbols>();
+ if (exportSymbols is not null)
+ {
+ return exportSymbols.TryGetSymbolAddress(name, out offset);
+ }
+ }
+ catch (DiagnosticsException)
+ {
+ }
+ offset = 0;
+ return false;
+ }
+
+ #endregion
+
/// <summary>
/// Find the runtime
/// </summary>
}
}
// If no .NET Core runtime, then check for desktop runtime
- if (runtime == null)
+ if (runtime is null)
{
foreach (Runtime r in runtimes)
{
private IEnumerable<Runtime> BuildRuntimes()
{
- if (_runtimes == null)
+ if (_runtimes is null)
{
_runtimes = new List<Runtime>();
- if (_dataTarget == null)
+ if (_dataTarget is null)
{
- _dataTarget = new DataTarget(new CustomDataTarget(this) {
- BinaryLocator = new BinaryLocator(_target)
- });
+ // Don't use the default binary locator or provide one. clrmd uses it to download the DAC, download assemblies
+ // to get metadata in its data target or for invalid memory region mapping and we already do all of that.
+ _dataTarget = new DataTarget(new CustomDataTarget(this)) {
+ BinaryLocator = null
+ };
}
- if (_dataTarget != null)
+ if (_dataTarget is not null)
{
for (int i = 0; i < _dataTarget.ClrVersions.Length; i++)
{
public override string ToString()
{
var sb = new StringBuilder();
- if (_runtimeModuleDirectory != null) {
+ if (_runtimeModuleDirectory is not null) {
sb.AppendLine($"Runtime module path: {_runtimeModuleDirectory}");
}
- if (_runtimes != null)
+ if (_runtimes is not null)
{
foreach (IRuntime runtime in _runtimes)
{
public override int Read(byte[] buffer, int offset, int count)
{
if (Position + count > Length) {
- throw new ArgumentOutOfRangeException();
+ return 0;
}
if (_memoryService.ReadMemory(_address + (ulong)Position, new Span<byte>(buffer, offset, count), out int bytesRead)) {
Position += bytesRead;
using Microsoft.Diagnostics.DebugServices;
using Microsoft.Diagnostics.Runtime;
using System;
+using System.Linq;
namespace Microsoft.Diagnostics.ExtensionCommands
{
{
if (Verbose)
{
- WriteLine("{0}", module.Name);
+ WriteLine("{0}{1}", module.Name, module.IsDynamic ? "(Dynamic)" : "");
WriteLine(" AssemblyName: {0}", module.AssemblyName);
WriteLine(" ImageBase: {0:X16}", module.ImageBase);
WriteLine(" Size: {0:X8}", module.Size);
}
else
{
- WriteLine("{0:X16} {1:X8} {2}", module.ImageBase, module.Size, module.Name);
+ WriteLine("{0:X16} {1:X8} {2}{3}", module.ImageBase, module.Size, module.Name, module.IsDynamic ? "(Dynamic)" : "");
}
}
}
<ItemGroup>
<ProjectReference Include="..\Microsoft.Diagnostics.DebugServices\Microsoft.Diagnostics.DebugServices.csproj" />
</ItemGroup>
-
- <ItemGroup>
- <Folder Include="ParallelStacks.Runtime\" />
- </ItemGroup>
</Project>