Misc interface and implementation changes (#1930)
authorMike McLaughlin <mikem@microsoft.com>
Sat, 30 Jan 2021 00:03:38 +0000 (16:03 -0800)
committerGitHub <noreply@github.com>
Sat, 30 Jan 2021 00:03:38 +0000 (16:03 -0800)
 Misc interface and implementation changes

Add IExportSymbols and IModuleSymbols interfaces and implementation

Change IModule.IndexFileSize/IndexTimeStamp to uint?.

Renamed IRuntimeService.Runtimes to EnumerateRuntimes to be more consistent with the rest of the interfaces.

Add IHost.EnumerateTargets().

40 files changed:
NuGet.config
documentation/FAQ.md
src/Microsoft.Diagnostics.DebugServices.Implementation/Module.cs
src/Microsoft.Diagnostics.DebugServices.Implementation/ModuleService.cs
src/Microsoft.Diagnostics.DebugServices.Implementation/ModuleServiceFromDataReader.cs
src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.cs
src/Microsoft.Diagnostics.DebugServices.Implementation/RuntimeService.cs
src/Microsoft.Diagnostics.DebugServices.Implementation/Thread.cs
src/Microsoft.Diagnostics.DebugServices.Implementation/ThreadService.cs
src/Microsoft.Diagnostics.DebugServices.Implementation/ThreadServiceFromDataReader.cs
src/Microsoft.Diagnostics.DebugServices/IExportSymbols.cs [new file with mode: 0644]
src/Microsoft.Diagnostics.DebugServices/IHost.cs
src/Microsoft.Diagnostics.DebugServices/IModule.cs
src/Microsoft.Diagnostics.DebugServices/IModuleSymbols.cs [new file with mode: 0644]
src/Microsoft.Diagnostics.DebugServices/IRuntimeService.cs
src/Microsoft.Diagnostics.DebugServices/ISymbolService.cs
src/Microsoft.Diagnostics.DebugServices/IThread.cs
src/Microsoft.Diagnostics.DebugServices/IThreadService.cs
src/Microsoft.Diagnostics.ExtensionCommands/Host/ModulesCommand.cs
src/Microsoft.Diagnostics.ExtensionCommands/Host/RegistersCommand.cs
src/Microsoft.Diagnostics.ExtensionCommands/Host/RuntimesCommand.cs
src/Microsoft.Diagnostics.ExtensionCommands/Host/ThreadsCommand.cs
src/SOS/SOS.Extensions/DebuggerServices.cs
src/SOS/SOS.Extensions/HostServices.cs
src/SOS/SOS.Extensions/ModuleServiceFromDebuggerServices.cs
src/SOS/SOS.Extensions/ThreadServiceFromDebuggerServices.cs
src/SOS/SOS.Hosting/CorDebugDataTargetWrapper.cs
src/SOS/SOS.Hosting/DataTargetWrapper.cs
src/SOS/SOS.Hosting/LLDBServices.cs
src/SOS/SOS.Hosting/SOSHost.cs
src/SOS/SOS.Hosting/SymbolServiceWrapper.cs
src/SOS/Strike/dbgengservices.cpp
src/SOS/Strike/dbgengservices.h
src/SOS/Strike/exts.cpp
src/SOS/Strike/strike.cpp
src/SOS/inc/debuggerservices.h
src/SOS/lldbplugin/services.cpp
src/SOS/lldbplugin/services.h
src/SOS/lldbplugin/soscommand.cpp
src/Tools/dotnet-dump/Analyzer.cs

index b7d55337c0eb0b787518bfdd59d5da094d8a2b4a..e855e6dd8c5811ca89b957ed4ce24f15f23d4575 100644 (file)
@@ -12,8 +12,8 @@
     <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" />
index f4b517dfd4daad8ed99f1243ef9ce12ad348bd78..ad788a0ae874ce3e15dfdcd337162cc1cfceea53 100644 (file)
@@ -48,7 +48,7 @@ Frequently Asked Questions
     ```
    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).
index ab4ca7d38c743b27cfbcf9404a771e82660e3b24..be35a06f1aff0bd7a1a7a5b39cc22bd7e3a99e63 100644 (file)
@@ -62,9 +62,9 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
 
         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
         {
index 9d3e3daf01988c82cc57483cb36e8401112b2525..6bbbe561c941570e6cbc9ee032a0ba45455589e1 100644 (file)
@@ -263,10 +263,14 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
                     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;
         }
@@ -289,11 +293,14 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
             { 
                 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);
+                        }
                     }
                 }
             }
index 9314e25b586f05deaf196be10bf12c58c7e5f261..abcc5d6e665aeea96273dac2fc97f36d39fe10d2 100644 (file)
@@ -18,6 +18,9 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
     {
         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;
@@ -42,9 +45,9 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
 
             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
             {
index 3bfe565578b110b596fb1a0a8873cf318e9ea0fd..5f886292509aa96eceafe0d37efadcebeb0dd14a 100644 (file)
@@ -256,8 +256,11 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
                 }
                 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)
@@ -320,7 +323,7 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
         {
             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}");
index 66975f68f38e0faaa6f072268b3f4ee438bef5cf..ab77b5b1141646c188d22f2bcc49a42def995ea8 100644 (file)
@@ -71,7 +71,7 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
         /// <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
@@ -129,8 +129,15 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
         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)
         {
@@ -168,7 +175,7 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
         {
             try
             {
-                byte[] registerContext = ThreadService.GetThreadInfoFromId(threadId).GetThreadContext();
+                byte[] registerContext = ThreadService.GetThreadFromId(threadId).GetThreadContext();
                 context = new Span<byte>(registerContext);
                 return true;
             }
index cf812e4710519bed3f10916acefc5a164060076a..321dca7dd4325449fdc940783b7b49a8f07b35fc 100644 (file)
@@ -3,6 +3,7 @@
 // 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
@@ -31,11 +32,11 @@ 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
                 {
@@ -54,10 +55,14 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
                         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;
index fdc8b0828d337a41c0693f821ee5de40377d478a..d1bcb161310c0286fdd7bc424d5653a5259c2a5e 100644 (file)
@@ -132,7 +132,7 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
         /// <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))
             {
@@ -149,7 +149,7 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
         /// <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);
         }
@@ -174,7 +174,7 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
         /// <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
             {
@@ -192,7 +192,7 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
         /// <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}");
index c9700049a4fba98f09c05cb7217790c4e6c8b88b..29db285b3081c644939316d71c780dff04ff8d7d 100644 (file)
@@ -6,6 +6,7 @@ using Microsoft.Diagnostics.Runtime;
 using Microsoft.Diagnostics.Runtime.DataReaders.Implementation;
 using System;
 using System.Collections.Generic;
+using System.Collections.Immutable;
 using System.Diagnostics;
 using System.Linq;
 
diff --git a/src/Microsoft.Diagnostics.DebugServices/IExportSymbols.cs b/src/Microsoft.Diagnostics.DebugServices/IExportSymbols.cs
new file mode 100644 (file)
index 0000000..420909c
--- /dev/null
@@ -0,0 +1,22 @@
+// 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);
+    }
+}
index c2e53998579861addafa1e5719edfa1ce24260c1..4031a2d141091774ceb8db9099a3a783f5136a82 100644 (file)
@@ -3,6 +3,8 @@
 // See the LICENSE file in the project root for more information.
 
 using System;
+using System.Collections;
+using System.Collections.Generic;
 
 namespace Microsoft.Diagnostics.DebugServices
 {
@@ -37,6 +39,11 @@ namespace Microsoft.Diagnostics.DebugServices
         /// </summary>
         IServiceProvider Services { get; }
 
+        /// <summary>
+        /// Enumerates all the targets
+        /// </summary>
+        IEnumerable<ITarget> EnumerateTargets();
+
         /// <summary>
         /// Current target instances or null
         /// </summary>
index 153202c0f0b5861c83a5372cd674e2a83fd14f23..234a50db9114cda1be14c2cd41902eb7d858d5d6 100644 (file)
@@ -41,12 +41,12 @@ namespace Microsoft.Diagnostics.DebugServices
         /// <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.
diff --git a/src/Microsoft.Diagnostics.DebugServices/IModuleSymbols.cs b/src/Microsoft.Diagnostics.DebugServices/IModuleSymbols.cs
new file mode 100644 (file)
index 0000000..0fe8c48
--- /dev/null
@@ -0,0 +1,31 @@
+// 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);
+    }
+}
index 7a544b07ea8ef77042c19d3f5dbbd760b122daf3..7d8c7b8504990c175499ba7d3c8f5c2437568fdd 100644 (file)
@@ -20,12 +20,12 @@ namespace Microsoft.Diagnostics.DebugServices
         /// <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 
index 6e5e00243618a516be4b8f052e0b7eb8490251aa..1b2c7733298ece6f9df23d5624163da07692e0cd 100644 (file)
@@ -12,12 +12,12 @@ namespace Microsoft.Diagnostics.DebugServices
         /// <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:
@@ -26,14 +26,14 @@ namespace Microsoft.Diagnostics.DebugServices
         /// * 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.
@@ -44,38 +44,38 @@ namespace Microsoft.Diagnostics.DebugServices
         /// <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
@@ -84,6 +84,6 @@ namespace Microsoft.Diagnostics.DebugServices
         /// <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);
     }
 }
index d46028e0e03d075692d417c22ab7a30b75f5808b..c91b1b9091cb6568325cc6cd9a171417b2f807c4 100644 (file)
@@ -34,7 +34,7 @@ namespace Microsoft.Diagnostics.DebugServices
         /// <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.
index a2362a60671cc87b315ca5d67a2e078dc2822565..35eadfc58bdbce44f24e07d277e78245adc38c23 100644 (file)
@@ -38,7 +38,7 @@ namespace Microsoft.Diagnostics.DebugServices
         /// <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).
@@ -46,7 +46,7 @@ namespace Microsoft.Diagnostics.DebugServices
         /// <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
@@ -65,7 +65,7 @@ namespace Microsoft.Diagnostics.DebugServices
         /// <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
@@ -73,6 +73,6 @@ namespace Microsoft.Diagnostics.DebugServices
         /// <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);
     }
 }
index 526bb1d0ad761043f5be53964583b93ded77eb29..2e260d549d39fe5d91d106134f93a96268b13c9e 100644 (file)
@@ -3,6 +3,7 @@
 // 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
@@ -18,26 +19,26 @@ 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
                 {
index fc5a5ecbb0ea72fe3c6ac0dd01e35086ee36bd51..da7141019dd4ee57f5b23493b3b2c47f76ac1426 100644 (file)
@@ -23,7 +23,7 @@ namespace Microsoft.Diagnostics.ExtensionCommands
             }
             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)
                     {
index edc0b9ccf898ffc311e97f8ae84e408902ae4e55..a00b555372454042390ed6ce8a7d37bac0fcfde1 100644 (file)
@@ -27,7 +27,7 @@ namespace Microsoft.Diagnostics.ExtensionCommands
             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)
@@ -41,9 +41,12 @@ namespace Microsoft.Diagnostics.ExtensionCommands
             }
             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());
                 }
index b88743f5f5ec64cd614e950bfeb0881d0cd59f0d..4c7c2d2ac6bd7c9febdf4616a7c685cd44b4e69d 100644 (file)
@@ -27,11 +27,11 @@ namespace Microsoft.Diagnostics.ExtensionCommands
                 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;
             }
@@ -43,9 +43,9 @@ namespace Microsoft.Diagnostics.ExtensionCommands
                     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);
index da2b15fe9b48b98e1397a282f9c0d1531733c671..a9fd5dc9f5fcefaab0d37e60ef88a2fbdd42598c 100644 (file)
@@ -2,11 +2,13 @@
 // 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;
@@ -28,9 +30,12 @@ namespace SOS
 
         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)
@@ -109,6 +114,9 @@ namespace SOS
         {
             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)
             {
@@ -244,23 +252,75 @@ namespace SOS
         {
             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);
             }
         }
     }
@@ -288,5 +348,7 @@ namespace SOS
         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;
     }
 }
index 25de047599c8eca637059f90d7bf78b22ae1f821..885e452d668c2a98adc3e33f0cb031bdbc7053dd 100644 (file)
@@ -21,7 +21,7 @@ namespace SOS.Extensions
     /// <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");
 
@@ -54,13 +54,17 @@ namespace SOS.Extensions
             }
         }
 
+        /// <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)
         {
@@ -81,8 +85,8 @@ namespace SOS.Extensions
             {
                 return HResult.E_FAIL;
             }
-            var hostServices = new HostServices();
-            return initialializeCallback(hostServices.IHostServices);
+            Instance = new HostServices();
+            return initialializeCallback(Instance.IHostServices);
         }
 
         private HostServices()
@@ -120,10 +124,12 @@ namespace SOS.Extensions
 
         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();
@@ -151,7 +157,7 @@ namespace SOS.Extensions
             // Create the wrapper for the host debugger services
             try
             {
-                DebuggerServices = new DebuggerServices(iunk);
+                DebuggerServices = new DebuggerServices(iunk, HostType);
             }
             catch (InvalidCastException ex)
             {
@@ -166,6 +172,7 @@ namespace SOS.Extensions
             catch (InvalidCastException)
             {
             }
+            HResult hr;
             try
             {
                 var consoleService = new ConsoleServiceFromDebuggerServices(DebuggerServices);
@@ -176,7 +183,7 @@ namespace SOS.Extensions
                 // 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}");
@@ -188,13 +195,18 @@ namespace SOS.Extensions
                 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;
         }
 
@@ -336,7 +348,7 @@ namespace SOS.Extensions
                 {
                     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;
                 });
index 54d8d8ca81b8cd781a884a7d9cefce6fd971c2df..392999c8e613424ed1a63077648ad046b4bc92be 100644 (file)
@@ -10,6 +10,7 @@ using Microsoft.Diagnostics.Runtime.Utilities;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.IO;
 using System.Runtime.InteropServices;
 
 namespace SOS.Extensions
@@ -19,8 +20,11 @@ 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;
 
@@ -30,16 +34,19 @@ namespace SOS.Extensions
                 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
@@ -52,9 +59,9 @@ namespace SOS.Extensions
 
             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
             {
@@ -104,6 +111,20 @@ namespace SOS.Extensions
 
             #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;
         }
 
@@ -132,11 +153,11 @@ namespace SOS.Extensions
                     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);
index 36b9e99974a99288aca294721d48f3cf3eecc8fb..dfb28e7be206dd6626f19398fd3775686b6411f0 100644 (file)
@@ -57,7 +57,6 @@ namespace SOS.Extensions
 
         protected override IEnumerable<IThread> GetThreadsInner()
         {
-            var threads = new List<IThread>();
             HResult hr = _debuggerServices.GetNumberThreads(out uint number);
             if (hr == HResult.S_OK)
             {
@@ -68,8 +67,7 @@ namespace SOS.Extensions
                 {
                     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
@@ -81,7 +79,6 @@ namespace SOS.Extensions
             {
                 Trace.TraceError("GetNumberThreads() FAILED {0:X8}", hr);
             }
-            return threads;
         }
 
         protected override ulong GetThreadTeb(uint threadId)
index 9c9017d58306ef49f2f4364b41460c9a8e48f5f8..a67deb10b92077698dbc3d2d9f10185f052793cb 100644 (file)
@@ -139,7 +139,7 @@ namespace SOS.Hosting
             byte[] registerContext;
             try
             {
-                registerContext = _threadService.GetThreadInfoFromId(threadId).GetThreadContext();
+                registerContext = _threadService.GetThreadFromId(threadId).GetThreadContext();
             }
             catch (DiagnosticsException)
             {
index f685d285ace3c74aa216cb340cc25deb692040e8..6b3055761256774fddbdf06651830e88f3fb7639 100644 (file)
@@ -210,7 +210,7 @@ namespace SOS.Hosting
             byte[] registerContext;
             try
             {
-                registerContext = _threadService.GetThreadInfoFromId(threadId).GetThreadContext();
+                registerContext = _threadService.GetThreadFromId(threadId).GetThreadContext();
             }
             catch (DiagnosticsException)
             {
index 9ec3a2791f6b52d7314cb752b164cefe9331fdd1..93f08e4b5fd1621e414d80a7e2358127f9c7a0ec 100644 (file)
@@ -195,8 +195,8 @@ namespace SOS.Hosting
                 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)
             {
index dd478b9133587d3daa0273a4d78523852cfb04c1..c22457a053d8e800a5e0f42876ff0c1927a49c72 100644 (file)
@@ -37,6 +37,10 @@ namespace SOS.Hosting
         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;
@@ -499,8 +503,8 @@ namespace SOS.Hosting
                     {
                         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;
 
@@ -672,7 +676,7 @@ namespace SOS.Hosting
             byte[] registerContext;
             try
             {
-                registerContext = ThreadService.GetThreadInfoFromId(threadId).GetThreadContext();
+                registerContext = ThreadService.GetThreadFromId(threadId).GetThreadContext();
             }
             catch (DiagnosticsException)
             {
@@ -744,7 +748,7 @@ namespace SOS.Hosting
         {
             try
             {
-                ThreadService.CurrentThreadId = ThreadService.GetThreadInfoFromIndex(unchecked((int)id)).ThreadId;
+                ThreadService.CurrentThreadId = ThreadService.GetThreadFromIndex(unchecked((int)id)).ThreadId;
             }
             catch (DiagnosticsException)
             {
@@ -805,7 +809,7 @@ namespace SOS.Hosting
             {
                 try
                 {
-                    IThread threadInfo = ThreadService.GetThreadInfoFromId(sysId);
+                    IThread threadInfo = ThreadService.GetThreadFromId(sysId);
                     id = (uint)threadInfo.ThreadIndex;
                     return HResult.S_OK;
                 }
@@ -826,7 +830,7 @@ namespace SOS.Hosting
                 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;
                 }
@@ -864,7 +868,7 @@ namespace SOS.Hosting
             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;
             }
@@ -909,7 +913,7 @@ namespace SOS.Hosting
             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;
             }
@@ -922,10 +926,10 @@ namespace SOS.Hosting
         {
             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;
                     }
index 9b587e3147a0f2e82a54d879cff153e8872a90d8..a01445e94b7f6d2e45f20cdff8f2b54b3b6be7a0 100644 (file)
@@ -232,6 +232,8 @@ namespace SOS.Hosting
                    (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);
index b3996d7f3a886885f198a34997909e5ea05602ae..0c398b39ab0c0916a34712242927bd0f853a19ee 100644 (file)
@@ -9,6 +9,8 @@
 #include "dbgengservices.h"
 #include "exts.h"
 
+extern IMachine* GetTargetMachine(ULONG processorType);
+
 DbgEngServices::DbgEngServices(IDebugClient* client) :
     m_ref(1),
     m_client(client),
@@ -16,7 +18,8 @@ DbgEngServices::DbgEngServices(IDebugClient* client) :
     m_data(nullptr),
     m_symbols(nullptr),
     m_system(nullptr),
-    m_advanced(nullptr)
+    m_advanced(nullptr),
+    m_targetMachine(nullptr)
 {
     client->AddRef();
 }
@@ -325,7 +328,7 @@ DbgEngServices::GetThreadContextBySystemId(
     {
         // 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);
@@ -334,7 +337,7 @@ DbgEngServices::GetThreadContextBySystemId(
         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;
 }
@@ -400,6 +403,41 @@ DbgEngServices::GetSymbolPath(
 {
     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
@@ -464,6 +502,13 @@ HRESULT DbgEngServices::ChangeEngineState(
     {
         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();
         }
@@ -517,6 +562,7 @@ HRESULT DbgEngServices::Exception(
 HRESULT DbgEngServices::ExitProcess(
     ULONG ExitCode)
 {
+    m_targetMachine = nullptr;
     Extensions::GetInstance()->DestroyTarget();
     return DEBUG_STATUS_NO_CHANGE;
 }
@@ -572,6 +618,18 @@ HRESULT DbgEngServices::UnloadModule(
 // 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,
index 1ca1af894ea64ce110d491d2e5e1d28695f37410..8dc7852a948b1fb774e18668128b685ee3f90e2e 100644 (file)
@@ -13,6 +13,8 @@
 
 #define VER_PLATFORM_UNIX 10 
 
+class IMachine;
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -27,6 +29,7 @@ private:
     PDEBUG_SYMBOLS2       m_symbols;
     PDEBUG_SYSTEM_OBJECTS m_system;
     PDEBUG_ADVANCED       m_advanced;
+    IMachine*             m_targetMachine;
 
 public:
     DbgEngServices(IDebugClient* client);
@@ -38,6 +41,8 @@ public:
     // Helper functions
     //----------------------------------------------------------------------------
 
+    IMachine* GetMachine();
+
     HRESULT SetCurrentThreadIdFromSystemId(
         ULONG32 sysId,
         PULONG originalThreadId);
@@ -162,6 +167,19 @@ public:
         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
     //----------------------------------------------------------------------------
index 003a145af1914a9c65c757f066626424fca0e5d3..adede7e4c48447fd7e4b4c840737dab85b6a0b88 100644 (file)
@@ -57,13 +57,13 @@ PDEBUG_SYSTEM_OBJECTS g_ExtSystem;
 
 // 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.
@@ -106,28 +106,24 @@ ExtQuery(ILLDBServices* services)
     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:
@@ -137,20 +133,45 @@ ArchQuery(void)
     }
 #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;
 }
 
index 1390ea64210666ccfef4f894b969ce0e26ebdac7..2f0f0bfc9c80d8158181a1355c83c9a335e7bde6 100644 (file)
@@ -16818,7 +16818,13 @@ DECLARE_API(ext)
     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 
     {
index c84dae05ff62fd4003e11c53bead5ac9445063eb..58060a344d9fa94f3a4df9cec6f445cfc4c873e0 100644 (file)
@@ -130,6 +130,19 @@ public:
         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
index 76797a9751efd7d75251bafc810151f4e270c6db..20256653a0693b0b7b6e45d75a3690d67214744e 100644 (file)
 
 #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;
@@ -826,6 +830,18 @@ LLDBServices::GetNameByOffset(
     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;
@@ -854,17 +870,36 @@ LLDBServices::GetNameByOffset(
         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();
@@ -1854,11 +1889,11 @@ HRESULT LLDBServices::GetModuleInfo(
     }
     if (pTimestamp)
     {
-        *pTimestamp = 0;
+        *pTimestamp = InvalidTimeStamp;
     }
     if (pChecksum)
     {
-        *pChecksum = 0;
+        *pChecksum = InvalidChecksum;
     }
     return S_OK;
 }
@@ -2229,7 +2264,8 @@ LLDBServices::GetThreadTeb(
     return E_NOTIMPL;
 }
 
-HRESULT LLDBServices::GetSymbolPath(
+HRESULT 
+LLDBServices::GetSymbolPath(
     PSTR buffer,
     ULONG bufferSize,
     PULONG pathSize)
@@ -2237,6 +2273,63 @@ HRESULT LLDBServices::GetSymbolPath(
     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
 //----------------------------------------------------------------------------
@@ -2535,4 +2628,4 @@ LLDBServices::InternalOutputVaList(
         }
     }
     return result;
-}
\ No newline at end of file
+}
index 0be29e1c4e6732f9852c85658c69da92751a9e74..14912afd1d540bc9680e97711ebb128d87e4004b 100644 (file)
@@ -197,6 +197,14 @@ public:
         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);
@@ -363,7 +371,20 @@ public:
         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)
     //----------------------------------------------------------------------------
index f45d92b03762702b0d14c17c4912de08c5bfba2c..59d22fa940992f60975e068df843a7e9e06430ee 100644 (file)
@@ -149,6 +149,7 @@ bool
 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.");
index 61a52210961d63d203c3b45213b75b9119d5120c..81bc6198212d37ab2e006b0488060aa1713f07bb 100644 (file)
@@ -14,6 +14,7 @@ using System.Reflection;
 using System.Runtime.InteropServices;
 using System.Threading;
 using System.Threading.Tasks;
+using System.Collections.Generic;
 
 namespace Microsoft.Diagnostics.Tools.Dump
 {
@@ -130,7 +131,7 @@ 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;
                 });
@@ -155,6 +156,8 @@ namespace Microsoft.Diagnostics.Tools.Dump
 
         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();