зеркало из https://github.com/dotnet/diagnostics.git
Fix various issues (#690)
Issue: https://github.com/dotnet/diagnostics/issues/673 SymbolReader doesn't support UNC symbol paths. Issue: https://github.com/dotnet/diagnostics/issues/674 Add -all gcroot option to docs. Issue: https://github.com/dotnet/diagnostics/issues/632 Better doc clrstack -all and other options. Issue: https://github.com/dotnet/diagnostics/issues/576 Doc RHEL lldb install. Issue: https://github.com/dotnet/diagnostics/issues/483 Add setclrpath command to dotnet-dump on linux. Mentioned in https://github.com/dotnet/diagnostics/issues/624 Issue: https://github.com/dotnet/diagnostics/issues/590 Add -timeout option to SetSymbolServer command. Issue: https://github.com/dotnet/diagnostics/issues/602 Use CommandPlatform on Windows specific commands Don't use the desktop clr to host SOS managed code. Don't allow dumplog on desktop clr target. Cleanup SOSHost "is runtime" checks. Removed unneeded install of the x86 SDK in InstallRuntimes.proj Fix SOS on Windows where it needs to download the DAC but the symbol server store was never initialized from the .sympath. This is even more important when both coreclr and desktop clr are loaded in the process/minidump. Update to 3.0.1 runtime version
This commit is contained in:
Родитель
49ff7a2091
Коммит
19eb443665
|
@ -193,7 +193,7 @@ To launch lldb:
|
|||
|
||||
#### RHEL 7.5 ####
|
||||
|
||||
[TBD]
|
||||
See [LLDB](https://access.redhat.com/documentation/en-us/red_hat_developer_tools/2018.2/html/using_clang_and_llvm_toolset/chap-lldb) on RedHat's web site.
|
||||
|
||||
#### SLES ####
|
||||
|
||||
|
|
|
@ -71,7 +71,7 @@ Type `!help <functionname>` for detailed info on that function.
|
|||
|-------------|-----------------|
|
||||
|**AnalyzeOOM** (**ao**)|Displays the information for the last out of memory (OOM) that occurred on an allocation request to the garbage collection heap. (In server garbage collection, it displays OOM, if any, on each garbage collection heap.)|
|
||||
|**BPMD** (**bpmd**) [**-nofuturemodule**] [\<*module name*> \<*method name*>] [**-md** <`MethodDesc`>] **-list** **-clear** \<*pending breakpoint number*> **-clearall**|Creates a breakpoint at the specified method in the specified module.<br /><br /> If the specified module and method have not been loaded, this command waits for a notification that the module was loaded and just-in-time (JIT) compiled before creating a breakpoint.<br /><br /> You can manage the list of pending breakpoints by using the **-list**, **-clear**, and **-clearall** options:<br /><br /> The **-list** option generates a list of all the pending breakpoints. If a pending breakpoint has a non-zero module ID, that breakpoint is specific to a function in that particular loaded module. If the pending breakpoint has a zero module ID, that breakpoint applies to modules that have not yet been loaded.<br /><br /> Use the **-clear** or **-clearall** option to remove pending breakpoints from the list.|
|
||||
|**CLRStack** [**-a**] [**-l**] [**-p**] [**-n**]|Provides a stack trace of managed code only.<br /><br /> The **-p** option shows arguments to the managed function.<br /><br /> The **-l** option shows information on local variables in a frame. The SOS Debugging Extension cannot retrieve local names, so the output for local names is in the format \<*local address*> **=** \<*value*>.<br /><br /> The **-a**(all) option is a shortcut for **-l** and **-p** combined.<br /><br /> The **-n** option disables the display of source file names and line numbers. If the debugger has the option SYMOPT_LOAD_LINES specified, SOS will look up the symbols for every managed frame and if successful will display the corresponding source file name and line number. The **-n** (No line numbers) parameter can be specified to disable this behavior.<br /><br /> The SOS Debugging Extension does not display transition frames on x64 and IA-64-based platforms.|
|
||||
|**CLRStack** [**-a**] [**-l**] [**-p**] [**-n**] [**-f**] [**-r**] [**-all**]|Provides a stack trace of managed code only.<br /><br /> The **-p** option shows arguments to the managed function.<br /><br /> The **-l** option shows information on local variables in a frame. The SOS Debugging Extension cannot retrieve local names, so the output for local names is in the format \<*local address*> **=** \<*value*>.<br /><br /> The **-a** option is a shortcut for **-l** and **-p** combined.<br /><br /> The **-n** option disables the display of source file names and line numbers. If the debugger has the option SYMOPT_LOAD_LINES specified, SOS will look up the symbols for every managed frame and if successful will display the corresponding source file name and line number. The **-n** (No line numbers) parameter can be specified to disable this behavior.<br /><br />The **-f** option (full mode) displays the native frames intermixing them with the managed frames and the assembly name and function offset for the managed frames.<br /><br />The **-r** option dumps the registers for each stack frame.<br /><br />The **-all** option dumps all the managed threads' stacks.|
|
||||
|**COMState**|Lists the COM apartment model for each thread and a `Context` pointer, if available.|
|
||||
|**DumpArray** [**-start** \<*startIndex*>] [**-length** \<*length*>] [**-details**] [**-nofields**] \<*array object address*><br /><br /> -or-<br /><br /> **DA** [**-start** \<*startIndex*>] [**-length** \<*length*>] [**-detail**] [**-nofields**] *array object address*>|Examines elements of an array object.<br /><br /> The **-start** option specifies the starting index at which to display elements.<br /><br /> The **-length** option specifies how many elements to show.<br /><br /> The **-details** option displays details of the element using the **DumpObj** and **DumpVC** formats.<br /><br /> The **-nofields** option prevents arrays from displaying. This option is available only when the **-detail** option is specified.|
|
||||
|**DumpAssembly** \<*assembly address*>|Displays information about an assembly.<br /><br /> The **DumpAssembly** command lists multiple modules, if they exist.<br /><br /> You can get an assembly address by using the **DumpDomain** command.|
|
||||
|
@ -101,7 +101,7 @@ Type `!help <functionname>` for detailed info on that function.
|
|||
|**GCHandles** [**-perdomain**]|Displays statistics about garbage collector handles in the process.<br /><br /> The **-perdomain** option arranges the statistics by application domain.<br /><br /> Use the **GCHandles** command to find memory leaks caused by garbage collector handle leaks. For example, a memory leak occurs when code retains a large array because a strong garbage collector handle still points to it, and the handle is discarded without freeing it.|
|
||||
|**GCHandleLeaks**|Searches memory for any references to strong and pinned garbage collector handles in the process and displays the results. If a handle is found, the **GCHandleLeaks** command displays the address of the reference. If a handle is not found in memory, this command displays a notification.|
|
||||
|**GCInfo** \<*MethodDesc address*>\<*Code address*>|Displays data that indicates when registers or stack locations contain managed objects. If a garbage collection occurs, the collector must know the locations of references to objects so it can update them with new object pointer values.|
|
||||
|**GCRoot** [**-nostacks**] \<*Object address*>|Displays information about references (or roots) to an object at the specified address.<br /><br /> The **GCRoot** command examines the entire managed heap and the handle table for handles within other objects and handles on the stack. Each stack is then searched for pointers to objects, and the finalizer queue is also searched.<br /><br /> This command does not determine whether a stack root is valid or is discarded. Use the **CLRStack** and **U** commands to disassemble the frame that the local or argument value belongs to in order to determine if the stack root is still in use.<br /><br /> The **-nostacks** option restricts the search to garbage collector handles and freachable objects.|
|
||||
|**GCRoot** [**-nostacks**] [**-all**] \<*Object address*>|Displays information about references (or roots) to an object at the specified address.<br /><br /> The **GCRoot** command examines the entire managed heap and the handle table for handles within other objects and handles on the stack. Each stack is then searched for pointers to objects, and the finalizer queue is also searched.<br /><br /> This command does not determine whether a stack root is valid or is discarded. Use the **CLRStack** and **U** commands to disassemble the frame that the local or argument value belongs to in order to determine if the stack root is still in use.<br /><br /> The **-nostacks** option restricts the search to garbage collector handles and reachable objects.<br /><br /> The **-all** option forces all roots to be displayed instead of just the unique roots.|
|
||||
|**GCWhere** *\<object address>*|Displays the location and size in the garbage collection heap of the argument passed in. When the argument lies in the managed heap but is not a valid object address, the size is displayed as 0 (zero).|
|
||||
|**Help** (**soshelp**) [\<*command*>] [`faq`]|Displays all available commands when no parameter is specified, or displays detailed help information about the specified command.<br /><br /> The `faq` parameter displays answers to frequently asked questions.|
|
||||
|**HeapStat** [**-inclUnrooted** | **-iu**]|Displays the generation sizes for each heap and the total free space in each generation on each heap. If the -**inclUnrooted** option is specified, the report includes information about the managed objects from the garbage collection heap that is no longer rooted.|
|
||||
|
|
|
@ -72,7 +72,7 @@ importance. Shortcut names for popular functions are listed in parenthesis. Type
|
|||
|Command|Description|
|
||||
|-------------|-----------------|
|
||||
|**bpmd** [**-nofuturemodule**] [\<*module name*> \<*method name*>] [**-md** <`MethodDesc`>] **-list** **-clear** \<*pending breakpoint number*> **-clearall**|Creates a breakpoint at the specified method in the specified module.<br /><br /> If the specified module and method have not been loaded, this command waits for a notification that the module was loaded and just-in-time (JIT) compiled before creating a breakpoint.<br /><br /> You can manage the list of pending breakpoints by using the **-list**, **-clear**, and **-clearall** options:<br /><br /> The **-list** option generates a list of all the pending breakpoints. If a pending breakpoint has a non-zero module ID, that breakpoint is specific to a function in that particular loaded module. If the pending breakpoint has a zero module ID, that breakpoint applies to modules that have not yet been loaded.<br /><br /> Use the **-clear** or **-clearall** option to remove pending breakpoints from the list.|
|
||||
|**ClrStack** (**clrstack**) [**-a**] [**-l**] [**-p**] [**-n**]|Provides a stack trace of managed code only.<br /><br /> The **-p** option shows arguments to the managed function.<br /><br /> The **-l** option shows information on local variables in a frame. The SOS Debugging Extension cannot retrieve local names, so the output for local names is in the format \<*local address*> **=** \<*value*>.<br /><br /> The **-a**(all) option is a shortcut for **-l** and **-p** combined.<br /><br /> The **-n** option disables the display of source file names and line numbers. If the debugger has the option SYMOPT_LOAD_LINES specified, SOS will look up the symbols for every managed frame and if successful will display the corresponding source file name and line number. The **-n** (No line numbers) parameter can be specified to disable this behavior.<br /><br /> The SOS Debugging Extension does not display transition frames on x64 and IA-64-based platforms.|
|
||||
|**CLRStack** [**-a**] [**-l**] [**-p**] [**-n**] [**-f**] [**-r**] [**-all**]|Provides a stack trace of managed code only.<br /><br /> The **-p** option shows arguments to the managed function.<br /><br /> The **-l** option shows information on local variables in a frame. The SOS Debugging Extension cannot retrieve local names, so the output for local names is in the format \<*local address*> **=** \<*value*>.<br /><br /> The **-a** option is a shortcut for **-l** and **-p** combined.<br /><br /> The **-n** option disables the display of source file names and line numbers. If the debugger has the option SYMOPT_LOAD_LINES specified, SOS will look up the symbols for every managed frame and if successful will display the corresponding source file name and line number. The **-n** (No line numbers) parameter can be specified to disable this behavior.<br /><br />The **-f** option (full mode) displays the native frames intermixing them with the managed frames and the assembly name and function offset for the managed frames.<br /><br />The **-r** option dumps the registers for each stack frame.<br /><br />The **-all** option dumps all the managed threads' stacks.|
|
||||
|**DumpArray** [**-start** \<*startIndex*>] [**-length** \<*length*>] [**-details**] [**-nofields**] \<*array object address*><br /><br /> -or-<br /><br /> **DA** [**-start** \<*startIndex*>] [**-length** \<*length*>] [**-detail**] [**-nofields**] *array object address*>|Examines elements of an array object.<br /><br /> The **-start** option specifies the starting index at which to display elements.<br /><br /> The **-length** option specifies how many elements to show.<br /><br /> The **-details** option displays details of the element using the **DumpObj** and **DumpVC** formats.<br /><br /> The **-nofields** option prevents arrays from displaying. This option is available only when the **-detail** option is specified.|
|
||||
|**DumpAsync** (**dumpasync**) [**-mt** \<*MethodTable address*>] [**-type** \<*partial type name*>] [**-waiting**] [**-roots**]|DumpAsync traverses the garbage collected heap, looking for objects representing async state machines as created when an async method's state is transferred to the heap. This command recognizes async state machines defined as `async void`, `async Task`, `async Task<T>`, `async ValueTask`, and `async ValueTask<T>`.<br /><br />The output includes a block of details for each async state machine object found. These details include:<br />- a line for the type of the async state machine object, including its MethodTable address, its object address, its size, and its type name.<br />- a line for the state machine type name as contained in the object.<br />- a listing of each field on the state machine.<br />- a line for a continuation from this state machine object, if one or more has been registered.<br />- discovered GC roots for this async state machine object.<br />|
|
||||
|**DumpAssembly** \<*assembly address*>|Displays information about an assembly.<br /><br /> The **DumpAssembly** command lists multiple modules, if they exist.<br /><br /> You can get an assembly address by using the **DumpDomain** command.|
|
||||
|
@ -97,7 +97,7 @@ importance. Shortcut names for popular functions are listed in parenthesis. Type
|
|||
|**FAQ**|Displays frequently asked questions.|
|
||||
|**FindAppDomain** \<*Object address*>|Determines the application domain of an object at the specified address.|
|
||||
|**GCInfo** \<*MethodDesc address*>\<*Code address*>|Displays data that indicates when registers or stack locations contain managed objects. If a garbage collection occurs, the collector must know the locations of references to objects so it can update them with new object pointer values.|
|
||||
|**GCRoot** [**-nostacks**] \<*Object address*>|Displays information about references (or roots) to an object at the specified address.<br /><br /> The **GCRoot** command examines the entire managed heap and the handle table for handles within other objects and handles on the stack. Each stack is then searched for pointers to objects, and the finalizer queue is also searched.<br /><br /> This command does not determine whether a stack root is valid or is discarded. Use the **clrstack** and **U** commands to disassemble the frame that the local or argument value belongs to in order to determine if the stack root is still in use.<br /><br /> The **-nostacks** option restricts the search to garbage collector handles and freachable objects.|
|
||||
|**GCRoot** [**-nostacks**] [**-all**] \<*Object address*>|Displays information about references (or roots) to an object at the specified address.<br /><br /> The **GCRoot** command examines the entire managed heap and the handle table for handles within other objects and handles on the stack. Each stack is then searched for pointers to objects, and the finalizer queue is also searched.<br /><br /> This command does not determine whether a stack root is valid or is discarded. Use the **clrstack** and **U** commands to disassemble the frame that the local or argument value belongs to in order to determine if the stack root is still in use.<br /><br /> The **-nostacks** option restricts the search to garbage collector handles and reachable objects.<br /><br /> The **-all** option forces all roots to be displayed instead of just the unique roots.|
|
||||
|**GCWhere** *\<object address>*|Displays the location and size in the garbage collection heap of the argument passed in. When the argument lies in the managed heap but is not a valid object address, the size is displayed as 0 (zero).|
|
||||
|**Help** (**soshelp**) [\<*command*>] [`faq`]|Displays all available commands when no parameter is specified, or displays detailed help information about the specified command.<br /><br /> The `faq` parameter displays answers to frequently asked questions.|
|
||||
|**HistClear**|Releases any resources used by the family of `Hist` commands.<br /><br /> Generally, you do not have to explicitly call `HistClear`, because each `HistInit` cleans up the previous resources.|
|
||||
|
|
|
@ -56,10 +56,6 @@
|
|||
Condition="$([MSBuild]::IsOsPlatform(Windows))"
|
||||
Inputs="$(VersionsPropsPath)" Outputs="$(TestConfigFileName)">
|
||||
|
||||
<!-- Install SDK for the x86 architecture -->
|
||||
<Exec Command="$(PowershellWrapper) "& { &$(DotnetInstallScriptCmd) $(CommonInstallArgs) -version $(NETCoreSDKVersion) }""
|
||||
Condition="'$(BuildArch)' == 'x86'" />
|
||||
|
||||
<Exec Command="$(PowershellWrapper) "& { &$(DotnetInstallScriptCmd) $(CommonInstallArgs) -version %(TestVersions.RuntimeVersion) -runtime dotnet }""
|
||||
Condition="%(TestVersions.Install)" />
|
||||
|
||||
|
|
|
@ -8,12 +8,10 @@
|
|||
<AutoGenerateAssemblyVersion>true</AutoGenerateAssemblyVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<!-- SDK Version from global.json -->
|
||||
<NETCoreSDKVersion>3.0.100</NETCoreSDKVersion>
|
||||
<!-- Runtime versions to test -->
|
||||
<MicrosoftNETCoreApp21Version>2.1.12</MicrosoftNETCoreApp21Version>
|
||||
<MicrosoftAspNetCoreApp21Version>$(MicrosoftNETCoreApp21Version)</MicrosoftAspNetCoreApp21Version>
|
||||
<MicrosoftNETCoreApp30Version>3.0.0</MicrosoftNETCoreApp30Version>
|
||||
<MicrosoftNETCoreApp30Version>3.0.1</MicrosoftNETCoreApp30Version>
|
||||
<MicrosoftAspNetCoreApp30Version>$(MicrosoftNETCoreApp30Version)</MicrosoftAspNetCoreApp30Version>
|
||||
<MicrosoftNETCoreApp31Version>3.1.0</MicrosoftNETCoreApp31Version>
|
||||
<MicrosoftAspNetCoreApp31Version>$(MicrosoftNETCoreApp31Version)</MicrosoftAspNetCoreApp31Version>
|
||||
|
@ -33,7 +31,7 @@
|
|||
<MicrosoftWin32PrimitivesVersion>4.3.0</MicrosoftWin32PrimitivesVersion>
|
||||
<!-- Other libs -->
|
||||
<MicrosoftSymbolStoreVersion>1.0.55801</MicrosoftSymbolStoreVersion>
|
||||
<MicrosoftDiagnosticsRuntimeVersion>1.1.46104</MicrosoftDiagnosticsRuntimeVersion>
|
||||
<MicrosoftDiagnosticsRuntimeVersion>1.1.57004</MicrosoftDiagnosticsRuntimeVersion>
|
||||
<MicrosoftDiaSymReaderNativePackageVersion>1.7.0</MicrosoftDiaSymReaderNativePackageVersion>
|
||||
<MicrosoftDiagnosticsTracingTraceEventVersion>2.0.44</MicrosoftDiagnosticsTracingTraceEventVersion>
|
||||
<SystemCommandLineExperimentalVersion>0.3.0-alpha.19602.1</SystemCommandLineExperimentalVersion>
|
||||
|
|
|
@ -24,5 +24,10 @@ namespace Microsoft.Diagnostics.DebugServices
|
|||
/// Cancellation token for current command
|
||||
/// </summary>
|
||||
public CancellationToken CancellationToken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Directory of the runtime module (coreclr.dll, libcoreclr.so, etc.)
|
||||
/// </summary>
|
||||
public string RuntimeModuleDirectory { get; set; }
|
||||
}
|
||||
}
|
|
@ -7,7 +7,19 @@ using System;
|
|||
namespace Microsoft.Diagnostics.Repl
|
||||
{
|
||||
/// <summary>
|
||||
/// Base command option attribute.
|
||||
/// OS Platforms to add command
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum CommandPlatform : byte
|
||||
{
|
||||
All = 0x00,
|
||||
Windows = 0x01,
|
||||
Linux = 0x02,
|
||||
OSX = 0x04,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base command, option and argument class.
|
||||
/// </summary>
|
||||
public class BaseAttribute : Attribute
|
||||
{
|
||||
|
@ -22,11 +34,22 @@ namespace Microsoft.Diagnostics.Repl
|
|||
public string Help;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Base command and command alias class.
|
||||
/// </summary>
|
||||
public class CommandBaseAttribute : BaseAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Optional OS platform for the command
|
||||
/// </summary>
|
||||
public CommandPlatform Platform = CommandPlatform.All;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Marks the class as a Command.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
|
||||
public class CommandAttribute : BaseAttribute
|
||||
public class CommandAttribute : CommandBaseAttribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Sets the value of the CommandBase.AliasExpansion when the command is executed.
|
||||
|
@ -38,7 +61,7 @@ namespace Microsoft.Diagnostics.Repl
|
|||
/// Adds an alias to the previous command attribute
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
|
||||
public class CommandAliasAttribute : BaseAttribute
|
||||
public class CommandAliasAttribute : CommandBaseAttribute
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ using System.CommandLine.Invocation;
|
|||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Diagnostics.Repl
|
||||
|
@ -114,7 +115,7 @@ namespace Microsoft.Diagnostics.Repl
|
|||
var baseAttributes = (BaseAttribute[])type.GetCustomAttributes(typeof(BaseAttribute), inherit: false);
|
||||
foreach (BaseAttribute baseAttribute in baseAttributes)
|
||||
{
|
||||
if (baseAttribute is CommandAttribute commandAttribute)
|
||||
if (baseAttribute is CommandAttribute commandAttribute && IsValidPlatform(commandAttribute))
|
||||
{
|
||||
command = new Command(commandAttribute.Name, commandAttribute.Help);
|
||||
var properties = new List<(PropertyInfo, Option)>();
|
||||
|
@ -167,9 +168,10 @@ namespace Microsoft.Diagnostics.Repl
|
|||
rootBuilder.AddCommand(command);
|
||||
}
|
||||
|
||||
if (baseAttribute is CommandAliasAttribute commandAliasAttribute)
|
||||
if (baseAttribute is CommandAliasAttribute commandAliasAttribute && IsValidPlatform(commandAliasAttribute))
|
||||
{
|
||||
if (command == null) {
|
||||
if (command == null)
|
||||
{
|
||||
throw new ArgumentException($"No previous CommandAttribute for this CommandAliasAttribute: {type.Name}");
|
||||
}
|
||||
command.AddAlias(commandAliasAttribute.Name);
|
||||
|
@ -189,6 +191,29 @@ namespace Microsoft.Diagnostics.Repl
|
|||
return service;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the command should be added.
|
||||
/// </summary>
|
||||
private static bool IsValidPlatform(CommandBaseAttribute attribute)
|
||||
{
|
||||
if (attribute.Platform != CommandPlatform.All)
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
return (attribute.Platform & CommandPlatform.Windows) != 0;
|
||||
}
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
return (attribute.Platform & CommandPlatform.Linux) != 0;
|
||||
}
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
{
|
||||
return (attribute.Platform & CommandPlatform.OSX) != 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static string BuildAlias(string parameterName)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(parameterName)) {
|
||||
|
|
|
@ -92,13 +92,17 @@ namespace SOS
|
|||
string GetCoreClrDirectory(
|
||||
IntPtr self)
|
||||
{
|
||||
foreach (ModuleInfo module in _soshost.DataReader.EnumerateModules())
|
||||
if (_soshost.AnalyzeContext.RuntimeModuleDirectory == null)
|
||||
{
|
||||
if (SOSHost.IsRuntimeModule(module)) {
|
||||
return Path.GetDirectoryName(module.FileName) + Path.DirectorySeparatorChar;
|
||||
foreach (ModuleInfo module in _soshost.DataReader.EnumerateModules())
|
||||
{
|
||||
if (SOSHost.IsCoreClrRuntimeModule(module))
|
||||
{
|
||||
_soshost.AnalyzeContext.RuntimeModuleDirectory = Path.GetDirectoryName(module.FileName) + Path.DirectorySeparatorChar;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return _soshost.AnalyzeContext.RuntimeModuleDirectory;
|
||||
}
|
||||
|
||||
int VirtualUnwind(
|
||||
|
@ -175,7 +179,7 @@ namespace SOS
|
|||
{
|
||||
if (runtimeOnly)
|
||||
{
|
||||
if (SOSHost.IsRuntimeModule(module))
|
||||
if (SOSHost.IsCoreClrRuntimeModule(module))
|
||||
{
|
||||
callback(IntPtr.Zero, module.FileName, module.ImageBase, unchecked((int)module.FileSize));
|
||||
break;
|
||||
|
|
|
@ -6,17 +6,12 @@ using Microsoft.Diagnostics.DebugServices;
|
|||
using Microsoft.Diagnostics.Runtime;
|
||||
using Microsoft.Diagnostics.Runtime.Interop;
|
||||
using Microsoft.Diagnostics.Runtime.Utilities;
|
||||
using Microsoft.SymbolStore;
|
||||
using Microsoft.SymbolStore.KeyGenerators;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Reflection.PortableExecutable;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
|
@ -61,6 +56,7 @@ namespace SOS
|
|||
bool symweb,
|
||||
string tempDirectory,
|
||||
string symbolServerPath,
|
||||
int timeoutInMintues,
|
||||
string symbolCachePath,
|
||||
string symbolDirectoryPath,
|
||||
string windowsSymbolPath);
|
||||
|
@ -155,13 +151,13 @@ namespace SOS
|
|||
GetExpressionDelegate = SOSHost.GetExpression,
|
||||
};
|
||||
|
||||
internal readonly IDataReader DataReader;
|
||||
|
||||
const string DesktopRuntimeModuleName = "clr";
|
||||
|
||||
private static readonly string s_coreclrModuleName;
|
||||
|
||||
private readonly AnalyzeContext _analyzeContext;
|
||||
internal readonly IDataReader DataReader;
|
||||
internal readonly AnalyzeContext AnalyzeContext;
|
||||
|
||||
private readonly RegisterService _registerService;
|
||||
private readonly MemoryService _memoryService;
|
||||
private readonly IConsoleService _console;
|
||||
|
@ -203,7 +199,7 @@ namespace SOS
|
|||
DataTarget dataTarget = serviceProvider.GetService<DataTarget>();
|
||||
DataReader = dataTarget.DataReader;
|
||||
_console = serviceProvider.GetService<IConsoleService>();
|
||||
_analyzeContext = serviceProvider.GetService<AnalyzeContext>();
|
||||
AnalyzeContext = serviceProvider.GetService<AnalyzeContext>();
|
||||
_memoryService = serviceProvider.GetService<MemoryService>();
|
||||
_registerService = serviceProvider.GetService<RegisterService>();
|
||||
_versionCache = new ReadVirtualCache(_memoryService);
|
||||
|
@ -343,7 +339,7 @@ namespace SOS
|
|||
internal int GetInterrupt(
|
||||
IntPtr self)
|
||||
{
|
||||
return _analyzeContext.CancellationToken.IsCancellationRequested ? S_OK : E_FAIL;
|
||||
return AnalyzeContext.CancellationToken.IsCancellationRequested ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
internal int OutputVaList(
|
||||
|
@ -877,7 +873,7 @@ namespace SOS
|
|||
IntPtr context,
|
||||
uint contextSize)
|
||||
{
|
||||
uint threadId = (uint)_analyzeContext.CurrentThreadId;
|
||||
uint threadId = (uint)AnalyzeContext.CurrentThreadId;
|
||||
byte[] registerContext = _registerService.GetThreadContext(threadId);
|
||||
if (registerContext == null) {
|
||||
return E_FAIL;
|
||||
|
@ -934,7 +930,7 @@ namespace SOS
|
|||
IntPtr self,
|
||||
out uint id)
|
||||
{
|
||||
return GetThreadIdBySystemId(self, (uint)_analyzeContext.CurrentThreadId, out id);
|
||||
return GetThreadIdBySystemId(self, (uint)AnalyzeContext.CurrentThreadId, out id);
|
||||
}
|
||||
|
||||
internal int SetCurrentThreadId(
|
||||
|
@ -944,7 +940,7 @@ namespace SOS
|
|||
try
|
||||
{
|
||||
unchecked {
|
||||
_analyzeContext.CurrentThreadId = (int)DataReader.EnumerateAllThreads().ElementAt((int)id);
|
||||
AnalyzeContext.CurrentThreadId = (int)DataReader.EnumerateAllThreads().ElementAt((int)id);
|
||||
}
|
||||
}
|
||||
catch (ArgumentOutOfRangeException)
|
||||
|
@ -958,7 +954,7 @@ namespace SOS
|
|||
IntPtr self,
|
||||
out uint sysId)
|
||||
{
|
||||
sysId = (uint)_analyzeContext.CurrentThreadId;
|
||||
sysId = (uint)AnalyzeContext.CurrentThreadId;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -1014,7 +1010,7 @@ namespace SOS
|
|||
IntPtr self,
|
||||
ulong* offset)
|
||||
{
|
||||
uint threadId = (uint)_analyzeContext.CurrentThreadId;
|
||||
uint threadId = (uint)AnalyzeContext.CurrentThreadId;
|
||||
ulong teb = DataReader.GetThreadTeb(threadId);
|
||||
Write(offset, teb);
|
||||
return S_OK;
|
||||
|
@ -1102,21 +1098,23 @@ namespace SOS
|
|||
int index,
|
||||
out ulong value)
|
||||
{
|
||||
uint threadId = (uint)_analyzeContext.CurrentThreadId;
|
||||
uint threadId = (uint)AnalyzeContext.CurrentThreadId;
|
||||
if (!_registerService.GetRegisterValue(threadId, index, out value)) {
|
||||
return E_FAIL;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
internal static bool IsRuntimeModule(ModuleInfo module)
|
||||
internal static bool IsCoreClrRuntimeModule(ModuleInfo module)
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && IsModuleEqual(module, DesktopRuntimeModuleName)) {
|
||||
return true;
|
||||
}
|
||||
return IsModuleEqual(module, s_coreclrModuleName);
|
||||
}
|
||||
|
||||
internal static bool IsDesktopRuntimeModule(ModuleInfo module)
|
||||
{
|
||||
return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && IsModuleEqual(module, DesktopRuntimeModuleName);
|
||||
}
|
||||
|
||||
internal static bool IsModuleEqual(ModuleInfo module, string moduleName)
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
|
||||
|
|
|
@ -172,15 +172,25 @@ namespace SOS
|
|||
/// symbol servers. This API can be called more than once to add more servers to search.
|
||||
/// </summary>
|
||||
/// <param name="logging">if true, enable logging diagnostics to console</param>
|
||||
/// <param name="msdl">if true, use the public microsoft server</param>
|
||||
/// <param name="msdl">if true, use the public Microsoft server</param>
|
||||
/// <param name="symweb">if true, use symweb internal server and protocol (file.ptr)</param>
|
||||
/// <param name="tempDirectory">temp directory unique to this instance of SOS</param>
|
||||
/// <param name="symbolServerPath">symbol server url (optional)</param>
|
||||
/// <param name="timeoutInMinutes">symbol server timeout in minutes (optional)</param>
|
||||
/// <param name="symbolCachePath">symbol cache directory path (optional)</param>
|
||||
/// <param name="symbolDirectoryPath">symbol directory path to search (optional)</param>
|
||||
/// <param name="windowsSymbolPath">windows symbol path (optional)</param>
|
||||
/// <returns>if false, failure</returns>
|
||||
public static bool InitializeSymbolStore(bool logging, bool msdl, bool symweb, string tempDirectory, string symbolServerPath, string symbolCachePath, string symbolDirectoryPath, string windowsSymbolPath)
|
||||
public static bool InitializeSymbolStore(
|
||||
bool logging,
|
||||
bool msdl,
|
||||
bool symweb,
|
||||
string tempDirectory,
|
||||
string symbolServerPath,
|
||||
int timeoutInMinutes,
|
||||
string symbolCachePath,
|
||||
string symbolDirectoryPath,
|
||||
string windowsSymbolPath)
|
||||
{
|
||||
if (logging) {
|
||||
// Uses the standard console to do the logging instead of sending it to the hosting debugger console
|
||||
|
@ -209,7 +219,7 @@ namespace SOS
|
|||
}
|
||||
}
|
||||
// Build the symbol stores using the other parameters
|
||||
if (!GetServerSymbolStore(ref store, msdl, symweb, symbolServerPath, symbolCachePath, symbolDirectoryPath)) {
|
||||
if (!GetServerSymbolStore(ref store, msdl, symweb, symbolServerPath, timeoutInMinutes, symbolCachePath, symbolDirectoryPath)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1075,7 +1085,7 @@ namespace SOS
|
|||
}
|
||||
|
||||
// Add the symbol stores to the chain
|
||||
if (!GetServerSymbolStore(ref store, msdl, false, symbolServerPath, symbolCachePath, symbolDirectoryPath))
|
||||
if (!GetServerSymbolStore(ref store, msdl, false, symbolServerPath, timeoutInMinutes: 0, symbolCachePath, symbolDirectoryPath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -1085,7 +1095,7 @@ namespace SOS
|
|||
return true;
|
||||
}
|
||||
|
||||
private static bool GetServerSymbolStore(ref SymbolStore store, bool msdl, bool symweb, string symbolServerPath, string symbolCachePath, string symbolDirectoryPath)
|
||||
private static bool GetServerSymbolStore(ref SymbolStore store, bool msdl, bool symweb, string symbolServerPath, int timeoutInMinutes, string symbolCachePath, string symbolDirectoryPath)
|
||||
{
|
||||
bool internalServer = false;
|
||||
|
||||
|
@ -1106,43 +1116,47 @@ namespace SOS
|
|||
{
|
||||
// Use the internal symbol store for symweb
|
||||
internalServer = symbolServerPath.Contains("symweb");
|
||||
|
||||
// Make sure the server Uri ends with "/"
|
||||
symbolServerPath = symbolServerPath.TrimEnd('/') + '/';
|
||||
}
|
||||
|
||||
if (symbolServerPath != null)
|
||||
{
|
||||
// Validate symbol server path
|
||||
if (!Uri.TryCreate(symbolServerPath, UriKind.Absolute, out Uri uri) || uri.IsFile)
|
||||
if (!Uri.TryCreate(symbolServerPath.TrimEnd('/') + '/', UriKind.Absolute, out Uri uri))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsDuplicateSymbolStore<HttpSymbolStore>(store, (httpSymbolStore) => uri.Equals(httpSymbolStore.Uri)))
|
||||
// Add a cache symbol store if file or UNC path
|
||||
if (uri.IsFile || uri.IsUnc)
|
||||
{
|
||||
// Create symbol server store
|
||||
if (internalServer)
|
||||
AddCachePath(ref store, symbolServerPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!IsDuplicateSymbolStore<HttpSymbolStore>(store, (httpSymbolStore) => uri.Equals(httpSymbolStore.Uri)))
|
||||
{
|
||||
store = new SymwebHttpSymbolStore(s_tracer, store, uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
store = new HttpSymbolStore(s_tracer, store, uri);
|
||||
// Create http symbol server store
|
||||
HttpSymbolStore httpSymbolStore;
|
||||
if (internalServer)
|
||||
{
|
||||
httpSymbolStore = new SymwebHttpSymbolStore(s_tracer, store, uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
httpSymbolStore = new HttpSymbolStore(s_tracer, store, uri);
|
||||
}
|
||||
if (timeoutInMinutes != 0)
|
||||
{
|
||||
httpSymbolStore.Timeout = TimeSpan.FromMinutes(timeoutInMinutes);
|
||||
}
|
||||
store = httpSymbolStore;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (symbolCachePath != null)
|
||||
{
|
||||
symbolCachePath = Path.GetFullPath(symbolCachePath);
|
||||
|
||||
// Check only the first symbol store for duplication. The same cache directory can be
|
||||
// added more than once but just not more than once in a row.
|
||||
if (!(store is CacheSymbolStore cacheSymbolStore && IsPathEqual(symbolCachePath, cacheSymbolStore.CacheDirectory)))
|
||||
{
|
||||
store = new CacheSymbolStore(s_tracer, store, symbolCachePath);
|
||||
}
|
||||
AddCachePath(ref store, symbolCachePath);
|
||||
}
|
||||
|
||||
if (symbolDirectoryPath != null)
|
||||
|
@ -1158,6 +1172,18 @@ namespace SOS
|
|||
return true;
|
||||
}
|
||||
|
||||
private static void AddCachePath(ref SymbolStore store, string symbolCachePath)
|
||||
{
|
||||
symbolCachePath = Path.GetFullPath(symbolCachePath);
|
||||
|
||||
// Check only the first symbol store for duplication. The same cache directory can be
|
||||
// added more than once but just not more than once in a row.
|
||||
if (!(store is CacheSymbolStore cacheSymbolStore && IsPathEqual(symbolCachePath, cacheSymbolStore.CacheDirectory)))
|
||||
{
|
||||
store = new CacheSymbolStore(s_tracer, store, symbolCachePath);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsDuplicateSymbolStore<T>(SymbolStore symbolStore, Func<T, bool> match)
|
||||
where T : SymbolStore
|
||||
{
|
||||
|
|
|
@ -235,7 +235,7 @@ HRESULT GetRuntimeDirectory(std::string& runtimeDirectory)
|
|||
LPCSTR directory = g_ExtServices->GetCoreClrDirectory();
|
||||
if (directory == NULL)
|
||||
{
|
||||
ExtErr("Error: Runtime module (%s) not loaded yet\n", NETCORE_RUNTIME_DLL_NAME_A);
|
||||
ExtErr("Error: Runtime module (%s) not loaded yet\n", GetRuntimeDllName());
|
||||
return E_FAIL;
|
||||
}
|
||||
if (!GetAbsolutePath(directory, runtimeDirectory))
|
||||
|
@ -408,6 +408,11 @@ static HRESULT GetHostRuntime(std::string& coreClrPath, std::string& hostRuntime
|
|||
// Find highest 3.1.x version
|
||||
if (!FindDotNetVersion(3, 1, hostRuntimeDirectory))
|
||||
{
|
||||
// Don't use the desktop runtime to host
|
||||
if (g_isDesktopRuntime)
|
||||
{
|
||||
return E_FAIL;
|
||||
}
|
||||
// If an installed runtime can not be found, use the target coreclr version
|
||||
HRESULT hr = GetRuntimeDirectory(hostRuntimeDirectory);
|
||||
if (FAILED(hr))
|
||||
|
@ -766,13 +771,21 @@ static int ReadMemoryForSymbols(ULONG64 address, uint8_t *buffer, int cb)
|
|||
/**********************************************************************\
|
||||
* Setup and initialize the symbol server support.
|
||||
\**********************************************************************/
|
||||
HRESULT InitializeSymbolStore(BOOL logging, BOOL msdl, BOOL symweb, const char* symbolServer, const char* cacheDirectory, const char* searchDirectory, const char* windowsSymbolPath)
|
||||
HRESULT InitializeSymbolStore(
|
||||
BOOL logging,
|
||||
BOOL msdl,
|
||||
BOOL symweb,
|
||||
const char* symbolServer,
|
||||
int timeoutInMinutes,
|
||||
const char* cacheDirectory,
|
||||
const char* searchDirectory,
|
||||
const char* windowsSymbolPath)
|
||||
{
|
||||
HRESULT Status = S_OK;
|
||||
IfFailRet(InitializeHosting());
|
||||
_ASSERTE(g_SOSNetCoreCallbacks.InitializeSymbolStoreDelegate != nullptr);
|
||||
|
||||
if (!g_SOSNetCoreCallbacks.InitializeSymbolStoreDelegate(logging, msdl, symweb, GetTempDirectory(), symbolServer, cacheDirectory, searchDirectory, windowsSymbolPath))
|
||||
if (!g_SOSNetCoreCallbacks.InitializeSymbolStoreDelegate(logging, msdl, symweb, GetTempDirectory(), symbolServer, timeoutInMinutes, cacheDirectory, searchDirectory, windowsSymbolPath))
|
||||
{
|
||||
ExtErr("Error initializing symbol server support\n");
|
||||
return E_FAIL;
|
||||
|
@ -807,17 +820,21 @@ void InitializeSymbolStoreFromSymPath()
|
|||
{
|
||||
if (g_SOSNetCoreCallbacks.InitializeSymbolStoreDelegate != nullptr)
|
||||
{
|
||||
ArrayHolder<char> symbolPath = new char[MAX_LONGPATH];
|
||||
if (SUCCEEDED(g_ExtSymbols->GetSymbolPath(symbolPath, MAX_LONGPATH, nullptr)))
|
||||
ULONG cchLength = 0;
|
||||
if (SUCCEEDED(g_ExtSymbols->GetSymbolPath(nullptr, 0, &cchLength)))
|
||||
{
|
||||
if (strlen(symbolPath) > 0)
|
||||
{
|
||||
if (!g_SOSNetCoreCallbacks.InitializeSymbolStoreDelegate(false, false, false, GetTempDirectory(), nullptr, nullptr, nullptr, symbolPath))
|
||||
ArrayHolder<char> symbolPath = new char[cchLength];
|
||||
if (SUCCEEDED(g_ExtSymbols->GetSymbolPath(symbolPath, cchLength, nullptr)))
|
||||
{
|
||||
if (strlen(symbolPath) > 0)
|
||||
{
|
||||
ExtErr("Windows symbol path parsing FAILED\n");
|
||||
return;
|
||||
if (!g_SOSNetCoreCallbacks.InitializeSymbolStoreDelegate(false, false, false, GetTempDirectory(), nullptr, 0, nullptr, nullptr, symbolPath))
|
||||
{
|
||||
ExtErr("Windows symbol path parsing FAILED\n");
|
||||
return;
|
||||
}
|
||||
g_symbolStoreInitialized = true;
|
||||
}
|
||||
g_symbolStoreInitialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -870,33 +887,37 @@ static void LoadNativeSymbolsCallback(void* param, const char* moduleFilePath, U
|
|||
HRESULT LoadNativeSymbols(bool runtimeOnly)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
#ifdef FEATURE_PAL
|
||||
if (g_symbolStoreInitialized)
|
||||
{
|
||||
#ifdef FEATURE_PAL
|
||||
hr = g_ExtServices2 ? g_ExtServices2->LoadNativeSymbols(runtimeOnly, LoadNativeSymbolsCallback) : E_NOINTERFACE;
|
||||
}
|
||||
#else
|
||||
if (runtimeOnly)
|
||||
if (runtimeOnly)
|
||||
{
|
||||
ULONG index;
|
||||
ULONG64 moduleAddress;
|
||||
HRESULT hr = GetRuntimeModuleInfo(&index, &moduleAddress);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ULONG index;
|
||||
ULONG64 moduleAddress;
|
||||
HRESULT hr = GetRuntimeModuleInfo(&index, &moduleAddress);
|
||||
ArrayHolder<char> moduleFilePath = new char[MAX_LONGPATH + 1];
|
||||
hr = g_ExtSymbols->GetModuleNames(index, 0, moduleFilePath, MAX_LONGPATH, NULL, NULL, 0, NULL, NULL, 0, NULL);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ArrayHolder<char> moduleFilePath = new char[MAX_LONGPATH + 1];
|
||||
hr = g_ExtSymbols->GetModuleNames(index, 0, moduleFilePath, MAX_LONGPATH, NULL, NULL, 0, NULL, NULL, 0, NULL);
|
||||
DEBUG_MODULE_PARAMETERS moduleParams;
|
||||
hr = g_ExtSymbols->GetModuleParameters(1, &moduleAddress, 0, &moduleParams);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
DEBUG_MODULE_PARAMETERS moduleParams;
|
||||
hr = g_ExtSymbols->GetModuleParameters(1, &moduleAddress, 0, &moduleParams);
|
||||
if (SUCCEEDED(hr))
|
||||
hr = InitializeSymbolStore();
|
||||
if (SUCCEEDED(hr) && g_symbolStoreInitialized)
|
||||
{
|
||||
LoadNativeSymbolsCallback(nullptr, moduleFilePath, moduleAddress, moduleParams.Size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ typedef void (*WriteLineDelegate)(const char*);
|
|||
typedef int (*ReadMemoryDelegate)(ULONG64, uint8_t*, int);
|
||||
typedef void (*SymbolFileCallbackDelegate)(void*, const char* moduleFileName, const char* symbolFilePath);
|
||||
|
||||
typedef BOOL (*InitializeSymbolStoreDelegate)(BOOL, BOOL, BOOL, const char*, const char*, const char*, const char*, const char*);
|
||||
typedef BOOL (*InitializeSymbolStoreDelegate)(BOOL, BOOL, BOOL, const char*, const char*, int, const char*, const char*, const char*);
|
||||
typedef void (*DisplaySymbolStoreDelegate)(WriteLineDelegate);
|
||||
typedef void (*DisableSymbolStoreDelegate)();
|
||||
typedef void (*LoadNativeSymbolsDelegate)(SymbolFileCallbackDelegate, void*, const char*, ULONG64, int, ReadMemoryDelegate);
|
||||
|
@ -71,10 +71,21 @@ extern LPCSTR GetDacFilePath();
|
|||
extern LPCSTR GetDbiFilePath();
|
||||
extern BOOL IsHostingInitialized();
|
||||
extern HRESULT InitializeHosting();
|
||||
extern HRESULT InitializeSymbolStore(BOOL logging, BOOL msdl, BOOL symweb, const char* symbolServer, const char* cacheDirectory, const char* searchDirectory, const char* windowsSymbolPath);
|
||||
|
||||
extern HRESULT InitializeSymbolStore(
|
||||
BOOL logging,
|
||||
BOOL msdl,
|
||||
BOOL symweb,
|
||||
const char* symbolServer,
|
||||
int timeoutInMinutes,
|
||||
const char* cacheDirectory,
|
||||
const char* searchDirectory,
|
||||
const char* windowsSymbolPath);
|
||||
|
||||
#ifndef FEATURE_PAL
|
||||
extern void InitializeSymbolStoreFromSymPath();
|
||||
#endif
|
||||
|
||||
extern HRESULT LoadNativeSymbols(bool runtimeOnly = false);
|
||||
extern void DisplaySymbolStore();
|
||||
extern void DisableSymbolStore();
|
||||
|
|
|
@ -554,7 +554,7 @@ of value classes, while others do not.
|
|||
\\
|
||||
|
||||
COMMAND: gcroot.
|
||||
!GCRoot [-nostacks] <Object address>
|
||||
!GCRoot [-nostacks] [-all] <Object address>
|
||||
|
||||
!GCRoot looks for references (or roots) to an object. These can exist in four
|
||||
places:
|
||||
|
@ -565,14 +565,16 @@ places:
|
|||
4. As a member of an object found in 1, 2 or 3 above.
|
||||
|
||||
First, all stacks will be searched for roots, then handle tables, and finally
|
||||
the freachable queue of the finalizer. Some caution about the stack roots:
|
||||
the reachable queue of the finalizer. Some caution about the stack roots:
|
||||
!GCRoot doesn't attempt to determine if a stack root it encountered is valid
|
||||
or is old (discarded) data. You would have to use !CLRStack and !U to
|
||||
disassemble the frame that the local or argument value belongs to in order to
|
||||
determine if it is still in use.
|
||||
|
||||
Because people often want to restrict the search to gc handles and freachable
|
||||
Because people often want to restrict the search to gc handles and reachable
|
||||
objects, there is a -nostacks option.
|
||||
|
||||
The -all option forces all roots to be displayed instead of just the unique roots.
|
||||
\\
|
||||
|
||||
COMMAND: objsize.
|
||||
|
|
|
@ -456,7 +456,7 @@ all objects in the finalizable and "ready for finalization" queues.
|
|||
\\
|
||||
|
||||
COMMAND: gcroot.
|
||||
GCRoot [-nostacks] <Object address>
|
||||
GCRoot [-nostacks] [-all] <Object address>
|
||||
|
||||
GCRoot looks for references (or roots) to an object. These can exist in four
|
||||
places:
|
||||
|
@ -467,14 +467,16 @@ places:
|
|||
4. As a member of an object found in 1, 2 or 3 above.
|
||||
|
||||
First, all stacks will be searched for roots, then handle tables, and finally
|
||||
the freachable queue of the finalizer. Some caution about the stack roots:
|
||||
the reachable queue of the finalizer. Some caution about the stack roots:
|
||||
GCRoot doesn't attempt to determine if a stack root it encountered is valid
|
||||
or is old (discarded) data. You would have to use CLRStack and U to
|
||||
disassemble the frame that the local or argument value belongs to in order to
|
||||
determine if it is still in use.
|
||||
|
||||
Because people often want to restrict the search to gc handles and freachable
|
||||
Because people often want to restrict the search to gc handles and reachable
|
||||
objects, there is a -nostacks option.
|
||||
|
||||
The -all option forces all roots to be displayed instead of just the unique roots.
|
||||
\\
|
||||
|
||||
COMMAND: pe.
|
||||
|
@ -615,7 +617,7 @@ exceptions by switching to the thread in question, and running
|
|||
\\
|
||||
|
||||
COMMAND: clrstack.
|
||||
CLRStack [-a] [-l] [-p] [-n] [-f]
|
||||
CLRStack [-a] [-l] [-p] [-n] [-f] [-r] [-all]
|
||||
CLRStack [-a] [-l] [-p] [-i] [variable name] [frame]
|
||||
|
||||
CLRStack attempts to provide a true stack trace for managed code only. It is
|
||||
|
|
|
@ -9830,8 +9830,14 @@ DECLARE_API(DumpLog)
|
|||
|
||||
MINIDUMP_NOT_SUPPORTED();
|
||||
|
||||
// Not supported on desktop runtime
|
||||
if (g_isDesktopRuntime)
|
||||
{
|
||||
ExtErr("DumpLog not supported on desktop runtime\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
const char* fileName = "StressLog.txt";
|
||||
|
||||
CLRDATA_ADDRESS StressLogAddress = NULL;
|
||||
|
||||
StringHolder sFileName, sLogAddr;
|
||||
|
@ -15906,6 +15912,7 @@ DECLARE_API(SetSymbolServer)
|
|||
StringHolder symbolCache;
|
||||
StringHolder searchDirectory;
|
||||
StringHolder windowsSymbolPath;
|
||||
size_t timeoutInMinutes = 0;
|
||||
BOOL disable = FALSE;
|
||||
BOOL loadNative = FALSE;
|
||||
BOOL msdl = FALSE;
|
||||
|
@ -15916,6 +15923,7 @@ DECLARE_API(SetSymbolServer)
|
|||
{"-disable", &disable, COBOOL, FALSE},
|
||||
{"-cache", &symbolCache.data, COSTRING, TRUE},
|
||||
{"-directory", &searchDirectory.data, COSTRING, TRUE},
|
||||
{"-timeout", &timeoutInMinutes, COSIZE_T, TRUE},
|
||||
{"-ms", &msdl, COBOOL, FALSE},
|
||||
{"-log", &logging, COBOOL, FALSE},
|
||||
{"-loadsymbols", &loadNative, COBOOL, FALSE},
|
||||
|
@ -15954,7 +15962,7 @@ DECLARE_API(SetSymbolServer)
|
|||
|
||||
if (msdl || symweb || symbolServer.data != nullptr || symbolCache.data != nullptr || searchDirectory.data != nullptr || windowsSymbolPath.data != nullptr)
|
||||
{
|
||||
Status = InitializeSymbolStore(logging, msdl, symweb, symbolServer.data, symbolCache.data, searchDirectory.data, windowsSymbolPath.data);
|
||||
Status = InitializeSymbolStore(logging, msdl, symweb, symbolServer.data, (int)timeoutInMinutes, symbolCache.data, searchDirectory.data, windowsSymbolPath.data);
|
||||
if (FAILED(Status))
|
||||
{
|
||||
return Status;
|
||||
|
|
|
@ -12,7 +12,7 @@ def runScenario(assembly, debugger, target):
|
|||
# set breakpoint at Test.Main and stop there
|
||||
test.stop_in_main(debugger, assembly)
|
||||
|
||||
ci.HandleCommand("dso", res)
|
||||
ci.HandleCommand("pe", res)
|
||||
print(res.GetOutput())
|
||||
print(res.GetError())
|
||||
# Interpreter must have this command and able to run it
|
||||
|
|
|
@ -41,8 +41,7 @@ namespace Microsoft.Diagnostics.Tools.Dump
|
|||
{
|
||||
_serviceProvider = new ServiceProvider();
|
||||
_consoleProvider = new ConsoleProvider();
|
||||
Type type = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? typeof(SOSCommandForWindows) : typeof(SOSCommand);
|
||||
_commandProcessor = new CommandProcessor(_serviceProvider, _consoleProvider, new Assembly[] { typeof(Analyzer).Assembly }, new Type[] { type });
|
||||
_commandProcessor = new CommandProcessor(_serviceProvider, _consoleProvider, new Assembly[] { typeof(Analyzer).Assembly });
|
||||
}
|
||||
|
||||
public async Task<int> Analyze(FileInfo dump_path, string[] command)
|
||||
|
@ -71,7 +70,16 @@ namespace Microsoft.Diagnostics.Tools.Dump
|
|||
AddServices(target);
|
||||
|
||||
// Automatically enable symbol server support
|
||||
SymbolReader.InitializeSymbolStore(logging: false, msdl: true, symweb: false, tempDirectory: null, symbolServerPath: null, symbolCachePath: null, symbolDirectoryPath: null, windowsSymbolPath: null);
|
||||
SymbolReader.InitializeSymbolStore(
|
||||
logging: false,
|
||||
msdl: true,
|
||||
symweb: false,
|
||||
tempDirectory: null,
|
||||
symbolServerPath: null,
|
||||
timeoutInMinutes: 0,
|
||||
symbolCachePath: null,
|
||||
symbolDirectoryPath: null,
|
||||
windowsSymbolPath: null);
|
||||
|
||||
// Run the commands from the dotnet-dump command line
|
||||
if (command != null)
|
||||
|
|
|
@ -48,7 +48,21 @@ namespace Microsoft.Diagnostics.Tools.Dump
|
|||
[Command(Name = "histobjfind", AliasExpansion = "HistObjFind", Help = "Displays all the log entries that reference an object at the specified address.")]
|
||||
[Command(Name = "histroot", AliasExpansion = "HistRoot", Help = "Displays information related to both promotions and relocations of the specified root.")]
|
||||
[Command(Name = "setsymbolserver", AliasExpansion = "SetSymbolServer", Help = "Enables the symbol server support ")]
|
||||
internal class SOSCommand : CommandBase
|
||||
[Command(Name = "dumprcw", AliasExpansion = "DumpRCW", Platform = CommandPlatform.Windows, Help = "Displays information about a Runtime Callable Wrapper.")]
|
||||
[Command(Name = "dumpccw", AliasExpansion = "DumpCCW", Platform = CommandPlatform.Windows, Help = "Displays information about a COM Callable Wrapper.")]
|
||||
[Command(Name = "dumppermissionset",AliasExpansion = "DumpPermissionSet", Platform = CommandPlatform.Windows, Help = "Displays a PermissionSet object (debug build only).")]
|
||||
[Command(Name = "traverseheap", AliasExpansion = "TraverseHeap", Platform = CommandPlatform.Windows, Help = "Writes out a file in a format understood by the CLR Profiler.")]
|
||||
[Command(Name = "analyzeoom", AliasExpansion = "AnalyzeOOM", Platform = CommandPlatform.Windows, Help = "Displays the info of the last OOM occurred on an allocation request to the GC heap.")]
|
||||
[Command(Name = "verifyobj", AliasExpansion = "VerifyObj", Platform = CommandPlatform.Windows, Help = "Checks the object for signs of corruption.")]
|
||||
[Command(Name = "listnearobj", AliasExpansion = "ListNearObj", Platform = CommandPlatform.Windows, Help = "Displays the object preceding and succeeding the address specified.")]
|
||||
[Command(Name = "gcheapstat", AliasExpansion = "GCHeapStat", Platform = CommandPlatform.Windows, Help = "Display various GC heap stats.")]
|
||||
[Command(Name = "watsonbuckets", AliasExpansion = "WatsonBuckets", Platform = CommandPlatform.Windows, Help = "Displays the Watson buckets.")]
|
||||
[Command(Name = "threadpool", AliasExpansion = "ThreadPool", Platform = CommandPlatform.Windows, Help = "Lists basic information about the thread pool.")]
|
||||
[Command(Name = "comstate", AliasExpansion = "COMState", Platform = CommandPlatform.Windows, Help = "Lists the COM apartment model for each thread.")]
|
||||
[Command(Name = "gchandles", AliasExpansion = "GCHandles", Platform = CommandPlatform.Windows, Help = "Provides statistics about GCHandles in the process.")]
|
||||
[Command(Name = "objsize", AliasExpansion = "ObjSize", Platform = CommandPlatform.Windows, Help = "Lists the sizes of the all the objects found on managed threads.")]
|
||||
[Command(Name = "gchandleleaks", AliasExpansion = "GCHandleLeaks", Platform = CommandPlatform.Windows, Help = "Helps in tracking down GCHandle leaks")]
|
||||
public class SOSCommand : CommandBase
|
||||
{
|
||||
[Argument(Name = "arguments", Help = "Arguments to SOS command.")]
|
||||
public string[] Arguments { get; set; }
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.Diagnostics.Repl;
|
||||
using System.CommandLine;
|
||||
|
||||
namespace Microsoft.Diagnostics.Tools.Dump
|
||||
{
|
||||
[Command(Name = "dumprcw", AliasExpansion = "DumpRCW", Help = "Displays information about a Runtime Callable Wrapper.")]
|
||||
[Command(Name = "dumpccw", AliasExpansion = "DumpCCW", Help = "Displays information about a COM Callable Wrapper.")]
|
||||
[Command(Name = "dumppermissionset", AliasExpansion = "DumpPermissionSet", Help = "Displays a PermissionSet object (debug build only).")]
|
||||
[Command(Name = "traverseheap", AliasExpansion = "TraverseHeap", Help = "Writes out a file in a format understood by the CLR Profiler.")]
|
||||
[Command(Name = "analyzeoom", AliasExpansion = "AnalyzeOOM", Help = "Displays the info of the last OOM occurred on an allocation request to the GC heap.")]
|
||||
[Command(Name = "verifyobj", AliasExpansion = "VerifyObj", Help = "Checks the object for signs of corruption.")]
|
||||
[Command(Name = "listnearobj", AliasExpansion = "ListNearObj", Help = "Displays the object preceding and succeeding the address specified.")]
|
||||
[Command(Name = "gcheapstat", AliasExpansion = "GCHeapStat", Help = "Display various GC heap stats.")]
|
||||
[Command(Name = "watsonbuckets", AliasExpansion = "WatsonBuckets", Help = "Displays the Watson buckets.")]
|
||||
[Command(Name = "threadpool", AliasExpansion = "ThreadPool", Help = "Lists basic information about the thread pool.")]
|
||||
[Command(Name = "comstate", AliasExpansion = "COMState", Help = "Lists the COM apartment model for each thread.")]
|
||||
[Command(Name = "gchandles", AliasExpansion = "GCHandles", Help = "Provides statistics about GCHandles in the process.")]
|
||||
[Command(Name = "objsize", AliasExpansion = "ObjSize", Help = "Lists the sizes of the all the objects found on managed threads.")]
|
||||
[Command(Name = "gchandleleaks", AliasExpansion = "GCHandleLeaks", Help = "Helps in tracking down GCHandle leaks")]
|
||||
internal class SOSCommandForWindows : SOSCommand
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.Diagnostics.DebugServices;
|
||||
using Microsoft.Diagnostics.Repl;
|
||||
using System.CommandLine;
|
||||
|
||||
namespace Microsoft.Diagnostics.Tools.Dump
|
||||
{
|
||||
[Command(Name = "setclrpath", Platform = CommandPlatform.Linux | CommandPlatform.OSX, Help = "Set the path to load coreclr DAC/DBI files.")]
|
||||
public class SetClrPath: CommandBase
|
||||
{
|
||||
public AnalyzeContext AnalyzeContext { get; set; }
|
||||
|
||||
[Argument(Name = "clrpath", Help = "Runtime directory path.")]
|
||||
public string Argument { get; set; }
|
||||
|
||||
public override void Invoke()
|
||||
{
|
||||
if (Argument == null)
|
||||
{
|
||||
WriteLine("Load path for DAC/DBI: '{0}'", AnalyzeContext.RuntimeModuleDirectory ?? "<none>");
|
||||
}
|
||||
else
|
||||
{
|
||||
AnalyzeContext.RuntimeModuleDirectory = Argument;
|
||||
WriteLine("Set load path for DAC/DBI to '{0}'", AnalyzeContext.RuntimeModuleDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -613,10 +613,10 @@
|
|||
#endif
|
||||
|
||||
#if !defined(MAX_LONGPATH)
|
||||
#define MAX_LONGPATH 260 /* max. length of full pathname */
|
||||
#define MAX_LONGPATH 1024 /* max. length of full pathname */
|
||||
#endif
|
||||
#if !defined(MAX_PATH_FNAME)
|
||||
#define MAX_PATH_FNAME MAX_PATH /* max. length of full pathname */
|
||||
#define MAX_PATH_FNAME MAX_PATH /* max. length of full pathname */
|
||||
#endif
|
||||
|
||||
#define __clr_reserved __reserved
|
||||
|
|
Загрузка…
Ссылка в новой задаче