//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public DebuggeeBreakpointBound(DebugBreakpointManager breakpointManager, DebuggeeBreakpointPending pendingBreakpoint, DebuggeeCodeContext codeContext) { if (breakpointManager == null) { throw new ArgumentNullException("breakpointManager"); } if (pendingBreakpoint == null) { throw new ArgumentNullException("pendingBreakpoint"); } if (codeContext == null) { throw new ArgumentNullException("codeContext"); } m_breakpointManager = breakpointManager; m_pendingBreakpoint = pendingBreakpoint; m_codeContext = codeContext; m_breakpointResolution = new DebuggeeBreakpointResolution(m_codeContext, "<bound breakpoint>"); m_breakpointEnabled = true; m_breakpointDeleted = false; m_hitCount = 0; }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int Subtract(ulong count, out IDebugMemoryContext2 offsetAddressContext) { // // Subtracts a specified value to the current context's address to create a new context. // LoggingUtils.PrintFunction(); try { DebuggeeAddress offsetAddress = m_address.Subtract(count); offsetAddressContext = new DebuggeeCodeContext(m_engine, DocumentContext, offsetAddress); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); offsetAddressContext = null; return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public DebuggeeBreakpointError(DebugBreakpointManager breakpointManager, DebuggeeBreakpointPending pendingBreakpoint, DebuggeeCodeContext codeContext, string error) { if (breakpointManager == null) { throw new ArgumentNullException("breakpointManager"); } if (pendingBreakpoint == null) { throw new ArgumentNullException("pendingBreakpoint"); } if (codeContext == null) { throw new ArgumentNullException("codeContext"); } m_breakpointManager = breakpointManager; m_pendingBreakpoint = pendingBreakpoint; m_codeContext = codeContext; m_breakpointResolution = new DebuggeeBreakpointResolution(m_codeContext, error); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int SetCodeContext(DebuggeeCodeContext codeContext) { LoggingUtils.PrintFunction(); m_codeContext = codeContext; return(Constants.S_OK); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public CLangDebuggeeDisassemblyStream(CLangDebugger debugger, enum_DISASSEMBLY_STREAM_SCOPE streamScope, IDebugCodeContext2 codeContext) { m_debugger = debugger; m_streamScope = streamScope; m_codeContext = codeContext as DebuggeeCodeContext; }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public DebuggeeBreakpointError(DebugBreakpointManager breakpointManager, DebuggeeBreakpointPending pendingBreakpoint, DebuggeeCodeContext codeContext, string error) { m_breakpointManager = breakpointManager ?? throw new ArgumentNullException(nameof(breakpointManager)); m_pendingBreakpoint = pendingBreakpoint ?? throw new ArgumentNullException(nameof(pendingBreakpoint)); m_codeContext = codeContext ?? throw new ArgumentNullException(nameof(codeContext)); m_breakpointResolution = new DebuggeeBreakpointResolution(m_codeContext, error); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public DebuggeeBreakpointResolution(DebuggeeCodeContext codeContext, string message) { if (codeContext == null) { throw new ArgumentNullException("codeContext"); } m_codeContext = codeContext; m_resolutionMessage = message; }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public DebuggeeDocumentContext(DebugEngine engine, string fileName, TEXT_POSITION beginPosition, TEXT_POSITION endPosition) { m_engine = engine; m_fileName = PathUtils.ConvertPathCygwinToWindows(fileName); m_beginPosition = beginPosition; m_endPosition = endPosition; m_codeContext = null; }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public DebuggeeBreakpointBound(DebugBreakpointManager breakpointManager, DebuggeeBreakpointPending pendingBreakpoint, DebuggeeCodeContext codeContext) { m_breakpointManager = breakpointManager ?? throw new ArgumentNullException(nameof(breakpointManager)); m_pendingBreakpoint = pendingBreakpoint ?? throw new ArgumentNullException(nameof(pendingBreakpoint)); m_codeContext = codeContext ?? throw new ArgumentNullException(nameof(codeContext)); m_breakpointResolution = new DebuggeeBreakpointResolution(m_codeContext, "<bound breakpoint>"); m_breakpointEnabled = true; m_breakpointDeleted = false; m_hitCount = 0; }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int EnumCodeContexts(IDebugDocumentPosition2 pDocPos, out IEnumDebugCodeContexts2 ppEnum) { // // Enumerates the code contexts for a given position in a source file. // LoggingUtils.PrintFunction(); try { string fileName; TEXT_POSITION [] startPos = new TEXT_POSITION [1]; TEXT_POSITION [] endPos = new TEXT_POSITION [1]; LoggingUtils.RequireOk(pDocPos.GetFileName(out fileName)); LoggingUtils.RequireOk(pDocPos.GetRange(startPos, endPos)); string location = string.Format("\"{0}:{1}\"", fileName, startPos [0].dwLine + 1); DebuggeeCodeContext codeContext = m_debugger.GetCodeContextForLocation(location); if (codeContext == null) { throw new InvalidOperationException("Failed evaluating code-context for location."); } DebuggeeCodeContext [] codeContexts = new DebuggeeCodeContext [] { codeContext }; ppEnum = new DebuggeeCodeContext.Enumerator(codeContexts); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); ppEnum = null; return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public DebuggeeStackFrame(DebugEngine engine, DebuggeeThread thread, string frameName) { m_debugEngine = engine; m_thread = thread; m_codeContext = null; m_documentContext = null; m_property = new DebuggeeProperty(engine, this, frameName, string.Empty); m_stackRegisters = new ConcurrentDictionary <string, DebuggeeProperty> (); m_stackArguments = new ConcurrentDictionary <string, DebuggeeProperty> (); m_stackLocals = new ConcurrentDictionary <string, DebuggeeProperty> (); m_customExpressions = new ConcurrentDictionary <string, DebuggeeProperty> (); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #region IDebugPendingBreakpoint2 Members //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public virtual int Bind() { // // Binds this pending breakpoint to one or more code locations. // LoggingUtils.PrintFunction(); DebuggeeDocumentContext documentContext = null; DebuggeeCodeContext codeContext = null; string bindLocation = string.Empty; try { ClearErrorBreakpoints(); if (m_breakpointDeleted) { return(Constants.E_BP_DELETED); } LoggingUtils.RequireOk(EvaluateBreakpointLocation(out documentContext, out codeContext, out bindLocation)); LoggingUtils.RequireOk(CreateBoundBreakpoint(bindLocation, documentContext, codeContext)); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public override int EvaluateBreakpointLocation(out DebuggeeDocumentContext documentContext, out DebuggeeCodeContext codeContext, out string location) { LoggingUtils.PrintFunction(); try { LoggingUtils.RequireOk(base.EvaluateBreakpointLocation(out documentContext, out codeContext, out location)); /*switch (m_breakpointRequestInfo.bpLocation.bpLocationType) * { * case (uint) enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE: * { * codeContext = CLangDebuggeeCodeContext.GetCodeContextForLocation (m_debugger, location); * * if (codeContext == null) * { * throw new InvalidOperationException (); * } * * documentContext = codeContext.DocumentContext; * * if (documentContext == null) * { * throw new InvalidOperationException (); * } * * break; * } * * default: * { * break; * } * }*/ return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); documentContext = null; codeContext = null; location = string.Empty; return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public virtual int CreateErrorBreakpoint(string errorReason, DebuggeeDocumentContext documentContext, DebuggeeCodeContext codeContext) { // // Create and broadcast a generic (non language-specific) errored breakpoint. // LoggingUtils.PrintFunction(); try { DebuggeeBreakpointError errorBreakpoint = new DebuggeeBreakpointError(m_breakpointManager, this, codeContext, errorReason); lock (m_errorBreakpoints) { m_errorBreakpoints.Add(errorBreakpoint); } uint numDebugPrograms = 1; IEnumDebugPrograms2 debugPrograms; IDebugProgram2 [] debugProgramsArray = new IDebugProgram2 [numDebugPrograms]; LoggingUtils.RequireOk(m_breakpointManager.Engine.EnumPrograms(out debugPrograms)); LoggingUtils.RequireOk(debugPrograms.Next(numDebugPrograms, debugProgramsArray, ref numDebugPrograms)); m_breakpointManager.Engine.Broadcast(new DebugEngineEvent.BreakpointError(errorBreakpoint), debugProgramsArray [0], null); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public virtual int CreateBoundBreakpoint(string location, DebuggeeDocumentContext documentContext, DebuggeeCodeContext codeContext) { LoggingUtils.PrintFunction(); throw new NotImplementedException(); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public virtual int EvaluateBreakpointLocation(out DebuggeeDocumentContext documentContext, out DebuggeeCodeContext codeContext, out string location) { LoggingUtils.PrintFunction(); documentContext = null; codeContext = null; location = string.Empty; try { switch (m_breakpointRequestInfo.bpLocation.bpLocationType) { case (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE: { // // Specifies the location type of the breakpoint as a line of source code. // string fileName; IDebugDocumentPosition2 documentPostion = (IDebugDocumentPosition2)Marshal.GetObjectForIUnknown(m_breakpointRequestInfo.bpLocation.unionmember2); LoggingUtils.RequireOk(documentPostion.GetFileName(out fileName)); bool fileInCurrentProject = true; // TODO if (File.Exists(fileName) && fileInCurrentProject) { TEXT_POSITION [] startPos = new TEXT_POSITION [1]; TEXT_POSITION [] endPos = new TEXT_POSITION [1]; LoggingUtils.RequireOk(documentPostion.GetRange(startPos, endPos)); documentContext = new DebuggeeDocumentContext(m_breakpointManager.Engine, fileName, startPos [0], endPos [0]); location = string.Format("\"{0}:{1}\"", fileName, startPos [0].dwLine + 1); } else { throw new NotImplementedException(); } break; } case (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET: { // // Specifies the location type of the breakpoint as a code function offset. // string function = string.Empty; IDebugFunctionPosition2 functionPosition = (IDebugFunctionPosition2)Marshal.GetObjectForIUnknown(m_breakpointRequestInfo.bpLocation.unionmember2); TEXT_POSITION [] textPos = new TEXT_POSITION [1]; LoggingUtils.RequireOk(functionPosition.GetFunctionName(out function)); LoggingUtils.RequireOk(functionPosition.GetOffset(textPos)); if (!string.IsNullOrEmpty(function)) { location = function; } break; } case (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_CONTEXT: { // // Specifies the location type of the breakpoint as a code context. // codeContext = ((IDebugCodeContext2)Marshal.GetObjectForIUnknown(m_breakpointRequestInfo.bpLocation.unionmember1)) as DebuggeeCodeContext; if (codeContext != null) { location = codeContext.Address.ToString(); } break; } case (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_STRING: { // // Specifies the location type of the breakpoint as a code string. // throw new NotImplementedException(); } case (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_ADDRESS: { // // Specifies the location type of the breakpoint as a code address. // string address = Marshal.PtrToStringBSTR(m_breakpointRequestInfo.bpLocation.unionmember4); if (!string.IsNullOrEmpty(address)) { location = address; } break; } case (uint)enum_BP_LOCATION_TYPE.BPLT_DATA_STRING: { // // Specifies the location type of the breakpoint as a data string. // string dataExpression = Marshal.PtrToStringBSTR(m_breakpointRequestInfo.bpLocation.unionmember3); if (!string.IsNullOrEmpty(dataExpression)) { location = dataExpression; } break; } default: { break; } } return(Constants.S_OK); } catch (NotImplementedException e) { LoggingUtils.HandleException(e); return(Constants.E_NOTIMPL); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public DebuggeeBreakpointResolution(DebuggeeCodeContext codeContext, string message) { m_codeContext = codeContext ?? throw new ArgumentNullException(nameof(codeContext)); m_resolutionMessage = message ?? throw new ArgumentNullException(nameof(message)); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int Seek(enum_SEEK_START dwSeekStart, IDebugCodeContext2 pCodeContext, ulong uCodeLocationId, long iInstructions) { // // Moves the read pointer in the disassembly stream a given number of instructions relative to a specified position. // LoggingUtils.PrintFunction(); try { switch (dwSeekStart) { case enum_SEEK_START.SEEK_START_BEGIN: { // // Starts seeking at the beginning of the current document. // throw new NotImplementedException(); } case enum_SEEK_START.SEEK_START_END: { // // Starts seeking at the end of the current document. // throw new NotImplementedException(); } case enum_SEEK_START.SEEK_START_CURRENT: { // // Starts seeking at the current position of the current document. // ulong offsetAddress = m_codeContext.Address.MemoryAddress; if (iInstructions > 0) { offsetAddress += (ulong)(iInstructions * 4); } else if (iInstructions < 0) { offsetAddress += (ulong)(Math.Abs(iInstructions) * 4); } m_codeContext.Address = new DebuggeeAddress(offsetAddress); break; } case enum_SEEK_START.SEEK_START_CODECONTEXT: { // // Starts seeking at the given code context of the current document. // DebuggeeCodeContext codeContext = (pCodeContext as DebuggeeCodeContext); ulong offsetAddress = codeContext.Address.MemoryAddress; if (iInstructions > 0) { offsetAddress += (ulong)(iInstructions * 4); } else if (iInstructions < 0) { offsetAddress += (ulong)(Math.Abs(iInstructions) * 4); } m_codeContext.Address = new DebuggeeAddress(offsetAddress); break; } case enum_SEEK_START.SEEK_START_CODELOCID: { // // Starts seeking at the given code location identifier. // ulong offsetAddress = uCodeLocationId; if (iInstructions > 0) { offsetAddress += (ulong)(iInstructions * 4); } else if (iInstructions < 0) { offsetAddress += (ulong)(Math.Abs(iInstructions) * 4); } m_codeContext.Address = new DebuggeeAddress(offsetAddress); break; } } return(Constants.S_OK); } catch (NotImplementedException e) { LoggingUtils.HandleException(e); return(Constants.E_NOTIMPL); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public CLangDebuggeeBreakpointError(CLangDebugger debugger, DebugBreakpointManager breakpointManager, DebuggeeBreakpointPending pendingBreakpoint, DebuggeeCodeContext codeContext, MiBreakpoint gdbBreakpoint, string error) : base(breakpointManager, pendingBreakpoint, codeContext, error) { m_debugger = debugger; GdbBreakpoint = gdbBreakpoint; }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int Compare(enum_CONTEXT_COMPARE contextCompare, IDebugMemoryContext2 [] compareToItems, uint compareToLength, out uint foundIndex) { // // Compares the memory context to each context in the given array in the manner indicated by compare flags, // returning an index of the first context that matches. // LoggingUtils.PrintFunction(); try { if (compareToItems.Length != compareToLength) { throw new ArgumentException("Comparing contexts of different sizes."); } // // Get the context info for the current object. // CONTEXT_INFO [] currentContextInfo = new CONTEXT_INFO [1]; LoggingUtils.RequireOk(GetInfo(enum_CONTEXT_INFO_FIELDS.CIF_ALLFIELDS, currentContextInfo)); for (uint i = 0; i < compareToLength; ++i) { DebuggeeCodeContext compareTo = compareToItems [i] as DebuggeeCodeContext; if (compareTo == null) { continue; } CONTEXT_INFO [] compareToInfo = new CONTEXT_INFO [1]; LoggingUtils.RequireOk(compareTo.GetInfo(enum_CONTEXT_INFO_FIELDS.CIF_ALLFIELDS, compareToInfo)); if (!DebugEngine.ReferenceEquals(m_engine, compareTo.m_engine)) { continue; } bool comparisonResult = false; switch (contextCompare) { case enum_CONTEXT_COMPARE.CONTEXT_EQUAL: { comparisonResult = (currentContextInfo [0].bstrAddressAbsolute.CompareTo(compareToInfo [0].bstrAddressAbsolute) == 0); break; } case enum_CONTEXT_COMPARE.CONTEXT_LESS_THAN: { comparisonResult = (currentContextInfo [0].bstrAddressAbsolute.CompareTo(compareToInfo [0].bstrAddressAbsolute) < 0); break; } case enum_CONTEXT_COMPARE.CONTEXT_GREATER_THAN: { comparisonResult = (currentContextInfo [0].bstrAddressAbsolute.CompareTo(compareToInfo [0].bstrAddressAbsolute) > 0); break; } case enum_CONTEXT_COMPARE.CONTEXT_LESS_THAN_OR_EQUAL: { comparisonResult = (currentContextInfo [0].bstrAddressAbsolute.CompareTo(compareToInfo [0].bstrAddressAbsolute) <= 0); break; } case enum_CONTEXT_COMPARE.CONTEXT_GREATER_THAN_OR_EQUAL: { comparisonResult = (currentContextInfo [0].bstrAddressAbsolute.CompareTo(compareToInfo [0].bstrAddressAbsolute) >= 0); break; } case enum_CONTEXT_COMPARE.CONTEXT_SAME_PROCESS: { comparisonResult = true; break; } case enum_CONTEXT_COMPARE.CONTEXT_SAME_FUNCTION: { comparisonResult = (currentContextInfo [0].bstrFunction.CompareTo(compareToInfo [0].bstrFunction) == 0); break; } case enum_CONTEXT_COMPARE.CONTEXT_SAME_MODULE: { comparisonResult = (currentContextInfo [0].bstrModuleUrl.CompareTo(compareToInfo [0].bstrModuleUrl) == 0); break; } case enum_CONTEXT_COMPARE.CONTEXT_SAME_SCOPE: // Fallthrough. default: { throw new NotImplementedException(); } } if (comparisonResult) { foundIndex = i; return(Constants.S_OK); } } } catch (NotImplementedException e) { LoggingUtils.HandleException(e); foundIndex = uint.MaxValue; return(Constants.E_NOTIMPL); } catch (Exception e) { LoggingUtils.HandleException(e); foundIndex = uint.MaxValue; return(Constants.E_COMPARE_CANNOT_COMPARE); } foundIndex = uint.MaxValue; return(Constants.S_FALSE); }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public override int CreateBoundBreakpoint(string location, DebuggeeDocumentContext documentContext, DebuggeeCodeContext codeContext) { // // Register a new GDB breakpoint. // LoggingUtils.PrintFunction(); try { if (m_breakpointRequestInfo.bpLocation.bpLocationType == (uint)enum_BP_TYPE.BPT_DATA) { throw new NotImplementedException(); } m_debugger.RunInterruptOperation(delegate(CLangDebugger debugger) { string command = string.Format("-break-insert -f {0} {1}", ((m_breakpointEnabled) ? "" : "-d"), PathUtils.SantiseWindowsPath(location)); debugger.GdbClient.SendCommand(command, delegate(MiResultRecord resultRecord) { if (resultRecord != null) { if (resultRecord.IsError()) { string errorReason = "<unknown error>"; if (resultRecord.HasField("msg")) { errorReason = resultRecord ["msg"] [0].GetString(); } LoggingUtils.RequireOk(CreateErrorBreakpoint(errorReason, documentContext, codeContext)); } else { MiResultValue breakpointData = resultRecord ["bkpt"] [0]; MiBreakpoint breakpoint = new MiBreakpoint(breakpointData.Values); LoggingUtils.RequireOk(CreateBoundBreakpoint(breakpoint, documentContext, codeContext)); } } }); }); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public CLangDebuggeeBreakpointBound(CLangDebugger debugger, DebugBreakpointManager breakpointManager, DebuggeeBreakpointPending pendingBreakpoint, DebuggeeCodeContext codeContext, MiBreakpoint gdbBreakpoint) : base(breakpointManager, pendingBreakpoint, codeContext) { m_debugger = debugger; GdbBreakpoint = gdbBreakpoint; }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// private void RefreshBreakpoint(object breakpoint) { // // Validate breakpoint input type. This function can be used for 'bound' and 'error' objects, so we need to handle this appropriately. // LoggingUtils.PrintFunction(); CLangDebuggeeBreakpointBound boundBreakpoint = null; CLangDebuggeeBreakpointError errorBreakpoint = null; MiBreakpoint gdbBreakpoint; DebuggeeBreakpointResolution resolution; if (breakpoint == null) { throw new ArgumentNullException("breakpoint"); } else if (breakpoint is CLangDebuggeeBreakpointBound) { boundBreakpoint = breakpoint as CLangDebuggeeBreakpointBound; gdbBreakpoint = boundBreakpoint.GdbBreakpoint; IDebugBreakpointResolution2 boundBreakpointResolution; int handle = boundBreakpoint.GetBreakpointResolution(out boundBreakpointResolution); if (handle == Constants.E_BP_DELETED) { return; } LoggingUtils.RequireOk(handle); resolution = (DebuggeeBreakpointResolution)boundBreakpointResolution; } else if (breakpoint is CLangDebuggeeBreakpointError) { errorBreakpoint = breakpoint as CLangDebuggeeBreakpointError; gdbBreakpoint = errorBreakpoint.GdbBreakpoint; IDebugErrorBreakpointResolution2 errorBreakpointResolution; int handle = errorBreakpoint.GetBreakpointResolution(out errorBreakpointResolution); if (handle == Constants.E_BP_DELETED) { return; } resolution = (DebuggeeBreakpointResolution)errorBreakpointResolution; lock (m_errorBreakpoints) { m_errorBreakpoints.Remove(errorBreakpoint); } } else { throw new ArgumentException("breakpoint"); } // // Query breakpoint info/status directly from GDB/MI. // try { string command = string.Format("-break-info {0}", gdbBreakpoint.ID); m_debugger.GdbClient.SendCommand(command, delegate(MiResultRecord resultRecord) { if (resultRecord == null) { throw new InvalidOperationException(); } else if (resultRecord.IsError()) { // // GDB/MI breakpoint info request failed. // gdbBreakpoint.Address = MiBreakpoint.Pending; (resolution as DebuggeeBreakpointResolution).CodeContext.Address = new DebuggeeAddress(gdbBreakpoint.Address); errorBreakpoint = new CLangDebuggeeBreakpointError(m_debugger, m_breakpointManager, this, (resolution as DebuggeeBreakpointResolution).CodeContext, gdbBreakpoint, resultRecord.Records [1].Stream); lock (m_errorBreakpoints) { m_errorBreakpoints.Add(errorBreakpoint); } m_debugger.Engine.Broadcast(new DebugEngineEvent.BreakpointError(errorBreakpoint), m_debugger.NativeProgram.DebugProgram, m_debugger.NativeProgram.GetThread(m_debugger.NativeProgram.CurrentThreadId)); } else { // // We've probably got sane breakpoint information back. Update current breakpoint values and re-process. // MiResultValue breakpointData = resultRecord ["BreakpointTable"] [0] ["body"] [0] ["bkpt"] [0]; MiBreakpoint currentGdbBreakpoint = new MiBreakpoint(breakpointData.Values); DebuggeeCodeContext codeContext = (resolution as DebuggeeBreakpointResolution).CodeContext; DebuggeeDocumentContext documentContext = codeContext.DocumentContext; LoggingUtils.RequireOk(CreateBoundBreakpoint(currentGdbBreakpoint, documentContext, codeContext)); } }); } catch (Exception e) { LoggingUtils.HandleException(e); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int CreateBoundBreakpoint(MiBreakpoint breakpoint, DebuggeeDocumentContext documentContext, DebuggeeCodeContext codeContext) { LoggingUtils.PrintFunction(); try { if (breakpoint == null) { throw new ArgumentNullException("breakpoint"); } if (breakpoint.IsPending()) { // // Address can't be satisfied. Unsatisfied likely indicates the modules or symbols associated with the context aren't loaded, yet. // DebuggeeAddress pendingAddress = new DebuggeeAddress(MiBreakpoint.Pending); DebuggeeCodeContext pendingContext = new CLangDebuggeeCodeContext(m_debugger, pendingAddress, documentContext); LoggingUtils.RequireOk(CreateErrorBreakpoint("Additional library symbols required.", breakpoint, documentContext, pendingContext)); } else if (breakpoint.IsMultiple()) { // // Breakpoint satisfied to multiple locations, no single memory address available. // CLangDebuggeeBreakpointBound boundBreakpoint = new CLangDebuggeeBreakpointBound(m_debugger, m_breakpointManager, this, codeContext, breakpoint); lock (m_boundBreakpoints) { m_boundBreakpoints.Clear(); m_boundBreakpoints.Add(boundBreakpoint); } m_debugger.Engine.Broadcast(new DebugEngineEvent.BreakpointBound(this, boundBreakpoint), m_debugger.NativeProgram.DebugProgram, m_debugger.NativeProgram.GetThread(m_debugger.NativeProgram.CurrentThreadId)); } else { // // Address satisfied, and the breakpoint is legitimately bound. // DebuggeeAddress boundAddress = new DebuggeeAddress(breakpoint.Address); DebuggeeCodeContext addressContext = new CLangDebuggeeCodeContext(m_debugger, boundAddress, documentContext); CLangDebuggeeBreakpointBound boundBreakpoint = new CLangDebuggeeBreakpointBound(m_debugger, m_breakpointManager, this, addressContext, breakpoint); lock (m_boundBreakpoints) { m_boundBreakpoints.Clear(); m_boundBreakpoints.Add(boundBreakpoint); } m_debugger.Engine.Broadcast(new DebugEngineEvent.BreakpointBound(this, boundBreakpoint), m_debugger.NativeProgram.DebugProgram, m_debugger.NativeProgram.GetThread(m_debugger.NativeProgram.CurrentThreadId)); } return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public int CreateErrorBreakpoint(string errorReason, MiBreakpoint gdbBreakpoint, DebuggeeDocumentContext documentContext, DebuggeeCodeContext codeContext) { // // Create a C-language breakpoint. This is tied to a GDB/MI breakpoint object. // LoggingUtils.PrintFunction(); try { CLangDebuggeeBreakpointError errorBreakpoint = new CLangDebuggeeBreakpointError(m_debugger, m_breakpointManager, this, codeContext, gdbBreakpoint, errorReason); lock (m_errorBreakpoints) { m_errorBreakpoints.Clear(); m_errorBreakpoints.Add(errorBreakpoint); } uint numDebugPrograms = 1; IEnumDebugPrograms2 debugPrograms; IDebugProgram2 [] debugProgramsArray = new IDebugProgram2 [numDebugPrograms]; LoggingUtils.RequireOk(m_breakpointManager.Engine.EnumPrograms(out debugPrograms)); LoggingUtils.RequireOk(debugPrograms.Next(numDebugPrograms, debugProgramsArray, ref numDebugPrograms)); m_breakpointManager.Engine.Broadcast(new DebugEngineEvent.BreakpointError(errorBreakpoint), debugProgramsArray [0], null); return(Constants.S_OK); } catch (Exception e) { LoggingUtils.HandleException(e); return(Constants.E_FAIL); } }