private bool CanBind() { // The sample engine only supports breakpoints on a file and line number or function name. No other types of breakpoints are supported. if (_deleted || (_bpRequestInfo.bpLocation.bpLocationType != (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE && _bpRequestInfo.bpLocation.bpLocationType != (uint)enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET)) { _BPError = new AD7ErrorBreakpoint(this, ResourceStrings.UnsupportedBreakpoint, enum_BP_ERROR_TYPE.BPET_GENERAL_ERROR); return(false); } if ((_bpRequestInfo.dwFields & enum_BPREQI_FIELDS.BPREQI_CONDITION) != 0) { if (!VerifyCondition(_bpRequestInfo.bpCondition)) { _BPError = new AD7ErrorBreakpoint(this, ResourceStrings.UnsupportedConditionalBreakpoint, enum_BP_ERROR_TYPE.BPET_GENERAL_ERROR); return(false); } } if ((_bpRequestInfo.dwFields & enum_BPREQI_FIELDS.BPREQI_PASSCOUNT) != 0) { _BPError = new AD7ErrorBreakpoint(this, ResourceStrings.UnsupportedPassCountBreakpoint, enum_BP_ERROR_TYPE.BPET_GENERAL_ERROR); return(false); } return(true); }
// Binds this pending breakpoint to one or more code locations. int IDebugPendingBreakpoint2.Bind() { try { if (CanBind()) { Task bindTask = null; _engine.DebuggedProcess.WorkerThread.RunOperation(() => { bindTask = _engine.DebuggedProcess.AddInternalBreakAction(this.BindAsync); }); bindTask.Wait(250); //wait a quarter of a second 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 _BPError = new AD7ErrorBreakpoint(this, ResourceStrings.LongBind, enum_BP_ERROR_TYPE.BPET_SEV_LOW | enum_BP_ERROR_TYPE.BPET_TYPE_WARNING); _engine.Callback.OnBreakpointError(_BPError); return(VSConstants.S_FALSE); } else { return(VSConstants.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(VSConstants.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)); } }
// The sample engine does not support pass counts on breakpoints. int IDebugPendingBreakpoint2.SetPassCount(BP_PASSCOUNT bpPassCount) { if (bpPassCount.stylePassCount != enum_BP_PASSCOUNT_STYLE.BP_PASSCOUNT_NONE) { _BPError = new AD7ErrorBreakpoint(this, ResourceStrings.UnsupportedPassCountBreakpoint, enum_BP_ERROR_TYPE.BPET_GENERAL_ERROR); _engine.Callback.OnBreakpointError(_BPError); return(VSConstants.E_FAIL); } return(VSConstants.S_OK); }
public AD7PendingBreakpoint(IDebugBreakpointRequest2 pBPRequest, AD7Engine engine, BreakpointManager bpManager) { _pBPRequest = pBPRequest; BP_REQUEST_INFO[] requestInfo = new BP_REQUEST_INFO[1]; EngineUtils.CheckOk(_pBPRequest.GetRequestInfo(enum_BPREQI_FIELDS.BPREQI_BPLOCATION | enum_BPREQI_FIELDS.BPREQI_CONDITION | enum_BPREQI_FIELDS.BPREQI_PASSCOUNT, requestInfo)); _bpRequestInfo = requestInfo[0]; _engine = engine; _bpManager = bpManager; _boundBreakpoints = new List <AD7BoundBreakpoint>(); _enabled = true; _deleted = false; _pendingDelete = false; _bp = null; // no underlying breakpoint created yet _BPError = null; }
int IDebugPendingBreakpoint2.SetCondition(BP_CONDITION bpCondition) { PendingBreakpoint bp = null; lock (_boundBreakpoints) { if (!VerifyCondition(bpCondition)) { _BPError = new AD7ErrorBreakpoint(this, ResourceStrings.UnsupportedConditionalBreakpoint, enum_BP_ERROR_TYPE.BPET_GENERAL_ERROR); _engine.Callback.OnBreakpointError(_BPError); return(VSConstants.E_FAIL); } if ((_bpRequestInfo.dwFields & enum_BPREQI_FIELDS.BPREQI_CONDITION) != 0 && _bpRequestInfo.bpCondition.styleCondition == bpCondition.styleCondition && _bpRequestInfo.bpCondition.bstrCondition == bpCondition.bstrCondition) { return(VSConstants.S_OK); // this condition was already set } _bpRequestInfo.bpCondition = bpCondition; _bpRequestInfo.dwFields |= enum_BPREQI_FIELDS.BPREQI_CONDITION; if (_bp != null) { bp = _bp; } } if (bp != null) { _engine.DebuggedProcess.WorkerThread.RunOperation(() => { _engine.DebuggedProcess.AddInternalBreakAction( () => bp.SetConditionAsync(bpCondition.bstrCondition, _engine.DebuggedProcess) ); }); } return(VSConstants.S_OK); }
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); } } } } }