internal State(ClrRuntime runtime, IDebugControl debugControl) { Runtime = runtime; DebugControl = debugControl; Todo = new Queue <MethodInfo>(); HandledMetadataTokens = new HashSet <uint>(); }
public string Execute(IDebugClient Client, IDebugControl Control, string Command) { try { Clear(); Client.SetOutputMask(SupportedMasks); Client.SetOutputCallbacks(this); //Application.DoEvents(); //DEBUG_STATUS status; //Control.GetExecutionStatus(out status); //DebugApi.WriteLine("Execution status {0}", status.ToString()); Control.Execute(DEBUG_OUTCTL.THIS_CLIENT | DEBUG_OUTCTL.NOT_LOGGED, Command, DEBUG_EXECUTE.NOT_LOGGED | DEBUG_EXECUTE.NO_REPEAT); //int res = 0; //do //{ // res = Control.WaitForEvent(DEBUG_WAIT.DEFAULT, 10000); // if(res == 1) WinApi.SetStatusBarMessage("10 seconds elapsed"); // //DebugApi.DebugWriteLine("10 seconds elapsed"); //} while (res == 1 /* ResultCom.S_FALSE */); } finally { Client.SetOutputCallbacks(null); } return(Text); }
public Debugger(IDebugClient5 client, IDebugControl control) { _client = client; _control = control; client.SetOutputCallbacks(this); }
public DataTarget LoadFullDumpWithDbgEng(GCMode gc = GCMode.Workstation) { Guid guid = new Guid("27fe5639-8407-4f47-8364-ee118fb08ac8"); int hr = DebugCreate(guid, out IntPtr pDebugClient); if (hr != 0) { throw new Exception($"Failed to create DebugClient, hr={hr:x}."); } IDebugClient client = (IDebugClient)Marshal.GetTypedObjectForIUnknown(pDebugClient, typeof(IDebugClient)); IDebugControl control = (IDebugControl)client; string dumpPath = BuildDumpName(gc, true); hr = client.OpenDumpFile(dumpPath); if (hr != 0) { throw new Exception($"Failed to OpenDumpFile, hr={hr:x}."); } hr = control.WaitForEvent(DEBUG_WAIT.DEFAULT, 10000); if (hr != 0) { throw new Exception($"Failed to attach to dump file, hr={hr:x}."); } Marshal.Release(pDebugClient); return(DataTarget.CreateFromDbgEng(pDebugClient)); }
/// <summary> /// Initializes a new instance of the <see cref="ExecuteWrapper" /> class. /// </summary> /// <param name="client">The client.</param> public ExecuteWrapper(IDebugClient client, IDebugControl control) { _client = client; _control = control; client.GetOutputCallbacks(out _old); // todo: error check client.SetOutputCallbacks(this); }
internal static IDebugControl GetDebugControl(this IntPtr debugClient) { if (_debugControl == null) { _debugControl = (IDebugControl)debugClient.GetIUnknown(); } return(_debugControl); }
public dbgeng() { var guid = new Guid("27fe5639-8407-4f47-8364-ee118fb08ac8"); HResult hr = DebugCreate(guid, out pDebugClient); if (!hr.IsOK) { throw new Exception(string.Format("Failed to create DebugClient, hr={0:x}.", hr)); } client = (IDebugClient)Marshal.GetTypedObjectForIUnknown(pDebugClient, typeof(IDebugClient)); control = (IDebugControl)Marshal.GetTypedObjectForIUnknown(pDebugClient, typeof(IDebugControl)); }
public static bool CheckActiveTarget(IDebugControl dbgControl) { dbgControl.GetDebuggeeType(out DEBUG_CLASS debugClass, out DEBUG_CLASS_QUALIFIER qualifier); if (debugClass != DEBUG_CLASS.USER_WINDOWS || (debugClass == DEBUG_CLASS.USER_WINDOWS && qualifier == DEBUG_CLASS_QUALIFIER.USER_WINDOWS_SMALL_DUMP)) { dbgControl.Output(DEBUG_OUTPUT.NORMAL, $"The current target is not a user-mode target.\n"); dbgControl.Output(DEBUG_OUTPUT.NORMAL, $"DebuggeeType: {debugClass}, {qualifier}.\n"); return(false); } return(true); }
public void Execute(CommandExecutionContext context) { _context = context; ClrMethod method = context.Runtime.GetMethodByAddress(InstructionPointer); if (method == null) { context.WriteError("There is no managed method at the address {0:x16}.", InstructionPointer); return; } _sourceFileCache = new Dictionary<string, string[]>(); using (var target = context.CreateTemporaryDbgEngTarget()) { _control = (IDebugControl)target.DebuggerInterface; DisassembleMethod(method); } }
public void Execute(CommandExecutionContext context) { _context = context; ClrMethod method = context.Runtime.GetMethodByAddress(InstructionPointer); if (method == null) { context.WriteError("There is no managed method at the address {0:x16}.", InstructionPointer); return; } _sourceFileCache = new Dictionary <string, string[]>(); using (var target = context.CreateTemporaryDbgEngTarget()) { _control = (IDebugControl)target.DebuggerInterface; DisassembleMethod(method); } }
public Debugger LaunchProcess(string commandLine, string workingDirectory) { IDebugClient5 client = CreateIDebugClient(); IDebugControl control = (IDebugControl)client; if (string.IsNullOrEmpty(workingDirectory)) { workingDirectory = Environment.CurrentDirectory; } string env = GetEnvironment(); DEBUG_CREATE_PROCESS_OPTIONS options = new DEBUG_CREATE_PROCESS_OPTIONS(); options.CreateFlags = (DEBUG_CREATE_PROCESS)1; int hr = client.CreateProcessAndAttach2(0, commandLine, ref options, (uint)Marshal.SizeOf(typeof(DEBUG_CREATE_PROCESS_OPTIONS)), workingDirectory, env, 0, DEBUG_ATTACH.DEFAULT); if (hr < 0) { throw new Exception(Debugger.GetExceptionString("IDebugClient::CreateProcessAndAttach2", hr)); } Debugger debugger = new Debugger(client, control); hr = client.SetEventCallbacks(debugger); if (hr < 0) { throw new Exception(Debugger.GetExceptionString("IDebugClient::SetEventCallbacks", hr)); } hr = client.SetOutputCallbacks(debugger); if (hr < 0) { throw new Exception(Debugger.GetExceptionString("IDebugClient::SetOutputCallbacks", hr)); } return(debugger); }
public DbgEngStream(IDebugClient client) { m_client = client; m_control = (IDebugControl)client; }
internal DebuggerOutput(IDebugClient client) { this.client = client; this.control = (IDebugControl)client; }
/// <summary> /// See https://github.com/goldshtn/msos/commit/705d3758d15835d2520b31fcf3028353bdbca73b#commitcomment-12499813 /// and https://github.com/Microsoft/dotnetsamples/blob/master/Microsoft.Diagnostics.Runtime/CLRMD/ClrMemDiag/Debugger/IDebugControl.cs#L126-L156 /// </summary> private void PrintAssemblyCode(ClrMethod method, IList<ILToNativeMap> ilMaps, ClrRuntime runtime, IDebugControl debugControl) { // This is the first instruction of the JIT'ed (or NGEN'ed) machine code. ulong startAddress = ilMaps.Select(entry => entry.StartAddress).Min(); // Unfortunately there's not a great way to get the size of the code, or the end address. // You are supposed to do code flow analysis like "uf" in windbg to find the size, but // in practice you can use the IL to native mapping: ulong endAddress = ilMaps.Select(entry => entry.EndAddress).Max(); var bufferSize = 500; // per-line var lineOfAssembly = new StringBuilder(bufferSize); ulong startOffset = startAddress, endOffset; uint disassemblySize; do { var flags = DEBUG_DISASM.EFFECTIVE_ADDRESS; var result = debugControl.Disassemble(startOffset, flags, lineOfAssembly, bufferSize, out disassemblySize, out endOffset); startOffset = endOffset; logger?.Write(lineOfAssembly.ToString()); if (lineOfAssembly.ToString().Contains(" call ") == false) continue; var methodCallInfo = GetCalledMethodFromAssemblyOutput(runtime, lineOfAssembly.ToString()); if (string.IsNullOrWhiteSpace(methodCallInfo) == false) logger?.WriteLine(LogKind.Info, $" {methodCallInfo}"); } while (disassemblySize > 0 && endOffset <= endAddress); logger?.WriteLine(); }
/// <summary> /// See https://github.com/goldshtn/msos/commit/705d3758d15835d2520b31fcf3028353bdbca73b#commitcomment-12499813 /// and https://github.com/Microsoft/dotnetsamples/blob/master/Microsoft.Diagnostics.Runtime/CLRMD/ClrMemDiag/Debugger/IDebugControl.cs#L126-L156 /// </summary> private void PrintAssemblyCode(ClrMethod method, IList <ILToNativeMap> ilMaps, ClrRuntime runtime, IDebugControl debugControl) { // This is the first instruction of the JIT'ed (or NGEN'ed) machine code. ulong startAddress = ilMaps.Select(entry => entry.StartAddress).Min(); // Unfortunately there's not a great way to get the size of the code, or the end address. // You are supposed to do code flow analysis like "uf" in windbg to find the size, but // in practice you can use the IL to native mapping: ulong endAddress = ilMaps.Select(entry => entry.EndAddress).Max(); var bufferSize = 500; // per-line var lineOfAssembly = new StringBuilder(bufferSize); ulong startOffset = startAddress, endOffset; uint disassemblySize; do { var flags = DEBUG_DISASM.EFFECTIVE_ADDRESS; var result = debugControl.Disassemble(startOffset, flags, lineOfAssembly, bufferSize, out disassemblySize, out endOffset); startOffset = endOffset; logger?.Write(lineOfAssembly.ToString()); if (lineOfAssembly.ToString().Contains(" call ") == false) { continue; } var methodCallInfo = GetCalledMethodFromAssemblyOutput(runtime, lineOfAssembly.ToString()); if (string.IsNullOrWhiteSpace(methodCallInfo) == false) { logger?.WriteLine(BenchmarkLogKind.Info, $" {methodCallInfo}"); } } while (disassemblySize > 0 && endOffset <= endAddress); logger?.WriteLine(); }
public DebugEngineStream(IDebugClient debugClient) { this.debugClient = debugClient; this.debugControl = (IDebugControl)debugClient; }
public DebugEngineStream(IDebugClient client) { _client = client; _control = (IDebugControl)client; }
public CommandExecutor(IDebugControl control) { _control = control; }
private static int ConnectDebuggerLiveHelper(DebugUtilities debugUtilities, uint processID, bool passive, out SimpleDebugger debuggerInformation) { int hr; IDebugControl debugControl = null; IDebugSystemObjects debugSystemObjects = null; SimpleOutputHandler debuggerOutputCallbacks = null; SimpleEventHandler debuggerEventCallbacks = null; debuggerInformation = null; hr = SimpleOutputHandler.Install(debugUtilities, out debuggerOutputCallbacks); if (hr != S_OK) { goto Error; } hr = SimpleEventHandler.Install(debugUtilities, out debuggerEventCallbacks); if (hr != S_OK) { goto ErrorWithDetach; } DEBUG_ATTACH attachFlags = passive ? DEBUG_ATTACH.NONINVASIVE | DEBUG_ATTACH.NONINVASIVE_NO_SUSPEND : DEBUG_ATTACH.INVASIVE_RESUME_PROCESS; hr = debugUtilities.DebugClient.AttachProcess(0, processID, attachFlags); if (hr != S_OK) { goto ErrorWithDetach; } while (debuggerEventCallbacks.SessionIsActive == false) { hr = debugControl.WaitForEvent(DEBUG_WAIT.DEFAULT, 50); if (FAILED(hr)) { goto ErrorWithDetach; } } bool foundMatchingProcess = false; uint numProcesses; debugSystemObjects.GetNumberProcesses(out numProcesses); uint[] systemProcessIDs = new uint[numProcesses]; uint[] engineProcessIDs = new uint[numProcesses]; hr = debugSystemObjects.GetProcessIdsByIndex(0, numProcesses, engineProcessIDs, systemProcessIDs); for (uint i = 0; i < numProcesses; ++i) { if (systemProcessIDs[i] == processID) { foundMatchingProcess = true; hr = debugSystemObjects.SetCurrentProcessId(engineProcessIDs[i]); if (FAILED(hr)) { debuggerOutputCallbacks.AddNoteLine(String.Format(CultureInfo.InvariantCulture, "ERROR! Failed to set the active process! hr={0:x8}", hr)); goto ErrorWithDetach; } break; } } if (foundMatchingProcess == false) { hr = E_FAIL; debuggerOutputCallbacks.AddNoteLine(String.Format(CultureInfo.InvariantCulture, "ERROR! The debugger engine could not find the requested process ID ({0})!", processID)); goto ErrorWithDetach; } debuggerInformation = new SimpleDebugger(debugUtilities, processID, passive, debuggerOutputCallbacks, debuggerEventCallbacks); goto Exit; ErrorWithDetach: debugUtilities.DebugClient.DetachProcesses(); debugUtilities.DebugClient.EndSession(DEBUG_END.ACTIVE_DETACH); Error: if (debuggerEventCallbacks != null) { debuggerEventCallbacks.Dispose(); } if (debuggerOutputCallbacks != null) { debuggerOutputCallbacks.Dispose(); } Exit: return(hr); }
internal DbgEngController(string dbgengPath, string dumpPath, string sosPath) { Trace.TraceInformation($"DbgEngController: {dbgengPath} {dumpPath} {sosPath}"); _converter = new CharToLineConverter((text) => { Trace.TraceInformation(text); }); IntPtr dbgengLibrary = DataTarget.PlatformFunctions.LoadLibrary(dbgengPath); var debugCreate = SOSHost.GetDelegateFunction <DebugCreateDelegate>(dbgengLibrary, "DebugCreate"); if (debugCreate == null) { throw new DiagnosticsException($"DebugCreate export not found"); } Guid iid = _iidClient; HResult hr = debugCreate(ref iid, out object client); if (hr != HResult.S_OK) { throw new DiagnosticsException($"DebugCreate FAILED {hr:X8}"); } Client = (IDebugClient)client; Control = (IDebugControl)client; Symbols = (IDebugSymbols2)client; hr = Client.SetOutputCallbacks(this); if (hr != HResult.S_OK) { throw new DiagnosticsException($"SetOutputCallbacks FAILED {hr:X8}"); } // Automatically enable/adjust symbol server support. Override the default cache path so // the cache isn't created in the debugger binaries .nuget package cache directory. string cachePath = Path.Combine(Environment.GetEnvironmentVariable("PROGRAMDATA"), "dbg", "sym"); string sympath = $"{Path.GetDirectoryName(dumpPath)};cache*{cachePath};SRV*https://msdl.microsoft.com/download/symbols"; hr = Symbols.SetSymbolPath(sympath); if (hr != HResult.S_OK) { Trace.TraceError($"SetSymbolPath({sympath}) FAILED {hr:X8}"); } // Load dump file hr = Client.OpenDumpFile(dumpPath); if (hr != HResult.S_OK) { throw new DiagnosticsException($"OpenDumpFile({dumpPath} FAILED {hr:X8}"); } ProcessEvents(); // Load the sos extensions hr = Control.Execute(DEBUG_OUTCTL.ALL_CLIENTS, $".load {sosPath}", DEBUG_EXECUTE.DEFAULT); if (hr != HResult.S_OK) { throw new DiagnosticsException($"Loading {sosPath} FAILED {hr:X8}"); } // Initialize the extension host hr = HostServices.Initialize(sosPath); if (hr != HResult.S_OK) { throw new DiagnosticsException($"HostServices.Initialize({sosPath}) FAILED {hr:X8}"); } var symbolService = Host.Services.GetService <ISymbolService>(); Trace.TraceInformation($"SymbolService: {symbolService}"); }