internal async Task BindAsync() { if (CanBind()) { string documentName = null; string functionName = null; TEXT_POSITION[] startPosition = new TEXT_POSITION[1]; TEXT_POSITION[] endPosition = new TEXT_POSITION[1]; string condition = null; string address = null; ulong codeAddress = 0; uint size = 0; IEnumerable <Checksum> checksums = null; lock (_boundBreakpoints) { if (_bp != null) // already bound { Debug.Fail("Breakpoint already bound"); return; } if ((_bpRequestInfo.dwFields & enum_BPREQI_FIELDS.BPREQI_CONDITION) != 0 && _bpRequestInfo.bpCondition.styleCondition == enum_BP_COND_STYLE.BP_COND_WHEN_TRUE) { condition = _bpRequestInfo.bpCondition.bstrCondition; } if ((_bpRequestInfo.dwFields & enum_BPREQI_FIELDS.BPREQI_BPLOCATION) != 0) { switch ((enum_BP_LOCATION_TYPE)_bpRequestInfo.bpLocation.bpLocationType) { case enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET: { IDebugFunctionPosition2 functionPosition = HostMarshal.GetDebugFunctionPositionForIntPtr(_bpRequestInfo.bpLocation.unionmember2); EngineUtils.CheckOk(functionPosition.GetFunctionName(out functionName)); break; } case enum_BP_LOCATION_TYPE.BPLT_CODE_CONTEXT: { IDebugCodeContext2 codePosition = HostMarshal.GetDebugCodeContextForIntPtr(_bpRequestInfo.bpLocation.unionmember1); if (!(codePosition is AD7MemoryAddress)) { goto default; // context is not from this engine } codeAddress = ((AD7MemoryAddress)codePosition).Address; break; } case enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE: { IDebugDocumentPosition2 docPosition = HostMarshal.GetDocumentPositionForIntPtr(_bpRequestInfo.bpLocation.unionmember2); // Get the name of the document that the breakpoint was put in EngineUtils.CheckOk(docPosition.GetFileName(out documentName)); // Get the location in the document that the breakpoint is in. EngineUtils.CheckOk(docPosition.GetRange(startPosition, endPosition)); // Get the document checksum // TODO: This and all other AD7 interface calls need to be moved so that they are only // executed from the main thread. // Github issue: https://github.com/Microsoft/MIEngine/issues/350 if (_engine.DebuggedProcess.MICommandFactory.SupportsBreakpointChecksums()) { try { checksums = GetSHA1Checksums(); } catch (Exception) { // If we fail to get a checksum there's nothing else we can do } } break; } case enum_BP_LOCATION_TYPE.BPLT_DATA_STRING: { address = HostMarshal.GetDataBreakpointStringForIntPtr(_bpRequestInfo.bpLocation.unionmember3); size = (uint)_bpRequestInfo.bpLocation.unionmember4; if (condition != null) { goto default; // mi has no conditions on watchpoints } break; } default: { this.SetError(new AD7ErrorBreakpoint(this, ResourceStrings.UnsupportedBreakpoint), true); return; } } } } PendingBreakpoint.BindResult bindResult; // Bind all breakpoints that match this source and line number. if (documentName != null) { bindResult = await PendingBreakpoint.Bind(documentName, startPosition[0].dwLine + 1, startPosition[0].dwColumn, _engine.DebuggedProcess, condition, _enabled, checksums, this); } else if (functionName != null) { bindResult = await PendingBreakpoint.Bind(functionName, _engine.DebuggedProcess, condition, _enabled, this); } else if (codeAddress != 0) { bindResult = await PendingBreakpoint.Bind(codeAddress, _engine.DebuggedProcess, condition, _enabled, this); } else { bindResult = await PendingBreakpoint.Bind(address, size, _engine.DebuggedProcess, condition, this); } lock (_boundBreakpoints) { if (bindResult.PendingBreakpoint != null) { _bp = bindResult.PendingBreakpoint; // an MI breakpoint object exists: TODO: lock? } if (bindResult.BoundBreakpoints == null || bindResult.BoundBreakpoints.Count == 0) { this.SetError(new AD7ErrorBreakpoint(this, bindResult.ErrorMessage), true); } else { Debug.Assert(_bp != null); foreach (BoundBreakpoint bp in bindResult.BoundBreakpoints) { AddBoundBreakpoint(bp); } } } } }
// Binds this pending breakpoint to one or more code locations. int IDebugPendingBreakpoint2.Bind() { try { if (CanBind()) { // Make sure that HostMarshal calls happen on main thread instead of poll thread. lock (_boundBreakpoints) { if (_bp != null) // already bound { Debug.Fail("Breakpoint already bound"); return(Constants.S_FALSE); } if ((_bpRequestInfo.dwFields & enum_BPREQI_FIELDS.BPREQI_CONDITION) != 0 && _bpRequestInfo.bpCondition.styleCondition == enum_BP_COND_STYLE.BP_COND_WHEN_TRUE) { _condition = _bpRequestInfo.bpCondition.bstrCondition; } if ((_bpRequestInfo.dwFields & enum_BPREQI_FIELDS.BPREQI_BPLOCATION) != 0) { switch ((enum_BP_LOCATION_TYPE)_bpRequestInfo.bpLocation.bpLocationType) { case enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET: try { IDebugFunctionPosition2 functionPosition = HostMarshal.GetDebugFunctionPositionForIntPtr(_bpRequestInfo.bpLocation.unionmember2); EngineUtils.CheckOk(functionPosition.GetFunctionName(out _functionName)); } finally { HostMarshal.Release(_bpRequestInfo.bpLocation.unionmember2); } break; case enum_BP_LOCATION_TYPE.BPLT_CODE_CONTEXT: try { IDebugCodeContext2 codePosition = HostMarshal.GetDebugCodeContextForIntPtr(_bpRequestInfo.bpLocation.unionmember1); if (!(codePosition is AD7MemoryAddress)) { goto default; // context is not from this engine } _codeAddress = ((AD7MemoryAddress)codePosition).Address; } finally { HostMarshal.Release(_bpRequestInfo.bpLocation.unionmember1); } break; case enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE: try { IDebugDocumentPosition2 docPosition = HostMarshal.GetDocumentPositionForIntPtr(_bpRequestInfo.bpLocation.unionmember2); // Get the name of the document that the breakpoint was put in EngineUtils.CheckOk(docPosition.GetFileName(out _documentName)); // Get the location in the document that the breakpoint is in. EngineUtils.CheckOk(docPosition.GetRange(_startPosition, _endPosition)); } finally { HostMarshal.Release(_bpRequestInfo.bpLocation.unionmember2); } // Get the document checksum if (_engine.DebuggedProcess.MICommandFactory.SupportsBreakpointChecksums()) { try { _checksums = GetSHA1Checksums(); } catch (Exception) { // If we fail to get a checksum there's nothing else we can do } } break; case enum_BP_LOCATION_TYPE.BPLT_DATA_STRING: _address = HostMarshal.GetDataBreakpointStringForIntPtr(_bpRequestInfo.bpLocation.unionmember3); _size = (uint)_bpRequestInfo.bpLocation.unionmember4; if (_condition != null) { goto default; // mi has no conditions on watchpoints } break; default: this.SetError(new AD7ErrorBreakpoint(this, ResourceStrings.UnsupportedBreakpoint), true); return(Constants.S_FALSE); } } } Task bindTask = null; _engine.DebuggedProcess.WorkerThread.RunOperation(() => { bindTask = _engine.DebuggedProcess.AddInternalBreakAction(this.BindAsync); }); bindTask.Wait(_engine.GetBPLongBindTimeout()); if (!bindTask.IsCompleted) { //send a low severity warning bp. This will allow the UI to respond quickly, and if the mi debugger doesn't end up binding, this warning will get //replaced by the real mi debugger error text this.SetError(new AD7ErrorBreakpoint(this, ResourceStrings.LongBind, enum_BP_ERROR_TYPE.BPET_SEV_LOW | enum_BP_ERROR_TYPE.BPET_TYPE_WARNING), true); return(Constants.S_FALSE); } else { return(Constants.S_OK); } } else { // The breakpoint could not be bound. This may occur for many reasons such as an invalid location, an invalid expression, etc... _engine.Callback.OnBreakpointError(_BPError); return(Constants.S_FALSE); } } catch (MIException e) { return(e.HResult); } catch (AggregateException e) { if (e.GetBaseException() is InvalidCoreDumpOperationException) { return(AD7_HRESULT.E_CRASHDUMP_UNSUPPORTED); } else { return(EngineUtils.UnexpectedException(e)); } } catch (InvalidCoreDumpOperationException) { return(AD7_HRESULT.E_CRASHDUMP_UNSUPPORTED); } catch (Exception e) { return(EngineUtils.UnexpectedException(e)); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 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); } }
internal async Task BindAsync() { if (CanBind()) { string documentName = null; string functionName = null; TEXT_POSITION[] startPosition = new TEXT_POSITION[1]; TEXT_POSITION[] endPosition = new TEXT_POSITION[1]; string condition = null; lock (_boundBreakpoints) { if (_bp != null) // already bound { Debug.Fail("Breakpoint already bound"); return; } if ((_bpRequestInfo.dwFields & enum_BPREQI_FIELDS.BPREQI_BPLOCATION) != 0) { if (_bpRequestInfo.bpLocation.bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET) { IDebugFunctionPosition2 functionPosition = HostMarshal.GetDebugFunctionPositionForIntPtr(_bpRequestInfo.bpLocation.unionmember2); EngineUtils.CheckOk(functionPosition.GetFunctionName(out functionName)); } else if (_bpRequestInfo.bpLocation.bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE) { IDebugDocumentPosition2 docPosition = HostMarshal.GetDocumentPositionForIntPtr(_bpRequestInfo.bpLocation.unionmember2); // Get the name of the document that the breakpoint was put in EngineUtils.CheckOk(docPosition.GetFileName(out documentName)); // Get the location in the document that the breakpoint is in. EngineUtils.CheckOk(docPosition.GetRange(startPosition, endPosition)); } } if ((_bpRequestInfo.dwFields & enum_BPREQI_FIELDS.BPREQI_CONDITION) != 0 && _bpRequestInfo.bpCondition.styleCondition == enum_BP_COND_STYLE.BP_COND_WHEN_TRUE) { condition = _bpRequestInfo.bpCondition.bstrCondition; } } PendingBreakpoint.BindResult bindResult; // Bind all breakpoints that match this source and line number. if (documentName != null) { bindResult = await PendingBreakpoint.Bind(documentName, startPosition[0].dwLine + 1, startPosition[0].dwColumn, _engine.DebuggedProcess, condition, this); } else { bindResult = await PendingBreakpoint.Bind(functionName, _engine.DebuggedProcess, condition, this); } lock (_boundBreakpoints) { if (bindResult.PendingBreakpoint != null) { _bp = bindResult.PendingBreakpoint; // an MI breakpoint object exists: TODO: lock? } if (bindResult.BoundBreakpoints == null || bindResult.BoundBreakpoints.Count == 0) { _BPError = new AD7ErrorBreakpoint(this, bindResult.ErrorMessage); _engine.Callback.OnBreakpointError(_BPError); } else { Debug.Assert(_bp != null); foreach (BoundBreakpoint bp in bindResult.BoundBreakpoints) { AddBoundBreakpoint(bp); } } } } }
/// <summary> /// AD7BoundBreakpoint constructor for file/line breaks. /// </summary> /// <param name="engine"> AD7 Engine. </param> /// <param name="bpReqInfo"> Contains the information required to implement a breakpoint. </param> /// <param name="pendingBreakpoint"> Associated pending breakpoint. </param> public AD7BoundBreakpoint(AD7Engine engine, BP_REQUEST_INFO bpReqInfo, AD7PendingBreakpoint pendingBreakpoint) { if (bpReqInfo.bpLocation.bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE) { string documentName; // Get Decument Position and File Name IDebugDocumentPosition2 docPosition = (IDebugDocumentPosition2)(Marshal.GetObjectForIUnknown(bpReqInfo.bpLocation.unionmember2)); docPosition.GetFileName(out documentName); // Need to shorten the path we send to GDB. StringBuilder shortPath = new StringBuilder(1024); GetShortPathName(documentName, shortPath, shortPath.Capacity); // Get the location in the document that the breakpoint is in. TEXT_POSITION[] startPosition = new TEXT_POSITION[1]; TEXT_POSITION[] endPosition = new TEXT_POSITION[1]; docPosition.GetRange(startPosition, endPosition); m_engine = engine; m_bpLocationType = (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE; m_filename = shortPath.ToString(); m_line = startPosition[0].dwLine + 1; m_pendingBreakpoint = pendingBreakpoint; m_enabled = true; m_deleted = false; m_hitCount = 0; m_remoteID = m_engine.BPMgr.RemoteAdd(this); } else if (bpReqInfo.bpLocation.bpLocationType == (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET) { string func; IDebugFunctionPosition2 funcPosition = (IDebugFunctionPosition2)(Marshal.GetObjectForIUnknown(bpReqInfo.bpLocation.unionmember2)); funcPosition.GetFunctionName(out func); m_engine = engine; m_func = func; m_enabled = true; m_deleted = false; m_hitCount = 0; m_bpLocationType = (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET; m_pendingBreakpoint = pendingBreakpoint; m_remoteID = m_engine.BPMgr.RemoteAdd(this); } // if ((m_remoteID == 0) && (VSNDK.AddIn.VSNDKAddIn.isDebugEngineRunning == false)) if (m_remoteID == 0) { return; } // Set the hit count and condition if (bpReqInfo.bpPassCount.stylePassCount != enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_NONE) { SetPassCount(bpReqInfo.bpPassCount); } if (bpReqInfo.bpCondition.styleCondition != enum_BP_COND_STYLE.BP_COND_NONE) { SetCondition(bpReqInfo.bpCondition); } // Get the Line Position sent back from GDB TEXT_POSITION tpos = new TEXT_POSITION(); tpos.dwLine = m_GDB_linePos - 1; uint xAddress = UInt32.Parse(m_GDB_Address.Substring(2), System.Globalization.NumberStyles.HexNumber); AD7MemoryAddress codeContext = new AD7MemoryAddress(m_engine, xAddress); AD7DocumentContext documentContext = new AD7DocumentContext(m_GDB_filename, tpos, tpos, codeContext); m_breakpointResolution = new AD7BreakpointResolution(m_engine, xAddress, documentContext); m_engine.Callback.OnBreakpointBound(this, 0); }
// Binds this pending breakpoint to one or more code locations. int IDebugPendingBreakpoint2.Bind() { try { if (CanBind()) { // Make sure that HostMarshal calls happen on main thread instead of poll thread. lock (_boundBreakpoints) { if (_bp != null) // already bound { Debug.Fail("Breakpoint already bound"); return(Constants.S_FALSE); } if ((_bpRequestInfo.dwFields & enum_BPREQI_FIELDS.BPREQI_CONDITION) != 0 && _bpRequestInfo.bpCondition.styleCondition == enum_BP_COND_STYLE.BP_COND_WHEN_TRUE) { _condition = _bpRequestInfo.bpCondition.bstrCondition; } if ((_bpRequestInfo.dwFields & enum_BPREQI_FIELDS.BPREQI_BPLOCATION) != 0) { switch ((enum_BP_LOCATION_TYPE)_bpRequestInfo.bpLocation.bpLocationType) { case enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET: try { IDebugFunctionPosition2 functionPosition = HostMarshal.GetDebugFunctionPositionForIntPtr(_bpRequestInfo.bpLocation.unionmember2); EngineUtils.CheckOk(functionPosition.GetFunctionName(out _functionName)); } finally { HostMarshal.Release(_bpRequestInfo.bpLocation.unionmember2); } break; case enum_BP_LOCATION_TYPE.BPLT_CODE_CONTEXT: try { IDebugCodeContext2 codePosition = HostMarshal.GetDebugCodeContextForIntPtr(_bpRequestInfo.bpLocation.unionmember1); if (!(codePosition is AD7MemoryAddress)) { goto default; // context is not from this engine } _codeAddress = ((AD7MemoryAddress)codePosition).Address; } finally { HostMarshal.Release(_bpRequestInfo.bpLocation.unionmember1); } break; case enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE: try { IDebugDocumentPosition2 docPosition = HostMarshal.GetDocumentPositionForIntPtr(_bpRequestInfo.bpLocation.unionmember2); // Get the name of the document that the breakpoint was put in EngineUtils.CheckOk(docPosition.GetFileName(out _documentName)); // Get the location in the document that the breakpoint is in. EngineUtils.CheckOk(docPosition.GetRange(_startPosition, _endPosition)); } finally { HostMarshal.Release(_bpRequestInfo.bpLocation.unionmember2); } // Get the document checksum if (_engine.DebuggedProcess.MICommandFactory.SupportsBreakpointChecksums()) { try { _checksums = GetSHA1Checksums(); } catch (Exception) { // If we fail to get a checksum there's nothing else we can do } } break; case enum_BP_LOCATION_TYPE.BPLT_DATA_STRING: string address = HostMarshal.GetDataBreakpointStringForIntPtr(_bpRequestInfo.bpLocation.unionmember3); if (address.Contains(",")) { this.AddressId = address; _address = address.Split(',')[0]; } else { this.AddressId = null; _address = address; } _size = (uint)_bpRequestInfo.bpLocation.unionmember4; if (_condition != null) { goto default; // mi has no conditions on watchpoints } break; default: this.SetError(new AD7ErrorBreakpoint(this, ResourceStrings.UnsupportedBreakpoint), true); return(Constants.S_FALSE); } } } if (!_enabled && IsHardwareBreakpoint) { return(Constants.S_OK); } return(BindWithTimeout()); } else { // The breakpoint could not be bound. This may occur for many reasons such as an invalid location, an invalid expression, etc... _engine.Callback.OnBreakpointError(_BPError); return(Constants.S_FALSE); } } catch (MIException e) { return(e.HResult); } catch (AggregateException e) { if (e.GetBaseException() is InvalidCoreDumpOperationException) { return(AD7_HRESULT.E_CRASHDUMP_UNSUPPORTED); } else { return(EngineUtils.UnexpectedException(e)); } } catch (InvalidCoreDumpOperationException) { return(AD7_HRESULT.E_CRASHDUMP_UNSUPPORTED); } catch (Exception e) { return(EngineUtils.UnexpectedException(e)); } }