<add key="dotnet5-transport" value="https://dnceng.pkgs.visualstudio.com/public/_packaging/dotnet5-transport/nuget/v3/index.json" />
<add key="dotnet-tools" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json" />
<add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" />
+ <add key="dotnet-diagnostics-tests" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-diagnostics-tests/nuget/v3/index.json" />
<!-- Legacy feeds -->
- <add key="dotnet-buildtools" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/myget-legacy/nuget/v3/index.json" />
<add key="dotnet-core" value="https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json" />
<!-- Standard feeds -->
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
```
or
```
- SOS does not support the current target architecture 'arm32' (0x01c4). A 32 bit target may require a 64 bit debugger or vice versa.
+ SOS does not support the current target architecture 'arm32' (0x01c4). A 32 bit target may require a 32 bit debugger or vice versa. In general, try to use the same bitness for the debugger and target process.
```
- You may need a different bitness of the Windows (windbg/cdb) debugger or dotnet-dump. If you are running an x64 (64 bit), try an x86 (32 bit) version. The easiest way to get an x86 version of dotnet-dump is installing the "single-file" version [here](https://aka.ms/dotnet-dump/win-x86). For more information on single-file tools see [here](https://github.com/dotnet/diagnostics/blob/master/documentation/single-file-tools.md#single-file-diagnostic-tools).
\ No newline at end of file
+ You may need a different bitness of the Windows (windbg/cdb) debugger or dotnet-dump. If you are running an x64 (64 bit), try an x86 (32 bit) version. The easiest way to get an x86 version of dotnet-dump is installing the "single-file" version [here](https://aka.ms/dotnet-dump/win-x86). For more information on single-file tools see [here](https://github.com/dotnet/diagnostics/blob/master/documentation/single-file-tools.md#single-file-diagnostic-tools).
public abstract ulong ImageSize { get; }
- public abstract int IndexFileSize { get; }
+ public abstract uint? IndexFileSize { get; }
- public abstract int IndexTimeStamp { get; }
+ public abstract uint? IndexTimeStamp { get; }
public bool IsPEImage
{
flags |= isVirtual ? Module.Flags.IsLoadedLayout : Module.Flags.IsFileLayout;
return peImage;
}
+ else
+ {
+ Trace.TraceError($"GetPEInfo: PE invalid {address:X16} isVirtual {isVirtual}");
+ }
}
catch (Exception ex) when (ex is BadImageFormatException || ex is EndOfStreamException || ex is IOException)
{
- Trace.TraceError($"GetPEInfo: loaded {address:X16} exception {ex.Message}");
+ Trace.TraceError($"GetPEInfo: loaded {address:X16} isVirtual {isVirtual} exception {ex.Message}");
}
return null;
}
{
if (SymbolService.IsSymbolStoreEnabled)
{
- SymbolStoreKey key = PEFileKeyGenerator.GetKey(Path.GetFileName(module.FileName), (uint)module.IndexTimeStamp, (uint)module.IndexFileSize);
- if (key != null)
+ if (module.IndexTimeStamp.HasValue && module.IndexFileSize.HasValue)
{
- // Now download the module from the symbol server
- downloadFilePath = SymbolService.DownloadFile(key);
+ 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);
+ }
}
}
}
{
class ModuleFromDataReader : Module
{
+ // 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 ModuleInfo _moduleInfo;
public override ulong ImageSize => _imageSize;
- public override int IndexFileSize => _moduleInfo.IndexFileSize;
+ public override uint? IndexFileSize => _moduleInfo.IndexTimeStamp == InvalidTimeStamp ? null : (uint)_moduleInfo.IndexFileSize;
- public override int IndexTimeStamp => _moduleInfo.IndexTimeStamp;
+ public override uint? IndexTimeStamp => _moduleInfo.IndexTimeStamp == InvalidTimeStamp ? null : (uint)_moduleInfo.IndexTimeStamp;
public override VersionInfo? Version
{
}
else if (platform == OSPlatform.Windows)
{
- // Use the coreclr.dll's id (timestamp/filesize) to download the the dac module.
- key = PEFileKeyGenerator.GetKey(fileName, (uint)RuntimeModule.IndexTimeStamp, (uint)RuntimeModule.IndexFileSize);
+ if (RuntimeModule.IndexTimeStamp.HasValue && RuntimeModule.IndexFileSize.HasValue)
+ {
+ // Use the coreclr.dll's id (timestamp/filesize) to download the the dac module.
+ key = PEFileKeyGenerator.GetKey(fileName, RuntimeModule.IndexTimeStamp.Value, RuntimeModule.IndexFileSize.Value);
+ }
}
if (key != null)
{
var sb = new StringBuilder();
string config = s_runtimeTypeNames[(int)RuntimeType];
- sb.AppendLine($"#{Id} {config} runtime at {RuntimeModule.ImageBase:X16} size {RuntimeModule.IndexFileSize:X8}");
+ sb.AppendLine($"#{Id} {config} runtime at {RuntimeModule.ImageBase:X16} size {RuntimeModule.ImageSize:X8}");
sb.AppendLine($" Runtime module path: {RuntimeModule.FileName}");
if (_dacFilePath != null) {
sb.AppendLine($" DAC: {_dacFilePath}");
/// <summary>
/// Returns the list of runtimes in the target
/// </summary>
- public IEnumerable<IRuntime> Runtimes => BuildRuntimes();
+ public IEnumerable<IRuntime> EnumerateRuntimes() => BuildRuntimes();
/// <summary>
/// Returns the current runtime
IEnumerable<ModuleInfo> IDataReader.EnumerateModules() =>
ModuleService.EnumerateModules().Select((module) => CreateModuleInfo(module)).ToList();
- private ModuleInfo CreateModuleInfo(IModule module) =>
- new ModuleInfo(this, module.ImageBase, module.FileName, isVirtual:true, module.IndexFileSize, module.IndexTimeStamp, new ImmutableArray<byte>());
+ private ModuleInfo CreateModuleInfo(IModule module) =>
+ new ModuleInfo(
+ this,
+ module.ImageBase,
+ module.FileName,
+ isVirtual:true,
+ unchecked((int)module.IndexFileSize.GetValueOrDefault(0)),
+ unchecked((int)module.IndexTimeStamp.GetValueOrDefault(0)),
+ new ImmutableArray<byte>());
ImmutableArray<byte> IDataReader.GetBuildId(ulong baseAddress)
{
{
try
{
- byte[] registerContext = ThreadService.GetThreadInfoFromId(threadId).GetThreadContext();
+ byte[] registerContext = ThreadService.GetThreadFromId(threadId).GetThreadContext();
context = new Span<byte>(registerContext);
return true;
}
// See the LICENSE file in the project root for more information.
using System;
+using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Microsoft.Diagnostics.DebugServices.Implementation
public uint ThreadId { get; }
- public bool GetRegisterValue(int index, out ulong value)
+ public bool TryGetRegisterValue(int index, out ulong value)
{
value = 0;
- if (_threadService.GetRegisterInfo(index, out RegisterInfo info))
+ if (_threadService.TryGetRegisterInfo(index, out RegisterInfo info))
{
try
{
case 8:
value = MemoryMarshal.Read<ulong>(threadContext);
return true;
+ default:
+ Trace.TraceError($"GetRegisterValue: 0x{ThreadId:X4} {info.RegisterName} invalid size {info.RegisterSize}");
+ break;
}
}
- catch (DiagnosticsException)
+ catch (DiagnosticsException ex)
{
+ Trace.TraceError($"GetRegisterValue: 0x{ThreadId:X4} {info.RegisterName} {ex}");
}
}
return false;
/// <param name="name">register name</param>
/// <param name="index">returns register index or -1</param>
/// <returns>true if name found</returns>
- public bool GetRegisterIndexByName(string name, out int index)
+ public bool TryGetRegisterIndexByName(string name, out int index)
{
if (_lookupByName.TryGetValue(name, out RegisterInfo info))
{
/// <param name="index">register index</param>
/// <param name="info">RegisterInfo</param>
/// <returns>true if index found</returns>
- public bool GetRegisterInfo(int index, out RegisterInfo info)
+ public bool TryGetRegisterInfo(int index, out RegisterInfo info)
{
return _lookupByIndex.TryGetValue(index, out info);
}
/// <param name="threadIndex">index</param>
/// <returns>thread info</returns>
/// <exception cref="DiagnosticsException">invalid thread index</exception>
- public IThread GetThreadInfoFromIndex(int threadIndex)
+ public IThread GetThreadFromIndex(int threadIndex)
{
try
{
/// <param name="threadId">os id</param>
/// <returns>thread info</returns>
/// <exception cref="DiagnosticsException">invalid thread id</exception>
- public IThread GetThreadInfoFromId(uint threadId)
+ public IThread GetThreadFromId(uint threadId)
{
if (!GetThreads().TryGetValue(threadId, out IThread thread)) {
throw new DiagnosticsException($"Invalid thread id: {threadId}");
using Microsoft.Diagnostics.Runtime.DataReaders.Implementation;
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
--- /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 System;
+
+namespace Microsoft.Diagnostics.DebugServices
+{
+ /// <summary>
+ /// Module export symbol lookup
+ /// </summary>
+ public interface IExportSymbols
+ {
+ /// <summary>
+ /// Returns the address of a module export symbol if found
+ /// </summary>
+ /// <param name="name">symbol name (without the module name prepended)</param>
+ /// <param name="offset">address returned</param>
+ /// <returns>true if found</returns>
+ bool TryGetSymbolAddress(string name, out ulong offset);
+ }
+}
// See the LICENSE file in the project root for more information.
using System;
+using System.Collections;
+using System.Collections.Generic;
namespace Microsoft.Diagnostics.DebugServices
{
/// </summary>
IServiceProvider Services { get; }
+ /// <summary>
+ /// Enumerates all the targets
+ /// </summary>
+ IEnumerable<ITarget> EnumerateTargets();
+
/// <summary>
/// Current target instances or null
/// </summary>
/// <summary>
/// Gets the specific file size of the image used to index it on the symbol server.
/// </summary>
- int IndexFileSize { get; }
+ uint? IndexFileSize { get; }
/// <summary>
/// Gets the timestamp of the image used to index it on the symbol server.
/// </summary>
- int IndexTimeStamp { get; }
+ uint? IndexTimeStamp { get; }
/// <summary>
/// Build id on Linux and MacOS, otherwise empty value.
--- /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 System;
+
+namespace Microsoft.Diagnostics.DebugServices
+{
+ /// <summary>
+ /// Module symbol lookup
+ /// </summary>
+ public interface IModuleSymbols
+ {
+ /// <summary>
+ /// Returns the symbol name and displacement if found
+ /// </summary>
+ /// <param name="address">address of symbol to find</param>
+ /// <param name="symbol">symbol name (without the module name prepended)</param>
+ /// <param name="displacement">offset from symbol</param>
+ /// <returns>true if found</returns>
+ bool TryGetSymbolName(ulong address, out string symbol, out ulong displacement);
+
+ /// <summary>
+ /// Returns the address of a module symbol if found
+ /// </summary>
+ /// <param name="name">symbol name (without the module name prepended)</param>
+ /// <param name="address">address of symbol</param>
+ /// <returns>true if found</returns>
+ bool TryGetSymbolAddress(string name, out ulong address);
+ }
+}
/// <summary>
/// Returns the list of runtimes in the target
/// </summary>
- public IEnumerable<IRuntime> Runtimes { get; }
+ IEnumerable<IRuntime> EnumerateRuntimes();
/// <summary>
/// Returns the current runtime or null if no runtime was found
/// </summary>
- public IRuntime CurrentRuntime { get; }
+ IRuntime CurrentRuntime { get; }
/// <summary>
/// Set the current runtime
/// <summary>
/// Invoked when anything changes in the symbol service (adding servers, caches, or directories, clearing store, etc.)
/// </summary>
- public IServiceEvent OnChangeEvent { get; }
+ IServiceEvent OnChangeEvent { get; }
/// <summary>
/// Returns true if symbol download has been enabled.
/// </summary>
- public bool IsSymbolStoreEnabled { get; }
+ bool IsSymbolStoreEnabled { get; }
/// <summary>
/// The default symbol cache path:
/// * dotnet-dump on Windows uses the VS symbol cache path: %TEMPDIR%\SymbolCache
/// * dotnet-dump/lldb on Linux/MacOS uses: $HOME/.dotnet/symbolcache
/// </summary>
- public string DefaultSymbolCache { get; set; }
+ string DefaultSymbolCache { get; set; }
/// <summary>
/// Parses the Windows debugger symbol path (srv*, cache*, etc.).
/// </summary>
/// <param name="symbolPath">Windows symbol path</param>
/// <returns>if false, error parsing symbol path</returns>
- public bool ParseSymbolPath(string symbolPath);
+ bool ParseSymbolPath(string symbolPath);
/// <summary>
/// Add symbol server to search path.
/// <param name="authToken"></param>
/// <param name="timeoutInMinutes">symbol server timeout in minutes (optional)</param>
/// <returns>if false, failure</returns>
- public bool AddSymbolServer(bool msdl, bool symweb, string symbolServerPath, string authToken, int timeoutInMinutes);
+ bool AddSymbolServer(bool msdl, bool symweb, string symbolServerPath, string authToken, int timeoutInMinutes);
/// <summary>
/// Add cache path to symbol search path
/// </summary>
/// <param name="symbolCachePath">symbol cache directory path (optional)</param>
- public void AddCachePath(string symbolCachePath);
+ void AddCachePath(string symbolCachePath);
/// <summary>
/// Add directory path to symbol search path
/// </summary>
/// <param name="symbolDirectoryPath">symbol directory path to search (optional)</param>
- public void AddDirectoryPath(string symbolDirectoryPath);
+ void AddDirectoryPath(string symbolDirectoryPath);
/// <summary>
/// This function disables any symbol downloading support.
/// </summary>
- public void DisableSymbolStore();
+ void DisableSymbolStore();
/// <summary>
/// Download a file from the symbol stores/server.
/// </summary>
/// <param name="key">index of the file to download</param>
/// <returns>path to the downloaded file either in the cache or in the temp directory or null if error</returns>
- public string DownloadFile(SymbolStoreKey key);
+ string DownloadFile(SymbolStoreKey key);
/// <summary>
/// Attempts to download/retrieve from cache the key.
/// </summary>
/// <param name="key">index of the file to retrieve</param>
/// <returns>stream or null</returns>
- public SymbolStoreFile GetSymbolStoreFile(SymbolStoreKey key);
+ SymbolStoreFile GetSymbolStoreFile(SymbolStoreKey key);
/// <summary>
/// Returns the metadata for the assembly
/// <param name="imageTimestamp">module timestamp</param>
/// <param name="imageSize">size of PE image</param>
/// <returns>metadata</returns>
- public ImmutableArray<byte> GetMetadata(string imagePath, uint imageTimestamp, uint imageSize);
+ ImmutableArray<byte> GetMetadata(string imagePath, uint imageTimestamp, uint imageSize);
}
}
/// <param name="registerIndex">register index</param>
/// <param name="value">value returned</param>
/// <returns>true if value found</returns>
- bool GetRegisterValue(int registerIndex, out ulong value);
+ bool TryGetRegisterValue(int registerIndex, out ulong value);
/// <summary>
/// Returns the raw context buffer bytes for the specified thread.
/// <param name="name">register name</param>
/// <param name="registerIndex">returns register index or -1</param>
/// <returns>true if name found</returns>
- bool GetRegisterIndexByName(string name, out int registerIndex);
+ bool TryGetRegisterIndexByName(string name, out int registerIndex);
/// <summary>
/// Returns the register info (name, offset, size, etc).
/// <param name="registerIndex">register index</param>
/// <param name="info">RegisterInfo</param>
/// <returns>true if index found</returns>
- bool GetRegisterInfo(int registerIndex, out RegisterInfo info);
+ bool TryGetRegisterInfo(int registerIndex, out RegisterInfo info);
/// <summary>
/// Current OS thread Id
/// <param name="threadIndex">index</param>
/// <returns>thread info</returns>
/// <exception cref="DiagnosticsException">invalid thread index</exception>
- IThread GetThreadInfoFromIndex(int threadIndex);
+ IThread GetThreadFromIndex(int threadIndex);
/// <summary>
/// Get the thread info from the OS thread id
/// <param name="threadId">os id</param>
/// <returns>thread info</returns>
/// <exception cref="DiagnosticsException">invalid thread id</exception>
- IThread GetThreadInfoFromId(uint threadId);
+ IThread GetThreadFromId(uint threadId);
}
}
// See the LICENSE file in the project root for more information.
using Microsoft.Diagnostics.DebugServices;
+using System.Diagnostics.Tracing;
using System.Linq;
namespace Microsoft.Diagnostics.ExtensionCommands
public override void Invoke()
{
ulong totalSize = 0;
- foreach (IModule module in ModuleService.EnumerateModules())
+ foreach (IModule module in ModuleService.EnumerateModules().OrderBy((m) => m.ModuleIndex))
{
totalSize += module.ImageSize;
if (Verbose)
{
- WriteLine("{0}", module.FileName);
- WriteLine(" Address: {0:X16}", module.ImageBase);
- WriteLine(" ImageSize: {0:X8}", module.ImageSize);
- WriteLine(" IsPEImage: {0}", module.IsPEImage);
- WriteLine(" IsManaged: {0}", module.IsManaged);
- WriteLine(" IsFileLayout: {0}", module.IsFileLayout?.ToString() ?? "<unknown>");
- WriteLine(" FileSize: {0:X8}", module.IndexFileSize);
- WriteLine(" TimeStamp: {0:X8}", module.IndexTimeStamp);
- WriteLine(" Version: {0}", module.Version?.ToString() ?? "<none>");
+ WriteLine("{0} {1}", module.ModuleIndex, module.FileName);
+ WriteLine(" Address: {0:X16}", module.ImageBase);
+ WriteLine(" ImageSize: {0:X8}", module.ImageSize);
+ WriteLine(" IsPEImage: {0}", module.IsPEImage);
+ WriteLine(" IsManaged: {0}", module.IsManaged);
+ WriteLine(" IsFileLayout: {0}", module.IsFileLayout?.ToString() ?? "<unknown>");
+ WriteLine(" IndexFileSize: {0:X8}", module.IndexFileSize?.ToString() ?? "<none>");
+ WriteLine(" IndexTimeStamp: {0:X8}", module.IndexTimeStamp?.ToString() ?? "<none>");
+ WriteLine(" Version: {0}", module.Version?.ToString() ?? "<none>");
string versionString = module.VersionString;
if (!string.IsNullOrEmpty(versionString)) {
- WriteLine(" {0}", versionString);
+ WriteLine(" {0}", versionString);
}
- WriteLine(" PdbInfo: {0}", module.PdbInfo?.ToString() ?? "<none>");
- WriteLine(" BuildId: {0}", !module.BuildId.IsDefaultOrEmpty ? string.Concat(module.BuildId.Select((b) => b.ToString("x2"))) : "<none>");
+ WriteLine(" PdbInfo: {0}", module.PdbInfo?.ToString() ?? "<none>");
+ WriteLine(" BuildId: {0}", !module.BuildId.IsDefaultOrEmpty ? string.Concat(module.BuildId.Select((b) => b.ToString("x2"))) : "<none>");
}
else
{
}
foreach (RegisterInfo register in ThreadService.Registers)
{
- if (thread.GetRegisterValue(register.RegisterIndex, out ulong value))
+ if (thread.TryGetRegisterValue(register.RegisterIndex, out ulong value))
{
switch (register.RegisterSize)
{
if (NetFx || NetCore)
{
string name = NetFx ? "desktop .NET Framework" : ".NET Core";
- foreach (IRuntime runtime in RuntimeService.Runtimes)
+ foreach (IRuntime runtime in RuntimeService.EnumerateRuntimes())
{
if (NetFx && runtime.RuntimeType == RuntimeType.Desktop ||
NetCore && runtime.RuntimeType == RuntimeType.NetCore)
}
else
{
- foreach (IRuntime runtime in RuntimeService.Runtimes)
+ // Display the current runtime star ("*") only if there is more than one runtime
+ bool displayStar = RuntimeService.EnumerateRuntimes().Count() > 1;
+
+ foreach (IRuntime runtime in RuntimeService.EnumerateRuntimes())
{
- string current = RuntimeService.Runtimes.Count() > 1 ? runtime == RuntimeService.CurrentRuntime ? "*" : " " : "";
+ string current = displayStar ? (runtime == RuntimeService.CurrentRuntime ? "*" : " ") : "";
Write(current);
Write(runtime.ToString());
}
IThread thread;
if (ThreadId)
{
- thread = ThreadService.GetThreadInfoFromId(Thread.Value);
+ thread = ThreadService.GetThreadFromId(Thread.Value);
}
else
{
- thread = ThreadService.GetThreadInfoFromIndex(unchecked((int)Thread.Value));
+ thread = ThreadService.GetThreadFromIndex(unchecked((int)Thread.Value));
}
ThreadService.CurrentThreadId = thread.ThreadId;
}
WriteLine("{0}{1} 0x{2:X4} ({2})", thread.ThreadId == currentThreadId ? "*" : " ", thread.ThreadIndex, thread.ThreadId);
if (Verbose)
{
- thread.GetRegisterValue(ThreadService.InstructionPointerIndex, out ulong ip);
- thread.GetRegisterValue(ThreadService.StackPointerIndex, out ulong sp);
- thread.GetRegisterValue(ThreadService.FramePointerIndex, out ulong fp);
+ thread.TryGetRegisterValue(ThreadService.InstructionPointerIndex, out ulong ip);
+ thread.TryGetRegisterValue(ThreadService.StackPointerIndex, out ulong sp);
+ thread.TryGetRegisterValue(ThreadService.FramePointerIndex, out ulong fp);
WriteLine(" IP 0x{0:X16}", ip);
WriteLine(" SP 0x{0:X16}", sp);
WriteLine(" FP 0x{0:X16}", fp);
// 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.DebugServices;
using Microsoft.Diagnostics.Runtime;
using Microsoft.Diagnostics.Runtime.Interop;
using Microsoft.Diagnostics.Runtime.Utilities;
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
private ref readonly IDebuggerServicesVTable VTable => ref Unsafe.AsRef<IDebuggerServicesVTable >(_vtable);
- internal DebuggerServices(IntPtr punk)
+ private readonly HostType _hostType;
+
+ internal DebuggerServices(IntPtr punk, HostType hostType)
: base(new RefCountedFreeLibrary(IntPtr.Zero), IID_IDebuggerServices, punk)
{
+ _hostType = hostType;
}
public HResult GetOperatingSystem(out DebuggerServices.OperatingSystem operatingSystem)
{
imageName = null;
+ // GetModuleNames under lldb doesn't support querying just the
+ // path length (imageNameBufferPtr = null) so use a fix size
+ // image name buffer.
byte[] imageNameBuffer = new byte[1024];
fixed (byte* imageNameBufferPtr = imageNameBuffer)
{
{
symbolPath = null;
- // TODO: Get the path length first instead of using a fixed length buffer
- byte[] buffer = new byte[1024];
- fixed (byte* bufferPtr = buffer)
+ // Get the path length first
+ HResult hr = VTable.GetSymbolPath(Self, null, 0, out uint pathSize);
+ if (hr == HResult.S_OK)
{
- HResult hr = VTable.GetSymbolPath(Self, bufferPtr, (uint)buffer.Length, out uint pathSize);
- if (hr >= HResult.S_OK)
+ if (pathSize > 0)
{
- if (pathSize > 0)
+ // Now get the symbol path
+ byte[] buffer = new byte[pathSize];
+ fixed (byte* bufferPtr = buffer)
{
- symbolPath = Encoding.ASCII.GetString(bufferPtr, (int)pathSize - 1);
+ hr = VTable.GetSymbolPath(Self, bufferPtr, (uint)buffer.Length, out pathSize);
+ if (hr == HResult.S_OK)
+ {
+ symbolPath = Encoding.ASCII.GetString(bufferPtr, (int)pathSize - 1);
+ }
}
- else
+ }
+ else
+ {
+ hr = HResult.E_INVALIDARG;
+ }
+ }
+ return hr;
+ }
+
+ public HResult GetSymbolByOffset(int moduleIndex, ulong address, out string symbol, out ulong displacement)
+ {
+ symbol = null;
+
+ // Get the symbol length first
+ HResult hr = VTable.GetSymbolByOffset(Self, moduleIndex, address, null, 0, out uint symbolSize, out displacement);
+ if (hr == HResult.S_OK)
+ {
+ if (symbolSize > 0)
+ {
+ // Now get the symbol
+ byte[] symbolBuffer = new byte[symbolSize];
+ fixed (byte* symbolBufferPtr = symbolBuffer)
{
- hr = HResult.E_INVALIDARG;
+ hr = VTable.GetSymbolByOffset(Self, moduleIndex, address, symbolBufferPtr, symbolBuffer.Length, out symbolSize, out displacement);
+ if (hr == HResult.S_OK)
+ {
+ symbol = Encoding.ASCII.GetString(symbolBufferPtr, (int)symbolSize - 1);
+ if (_hostType == HostType.DbgEng)
+ {
+ int index = symbol.IndexOf('!');
+ if (index != -1) {
+ symbol = symbol.Remove(0, index + 1);
+ }
+ }
+ }
}
}
- return hr;
+ else
+ {
+ hr = HResult.E_INVALIDARG;
+ }
+ }
+ return hr;
+ }
+
+ public HResult GetOffsetBySymbol(int moduleIndex, string symbol, out ulong address)
+ {
+ if (symbol == null) throw new ArgumentNullException(nameof(symbol));
+
+ byte[] symbolBytes = Encoding.ASCII.GetBytes(symbol + "\0");
+ fixed (byte* symbolPtr = symbolBytes)
+ {
+ return VTable.GetOffsetBySymbol(Self, moduleIndex, symbolPtr, out address);
}
}
}
public readonly delegate* unmanaged[Stdcall]<IntPtr, uint, out ulong, HResult> GetThreadTeb;
public readonly delegate* unmanaged[Stdcall]<IntPtr, uint, uint, byte*, HResult> VirtualUnwind;
public readonly delegate* unmanaged[Stdcall]<IntPtr, byte*, uint, out uint, HResult> GetSymbolPath;
+ public readonly delegate* unmanaged[Stdcall]<IntPtr, int, ulong, byte*, int, out uint, out ulong, HResult> GetSymbolByOffset;
+ public readonly delegate* unmanaged[Stdcall]<IntPtr, int, byte*, out ulong, HResult> GetOffsetBySymbol;
}
}
/// <summary>
/// The extension services Wrapper the native hosts are given
/// </summary>
- internal sealed unsafe class HostServices : COMCallableIUnknown, IHost
+ public sealed unsafe class HostServices : COMCallableIUnknown, IHost
{
private static readonly Guid IID_IHostServices = new Guid("27B2CB8D-BDEE-4CBD-B6EF-75880D76D46F");
}
}
+ /// <summary>
+ /// The host services instance. Only valid after Initialize is called.
+ /// </summary>
+ public static HostServices Instance { get; private set; }
+
/// <summary>
/// This is the main managed entry point that the native hosting code calls. It needs to be a single function
/// and is restricted to just a string parameter because host APIs (i.e. desktop clr) have this narrow interface.
/// </summary>
/// <param name="extensionPath">Path and filename of native extensions to callback</param>
- /// <param name="callbackName">Name of callback function</param>
- /// <returns></returns>
+ /// <returns>hresult</returns>
public static int Initialize(
[MarshalAs(UnmanagedType.LPStr)] string extensionPath)
{
{
return HResult.E_FAIL;
}
- var hostServices = new HostServices();
- return initialializeCallback(hostServices.IHostServices);
+ Instance = new HostServices();
+ return initialializeCallback(Instance.IHostServices);
}
private HostServices()
public IServiceEvent OnShutdownEvent { get; } = new ServiceEvent();
- HostType IHost.HostType => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? HostType.DbgEng : HostType.Lldb;
+ public HostType HostType => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? HostType.DbgEng : HostType.Lldb;
IServiceProvider IHost.Services => _serviceProvider;
+ IEnumerable<ITarget> IHost.EnumerateTargets() => _target != null ? new ITarget[] { _target } : Array.Empty<ITarget>();
+
ITarget IHost.CurrentTarget => _target;
void IHost.SetCurrentTarget(int targetid) => throw new NotImplementedException();
// Create the wrapper for the host debugger services
try
{
- DebuggerServices = new DebuggerServices(iunk);
+ DebuggerServices = new DebuggerServices(iunk, HostType);
}
catch (InvalidCastException ex)
{
catch (InvalidCastException)
{
}
+ HResult hr;
try
{
var consoleService = new ConsoleServiceFromDebuggerServices(DebuggerServices);
// Add each extension command to the native debugger
foreach ((string name, string help, IEnumerable<string> aliases) in _commandProcessor.Commands)
{
- HResult hr = DebuggerServices.AddCommand(name, help, aliases);
+ hr = DebuggerServices.AddCommand(name, help, aliases);
if (hr != HResult.S_OK)
{
Trace.TraceWarning($"Cannot add extension command {hr:X8} {name} - {help}");
Trace.TraceError(ex.ToString());
return HResult.E_FAIL;
}
- if (DebuggerServices.GetSymbolPath(out string symbolPath) == HResult.S_OK)
+ hr = DebuggerServices.GetSymbolPath(out string symbolPath);
+ if (hr == HResult.S_OK)
{
if (!_symbolService.ParseSymbolPath(symbolPath))
{
Trace.TraceError("ParseSymbolPath FAILED: {0}", symbolPath);
}
}
+ else
+ {
+ Trace.TraceError("DebuggerServices.GetSymbolPath FAILED: {0:X8}", hr);
+ }
return HResult.S_OK;
}
{
IThreadService threadService = _target.Services.GetService<IThreadService>();
if (threadService != null && threadService.CurrentThreadId.HasValue) {
- return threadService.GetThreadInfoFromId(threadService.CurrentThreadId.Value);
+ return threadService.GetThreadFromId(threadService.CurrentThreadId.Value);
}
return null;
});
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.IO;
using System.Runtime.InteropServices;
namespace SOS.Extensions
/// </summary>
internal class ModuleServiceFromDebuggerServices : ModuleService
{
- class ModuleFromDebuggerServices : Module
+ class ModuleFromDebuggerServices : Module, IExportSymbols, IModuleSymbols
{
+ // This is what dbgeng/IDebuggerServices returns for non-PE modules that don't have a timestamp
+ private const uint InvalidTimeStamp = 0xFFFFFFFE;
+
private readonly ModuleServiceFromDebuggerServices _moduleService;
private string _versionString;
string imageName,
ulong imageBase,
ulong imageSize,
- int indexFileSize,
- int indexTimeStamp)
+ uint indexFileSize,
+ uint indexTimeStamp)
{
_moduleService = moduleService;
ModuleIndex = moduleIndex;
FileName = imageName;
ImageBase = imageBase;
ImageSize = imageSize;
- IndexFileSize = indexFileSize;
- IndexTimeStamp = indexTimeStamp;
+ IndexFileSize = indexTimeStamp == InvalidTimeStamp ? null : indexFileSize;
+ IndexTimeStamp = indexTimeStamp == InvalidTimeStamp ? null : indexTimeStamp;
+
+ ServiceProvider.AddService<IExportSymbols>(this);
+ ServiceProvider.AddService<IModuleSymbols>(this);
}
#region IModule
public override ulong ImageSize { get; }
- public override int IndexFileSize { get; }
+ public override uint? IndexFileSize { get; }
- public override int IndexTimeStamp { get; }
+ public override uint? IndexTimeStamp { get; }
public override VersionInfo? Version
{
#endregion
+ #region IExportSymbols/IModuleSymbols
+
+ public bool TryGetSymbolName(ulong address, out string symbol, out ulong displacement)
+ {
+ return _moduleService._debuggerServices.GetSymbolByOffset(ModuleIndex, address, out symbol, out displacement) == HResult.S_OK;
+ }
+
+ public bool TryGetSymbolAddress(string name, out ulong address)
+ {
+ return _moduleService._debuggerServices.GetOffsetBySymbol(ModuleIndex, name, out address) == HResult.S_OK;
+ }
+
+ #endregion
+
protected override ModuleService ModuleService => _moduleService;
}
if (hr == HResult.S_OK)
{
hr = _debuggerServices.GetModuleName(moduleIndex, out string imageName);
- if (hr < 0)
+ if (hr < HResult.S_OK)
{
Trace.TraceError("GetModuleName({0}) {1:X16} FAILED {2:X8}", moduleIndex, imageBase, hr);
}
- var module = new ModuleFromDebuggerServices(this, moduleIndex, imageName, imageBase, imageSize, unchecked((int)imageSize), unchecked((int)timestamp));
+ var module = new ModuleFromDebuggerServices(this, moduleIndex, imageName, imageBase, imageSize, (uint)imageSize, timestamp);
if (!modules.TryGetValue(imageBase, out IModule original))
{
modules.Add(imageBase, module);
protected override IEnumerable<IThread> GetThreadsInner()
{
- var threads = new List<IThread>();
HResult hr = _debuggerServices.GetNumberThreads(out uint number);
if (hr == HResult.S_OK)
{
{
for (int i = 0; i < number; i++)
{
- var thread = new Thread(this, unchecked((int)threadIds[i]), threadSysIds[i]);
- threads.Add(thread);
+ yield return new Thread(this, unchecked((int)threadIds[i]), threadSysIds[i]);
}
}
else
{
Trace.TraceError("GetNumberThreads() FAILED {0:X8}", hr);
}
- return threads;
}
protected override ulong GetThreadTeb(uint threadId)
byte[] registerContext;
try
{
- registerContext = _threadService.GetThreadInfoFromId(threadId).GetThreadContext();
+ registerContext = _threadService.GetThreadFromId(threadId).GetThreadContext();
}
catch (DiagnosticsException)
{
byte[] registerContext;
try
{
- registerContext = _threadService.GetThreadInfoFromId(threadId).GetThreadContext();
+ registerContext = _threadService.GetThreadFromId(threadId).GetThreadContext();
}
catch (DiagnosticsException)
{
IModule module = _soshost.ModuleService.GetModuleFromIndex((int)index);
SOSHost.Write(moduleBase, module.ImageBase);
SOSHost.Write(moduleSize, module.ImageSize);
- SOSHost.Write(timestamp, (uint)module.IndexTimeStamp);
- SOSHost.Write(checksum, 0);
+ SOSHost.Write(timestamp, module.IndexTimeStamp.GetValueOrDefault(SOSHost.InvalidTimeStamp));
+ SOSHost.Write(checksum, SOSHost.InvalidChecksum);
}
catch (DiagnosticsException)
{
private const string SOSInitialize = "SOSInitializeByHost";
private const string SOSUninitialize = "SOSUninitializeByHost";
+ // This is what dbgeng/IDebuggerServices returns for non-PE modules that don't have a timestamp
+ internal const uint InvalidTimeStamp = 0xFFFFFFFE;
+ internal const uint InvalidChecksum = 0xFFFFFFFF;
+
internal readonly ITarget Target;
internal readonly IConsoleService ConsoleService;
internal readonly IModuleService ModuleService;
{
moduleParams[i].Base = module.ImageBase;
moduleParams[i].Size = (uint)module.ImageSize;
- moduleParams[i].TimeDateStamp = (uint)module.IndexTimeStamp;
- moduleParams[i].Checksum = 0;
+ moduleParams[i].TimeDateStamp = module.IndexTimeStamp.GetValueOrDefault(InvalidTimeStamp);
+ moduleParams[i].Checksum = InvalidChecksum;
moduleParams[i].Flags = DEBUG_MODULE.LOADED;
moduleParams[i].SymbolType = DEBUG_SYMTYPE.PDB;
byte[] registerContext;
try
{
- registerContext = ThreadService.GetThreadInfoFromId(threadId).GetThreadContext();
+ registerContext = ThreadService.GetThreadFromId(threadId).GetThreadContext();
}
catch (DiagnosticsException)
{
{
try
{
- ThreadService.CurrentThreadId = ThreadService.GetThreadInfoFromIndex(unchecked((int)id)).ThreadId;
+ ThreadService.CurrentThreadId = ThreadService.GetThreadFromIndex(unchecked((int)id)).ThreadId;
}
catch (DiagnosticsException)
{
{
try
{
- IThread threadInfo = ThreadService.GetThreadInfoFromId(sysId);
+ IThread threadInfo = ThreadService.GetThreadFromId(sysId);
id = (uint)threadInfo.ThreadIndex;
return HResult.S_OK;
}
uint threadId = ThreadService.CurrentThreadId.Value;
try
{
- ulong teb = ThreadService.GetThreadInfoFromId(threadId).GetThreadTeb();
+ ulong teb = ThreadService.GetThreadFromId(threadId).GetThreadTeb();
Write(offset, teb);
return HResult.S_OK;
}
string name,
out uint index)
{
- if (!ThreadService.GetRegisterIndexByName(name, out int value)) {
+ if (!ThreadService.TryGetRegisterIndexByName(name, out int value)) {
index = 0;
return HResult.E_INVALIDARG;
}
string register,
out ulong value)
{
- if (!ThreadService.GetRegisterIndexByName(register, out int index)) {
+ if (!ThreadService.TryGetRegisterIndexByName(register, out int index)) {
value = 0;
return HResult.E_INVALIDARG;
}
{
if (ThreadService.CurrentThreadId.HasValue)
{
- IThread thread = ThreadService.GetThreadInfoFromId(ThreadService.CurrentThreadId.Value);
+ IThread thread = ThreadService.GetThreadFromId(ThreadService.CurrentThreadId.Value);
if (thread != null)
{
- if (thread.GetRegisterValue(index, out value))
+ if (thread.TryGetRegisterValue(index, out value))
{
return HResult.S_OK;
}
(ex is DiagnosticsException ||
ex is BadInputFormatException ||
ex is InvalidVirtualAddressException ||
+ ex is ArgumentOutOfRangeException ||
+ ex is IndexOutOfRangeException ||
ex is TaskCanceledException)
{
Trace.TraceError("{0} address {1:X16}: {2}", moduleFilePath, address, ex.Message);
#include "dbgengservices.h"
#include "exts.h"
+extern IMachine* GetTargetMachine(ULONG processorType);
+
DbgEngServices::DbgEngServices(IDebugClient* client) :
m_ref(1),
m_client(client),
m_data(nullptr),
m_symbols(nullptr),
m_system(nullptr),
- m_advanced(nullptr)
+ m_advanced(nullptr),
+ m_targetMachine(nullptr)
{
client->AddRef();
}
{
// Prepare context structure
ZeroMemory(context, contextSize);
- g_targetMachine->SetContextFlags(context, contextFlags);
+ GetMachine()->SetContextFlags(context, contextFlags);
// Ok, do it!
hr = m_advanced->GetThreadContext((LPVOID)context, contextSize);
m_system->SetCurrentThreadId(originalThreadId);
// GetThreadContext clears ContextFlags or sets them incorrectly and DBI needs it set to know what registers to copy
- g_targetMachine->SetContextFlags(context, contextFlags);
+ GetMachine()->SetContextFlags(context, contextFlags);
}
return hr;
}
{
return m_symbols->GetSymbolPath(buffer, bufferSize, pathSize);
}
+
+HRESULT
+DbgEngServices::GetSymbolByOffset(
+ ULONG moduleIndex,
+ ULONG64 offset,
+ PSTR nameBuffer,
+ ULONG nameBufferSize,
+ PULONG nameSize,
+ PULONG64 displacement)
+{
+ return m_symbols->GetNameByOffset(offset, nameBuffer, nameBufferSize, nameSize, displacement);
+}
+
+HRESULT
+DbgEngServices::GetOffsetBySymbol(
+ ULONG moduleIndex,
+ PCSTR name,
+ PULONG64 offset)
+{
+ ULONG cch = 0;
+ HRESULT hr = m_symbols->GetModuleNameString(DEBUG_MODNAME_MODULE, moduleIndex, 0, nullptr, 0, &cch);
+ if (FAILED(hr)) {
+ return hr;
+ }
+ ArrayHolder<char> moduleName = new char[cch];
+ hr = m_symbols->GetModuleNameString(DEBUG_MODNAME_MODULE, moduleIndex, 0, moduleName, cch, nullptr);
+ if (FAILED(hr)) {
+ return hr;
+ }
+ std::string symbolName;
+ symbolName.append(moduleName);
+ symbolName.append("!");
+ symbolName.append(name);
+ return m_symbols->GetOffsetByName(symbolName.c_str(), offset);
+}
//----------------------------------------------------------------------------
// IRemoteMemoryService
{
if (((Argument & DEBUG_STATUS_MASK) == DEBUG_STATUS_BREAK) && ((Argument & DEBUG_STATUS_INSIDE_WAIT) == 0))
{
+ ULONG processId = 0;
+ m_system->GetCurrentProcessSystemId(&processId);
+ m_control->Output(DEBUG_OUTPUT_NORMAL, "ChangeEngineState: processId %d\n", processId);
+
+ // Has the process changed since the last commmand?
+ Extensions::GetInstance()->UpdateTarget(processId);
+
// Flush the target when the debugger target breaks
Extensions::GetInstance()->FlushTarget();
}
HRESULT DbgEngServices::ExitProcess(
ULONG ExitCode)
{
+ m_targetMachine = nullptr;
Extensions::GetInstance()->DestroyTarget();
return DEBUG_STATUS_NO_CHANGE;
}
// Helper Functions
//----------------------------------------------------------------------------
+IMachine*
+DbgEngServices::GetMachine()
+{
+ if (m_targetMachine == nullptr)
+ {
+ ULONG processorType = 0;
+ m_control->GetExecutingProcessorType(&processorType);
+ m_targetMachine = ::GetTargetMachine(processorType);
+ }
+ return m_targetMachine;
+}
+
HRESULT
DbgEngServices::SetCurrentThreadIdFromSystemId(
ULONG32 sysId,
#define VER_PLATFORM_UNIX 10
+class IMachine;
+
#ifdef __cplusplus
extern "C" {
#endif
PDEBUG_SYMBOLS2 m_symbols;
PDEBUG_SYSTEM_OBJECTS m_system;
PDEBUG_ADVANCED m_advanced;
+ IMachine* m_targetMachine;
public:
DbgEngServices(IDebugClient* client);
// Helper functions
//----------------------------------------------------------------------------
+ IMachine* GetMachine();
+
HRESULT SetCurrentThreadIdFromSystemId(
ULONG32 sysId,
PULONG originalThreadId);
ULONG bufferSize,
PULONG pathSize);
+ HRESULT STDMETHODCALLTYPE GetSymbolByOffset(
+ ULONG moduleIndex,
+ ULONG64 offset,
+ PSTR nameBuffer,
+ ULONG nameBufferSize,
+ PULONG nameSize,
+ PULONG64 displacement);
+
+ HRESULT STDMETHODCALLTYPE GetOffsetBySymbol(
+ ULONG moduleIndex,
+ PCSTR name,
+ PULONG64 offset);
+
//----------------------------------------------------------------------------
// IRemoteMemoryService
//----------------------------------------------------------------------------
// Queries for all debugger interfaces.
#ifndef FEATURE_PAL
-extern "C" HRESULT
+HRESULT
ExtQuery(PDEBUG_CLIENT client)
{
HRESULT Status;
g_ExtClient = client;
#else
-extern "C" HRESULT
+HRESULT
ExtQuery(ILLDBServices* services)
{
// Initialize the PAL and extension suppport in one place and only once.
return Status;
}
-extern "C" HRESULT
-ArchQuery(void)
+IMachine*
+GetTargetMachine(ULONG processorType)
{
- ULONG targetArchitecture;
IMachine* targetMachine = NULL;
-
- g_ExtControl->GetExecutingProcessorType(&targetArchitecture);
-
#ifdef SOS_TARGET_AMD64
- if(targetArchitecture == IMAGE_FILE_MACHINE_AMD64)
+ if (processorType == IMAGE_FILE_MACHINE_AMD64)
{
targetMachine = AMD64Machine::GetInstance();
}
#endif // SOS_TARGET_AMD64
#ifdef SOS_TARGET_X86
- if (targetArchitecture == IMAGE_FILE_MACHINE_I386)
+ if (processorType == IMAGE_FILE_MACHINE_I386)
{
targetMachine = X86Machine::GetInstance();
}
#endif // SOS_TARGET_X86
#ifdef SOS_TARGET_ARM
- switch (targetArchitecture)
+ switch (processorType)
{
case IMAGE_FILE_MACHINE_ARM:
case IMAGE_FILE_MACHINE_THUMB:
}
#endif // SOS_TARGET_ARM
#ifdef SOS_TARGET_ARM64
- if (targetArchitecture == IMAGE_FILE_MACHINE_ARM64)
+ if (processorType == IMAGE_FILE_MACHINE_ARM64)
{
targetMachine = ARM64Machine::GetInstance();
}
#endif // SOS_TARGET_ARM64
+ return targetMachine;
+}
- if (targetMachine == NULL)
+HRESULT
+ArchQuery(void)
+{
+ ULONG processorType = 0;
+ g_ExtControl->GetExecutingProcessorType(&processorType);
+
+ g_targetMachine = GetTargetMachine(processorType);
+ if (g_targetMachine == NULL)
{
- g_targetMachine = NULL;
- ExtErr("The SOS that is loaded does not support the current target architecture '0x%04x'. A 32 bit target may require a 64 bit debugger or vice versa.\n", targetArchitecture);
+ const char* architecture = "";
+ switch (processorType)
+ {
+ case IMAGE_FILE_MACHINE_AMD64:
+ architecture = "x64";
+ break;
+ case IMAGE_FILE_MACHINE_I386:
+ architecture = "x86";
+ break;
+ case IMAGE_FILE_MACHINE_ARM:
+ case IMAGE_FILE_MACHINE_THUMB:
+ case IMAGE_FILE_MACHINE_ARMNT:
+ architecture = "arm32";
+ break;
+ case IMAGE_FILE_MACHINE_ARM64:
+ architecture = "arm64";
+ break;
+ }
+ ExtErr("SOS does not support the current target architecture '%s' (0x%04x). A 32 bit target may require a 32 bit debugger or vice versa. In general, try to use the same bitness for the debugger and target process.\n",
+ architecture, processorType);
return E_FAIL;
}
-
- g_targetMachine = targetMachine;
return S_OK;
}
IHostServices* hostServices = GetHostServices();
if (hostServices != nullptr)
{
- Status = hostServices->DispatchCommand(args);
+ // Just load the managed infrastructure if no command. This is useful in lldb
+ // where the managed extension commands are not added until a command does
+ // GetHostServices() like soshelp, logging, sosstatus, setsymbolserver and ext.
+ if (args != nullptr && strlen(args) > 0)
+ {
+ Status = hostServices->DispatchCommand(args);
+ }
}
else
{
PSTR buffer,
ULONG bufferSize,
PULONG pathSize) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetSymbolByOffset(
+ ULONG moduleIndex,
+ ULONG64 offset,
+ PSTR nameBuffer,
+ ULONG nameBufferSize,
+ PULONG nameSize,
+ PULONG64 displacement) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetOffsetBySymbol(
+ ULONG moduleIndex,
+ PCSTR name,
+ PULONG64 offset) = 0;
};
#ifdef __cplusplus
#define CONVERT_FROM_SIGN_EXTENDED(offset) ((ULONG_PTR)(offset))
+// Return what dbgeng returns for Linux modules that don't have a timestamp/checksum
+#define InvalidTimeStamp 0xFFFFFFFE;
+#define InvalidChecksum 0xFFFFFFFF;
+
ULONG g_currentThreadIndex = (ULONG)-1;
ULONG g_currentThreadSystemId = (ULONG)-1;
char *g_coreclrDirectory = nullptr;
ULONG nameBufferSize,
PULONG nameSize,
PULONG64 displacement)
+{
+ return GetNameByOffset(DEBUG_ANY_ID, offset, nameBuffer, nameBufferSize, nameSize, displacement);
+}
+
+HRESULT
+LLDBServices::GetNameByOffset(
+ ULONG moduleIndex,
+ ULONG64 offset,
+ PSTR nameBuffer,
+ ULONG nameBufferSize,
+ PULONG nameSize,
+ PULONG64 displacement)
{
ULONG64 disp = DEBUG_INVALID_OFFSET;
HRESULT hr = S_OK;
goto exit;
}
- module = address.GetModule();
- if (!module.IsValid())
+ // If module index is invalid, add module name to symbol
+ if (moduleIndex == DEBUG_ANY_ID)
{
- hr = E_FAIL;
- goto exit;
- }
+ module = address.GetModule();
+ if (!module.IsValid())
+ {
+ hr = E_FAIL;
+ goto exit;
+ }
- file = module.GetFileSpec();
- if (file.IsValid())
+ file = module.GetFileSpec();
+ if (file.IsValid())
+ {
+ str.append(file.GetFilename());
+ }
+ }
+ else
{
- str.append(file.GetFilename());
+ module = target.GetModuleAtIndex(moduleIndex);
+ if (!module.IsValid())
+ {
+ hr = E_INVALIDARG;
+ goto exit;
+ }
+
+ if (module != address.GetModule())
+ {
+ hr = E_INVALIDARG;
+ goto exit;
+ }
}
symbol = address.GetSymbol();
}
if (pTimestamp)
{
- *pTimestamp = 0;
+ *pTimestamp = InvalidTimeStamp;
}
if (pChecksum)
{
- *pChecksum = 0;
+ *pChecksum = InvalidChecksum;
}
return S_OK;
}
return E_NOTIMPL;
}
-HRESULT LLDBServices::GetSymbolPath(
+HRESULT
+LLDBServices::GetSymbolPath(
PSTR buffer,
ULONG bufferSize,
PULONG pathSize)
return E_NOTIMPL;
}
+HRESULT
+LLDBServices::GetSymbolByOffset(
+ ULONG moduleIndex,
+ ULONG64 offset,
+ PSTR nameBuffer,
+ ULONG nameBufferSize,
+ PULONG nameSize,
+ PULONG64 displacement)
+{
+ return GetNameByOffset(moduleIndex, offset, nameBuffer, nameBufferSize, nameSize, displacement);
+}
+
+HRESULT
+LLDBServices::GetOffsetBySymbol(
+ ULONG moduleIndex,
+ PCSTR name,
+ PULONG64 offset)
+{
+ HRESULT hr = S_OK;
+
+ lldb::SBTarget target;
+ lldb::SBModule module;
+ lldb::SBSymbol symbol;
+ lldb::SBAddress startAddress;
+
+ if (offset == nullptr)
+ {
+ hr = E_INVALIDARG;
+ goto exit;
+ }
+
+ target = m_debugger.GetSelectedTarget();
+ if (!target.IsValid())
+ {
+ hr = E_FAIL;
+ goto exit;
+ }
+
+ module = target.GetModuleAtIndex(moduleIndex);
+ if (!module.IsValid())
+ {
+ hr = E_INVALIDARG;
+ goto exit;
+ }
+
+ symbol = module.FindSymbol(name);
+ if (!symbol.IsValid())
+ {
+ hr = E_INVALIDARG;
+ goto exit;
+ }
+ startAddress = symbol.GetStartAddress();
+ *offset = startAddress.GetLoadAddress(target);
+exit:
+ return hr;
+}
+
//----------------------------------------------------------------------------
// Helper functions
//----------------------------------------------------------------------------
}
}
return result;
-}
\ No newline at end of file
+}
PULONG nameSize,
PULONG64 displacement);
+ HRESULT STDMETHODCALLTYPE GetNameByOffset(
+ ULONG moduleIndex,
+ ULONG64 offset,
+ PSTR nameBuffer,
+ ULONG nameBufferSize,
+ PULONG nameSize,
+ PULONG64 displacement);
+
HRESULT STDMETHODCALLTYPE GetNumberModules(
PULONG loaded,
PULONG unloaded);
PSTR buffer,
ULONG bufferSize,
PULONG pathSize);
+
+ HRESULT STDMETHODCALLTYPE GetSymbolByOffset(
+ ULONG moduleIndex,
+ ULONG64 offset,
+ PSTR nameBuffer,
+ ULONG nameBufferSize,
+ PULONG nameSize,
+ PULONG64 displacement);
+ HRESULT STDMETHODCALLTYPE GetOffsetBySymbol(
+ ULONG moduleIndex,
+ PCSTR name,
+ PULONG64 offset);
+
//----------------------------------------------------------------------------
// LLDBServices (internal)
//----------------------------------------------------------------------------
sosCommandInitialize(lldb::SBDebugger debugger)
{
g_services->AddCommand("sos", new sosCommand(nullptr), "Various .NET Core debugging commands. See 'soshelp' for more details. sos <command-name> <args>");
+ g_services->AddCommand("ext", new sosCommand("ext"), "Execute extension command. See 'soshelp' for more details. ext <command-name> <args>");
g_services->AddCommand("bpmd", new sosCommand("bpmd"), "Creates a breakpoint at the specified managed method in the specified module.");
g_services->AddCommand("clrstack", new sosCommand("ClrStack"), "Provides a stack trace of managed code only.");
g_services->AddCommand("clrthreads", new sosCommand("Threads"), "List the managed threads running.");
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
+using System.Collections.Generic;
namespace Microsoft.Diagnostics.Tools.Dump
{
services.AddServiceFactory<IThread>(() => {
IThreadService threadService = _target.Services.GetService<IThreadService>();
if (threadService != null && threadService.CurrentThreadId.HasValue) {
- return threadService.GetThreadInfoFromId(threadService.CurrentThreadId.Value);
+ return threadService.GetThreadFromId(threadService.CurrentThreadId.Value);
}
return null;
});
IServiceProvider IHost.Services => _serviceProvider;
+ IEnumerable<ITarget> IHost.EnumerateTargets() => _target != null ? new ITarget[] { _target } : Array.Empty<ITarget>();
+
ITarget IHost.CurrentTarget => _target;
void IHost.SetCurrentTarget(int targetid) => throw new NotImplementedException();