public void RemoteDisable(AD7BoundBreakpoint aBBP) { mActiveBPs[aBBP.RemoteID] = null; int index = mEngine.mProcess.INT3sSet.FindIndex(x => x.Key == aBBP.mAddress); mEngine.mProcess.INT3sSet.RemoveAt(index); mDbgConnector.DeleteBreakpoint(aBBP.RemoteID); }
// Engines notify the debugger that a breakpoint has bound through the breakpoint bound event. public void OnBreakpointBound(object objBoundBreakpoint, uint address) { AD7BoundBreakpoint boundBreakpoint = (AD7BoundBreakpoint)objBoundBreakpoint; IDebugPendingBreakpoint2 pendingBreakpoint; ((IDebugBoundBreakpoint2)boundBreakpoint).GetPendingBreakpoint(out pendingBreakpoint); AD7BreakpointBoundEvent eventObject = new AD7BreakpointBoundEvent((AD7PendingBreakpoint)pendingBreakpoint, boundBreakpoint); Send(eventObject, AD7BreakpointBoundEvent.IID, null); }
// Creates an entry and remotely enables the breakpoint in the debug stub public int RemoteEnable(AD7BoundBreakpoint aBBP) { for (int xID = 0; xID < MaxBP; xID++) { if (mActiveBPs[xID] == null) { mActiveBPs[xID] = aBBP; var label = mEngine.mProcess.mDebugInfoDb.GetLabels(aBBP.mAddress)[0]; mEngine.mProcess.INT3sSet.Add(new KeyValuePair<uint, string>(aBBP.mAddress, label)); mDbgConnector.SetBreakpoint(xID, aBBP.mAddress); return xID; } } throw new Exception("Maximum number of active breakpoints exceeded (" + MaxBP + ")."); }
// Creates an entry and remotely enables the breakpoint in the debug stub public int RemoteEnable(AD7BoundBreakpoint aBBP) { for (int xID = 0; xID < MaxBP; xID++) { if (mActiveBPs[xID] == null) { mActiveBPs[xID] = aBBP; var label = mEngine.mProcess.mDebugInfoDb.GetLabels(aBBP.mAddress)[0]; mEngine.mProcess.INT3sSet.Add(new KeyValuePair <uint, string>(aBBP.mAddress, label)); mDbgConnector.SetBreakpoint(xID, aBBP.mAddress); return(xID); } } throw new Exception("Maximum number of active breakpoints exceeded (" + MaxBP + ")."); }
// Binds this pending breakpoint to one or more code locations. int IDebugPendingBreakpoint2.Bind() { try { if (CanBind()) { var xDocPos = (IDebugDocumentPosition2)(Marshal.GetObjectForIUnknown(mBpRequestInfo.bpLocation.unionmember2)); // Get the name of the document that the breakpoint was put in string xDocName; EngineUtils.CheckOk(xDocPos.GetFileName(out xDocName)); xDocName = xDocName.ToLower(); //Bug: Some filenames were returned with the drive letter as lower case but in DocumentGUIDs it was captialised so file-not-found! // Get the location in the document that the breakpoint is in. var xStartPos = new TEXT_POSITION[1]; var xEndPos = new TEXT_POSITION[1]; EngineUtils.CheckOk(xDocPos.GetRange(xStartPos, xEndPos)); UInt32 xAddress = 0; var xDebugInfo = mEngine.mProcess.mDebugInfoDb; // We must check for DocID. This is important because in a solution that contains many projects, // VS will send us BPs from other Cosmos projects (and possibly non Cosmos ones, didnt look that deep) // but we wont have them in our doc list because it contains only ones from the currently project // to run. long xDocID; if (xDebugInfo.DocumentGUIDs.TryGetValue(xDocName, out xDocID)) { // Find which Method the Doc, Line, Col are in. // Must add +1 for both Line and Col. They are 0 based, while SP ones are 1 based. // () around << are VERY important.. + has precedence over << Int64 xPos = (((Int64)xStartPos[0].dwLine + 1) << 32) + xStartPos[0].dwColumn + 1; try { var potXMethods = xDebugInfo.Connection.Query(new SQLinq<Method>().Where(x => x.DocumentID == xDocID && x.LineColStart <= xPos && x.LineColEnd >= xPos)); var xMethod = potXMethods.Single(); var asm = xDebugInfo.Connection.Get<AssemblyFile>(xMethod.AssemblyFileID); // We have the method. Now find out what Sequence Point it belongs to. var xSPs = xDebugInfo.GetSequencePoints(asm.Pathname, xMethod.MethodToken); var xSP = xSPs.Single(q => q.LineColStart <= xPos && q.LineColEnd >= xPos); // We have the Sequence Point, find the MethodILOp var xOp = xDebugInfo.Connection.Query(new SQLinq<MethodIlOp>().Where(q => q.MethodID == xMethod.ID && q.IlOffset == xSP.Offset)).First(); // Get the address of the Label xAddress = xDebugInfo.AddressOfLabel(xOp.LabelName); if (xAddress > 0) { var xBPR = new AD7BreakpointResolution(mEngine, xAddress, GetDocumentContext(xAddress)); var xBBP = new AD7BoundBreakpoint(mEngine, xAddress, this, xBPR); mBoundBPs.Add(xBBP); } // Ask the symbol engine to find all addresses in all modules with symbols that match this source and line number. //uint[] addresses = mEngine.DebuggedProcess.GetAddressesForSourceLocation(null, documentName, startPosition[0].dwLine + 1, startPosition[0].dwColumn); lock (mBoundBPs) { //foreach (uint addr in addresses) { // AD7BreakpointResolution breakpointResolution = new AD7BreakpointResolution(mEngine, addr, GetDocumentContext(addr)); // AD7BoundBreakpoint boundBreakpoint = new AD7BoundBreakpoint(mEngine, addr, this, breakpointResolution); // m_boundBreakpoints.Add(boundBreakpoint); // mEngine.DebuggedProcess.SetBreakpoint(addr, boundBreakpoint); //} } } catch(InvalidOperationException) { //No elements in potXMethods sequence! return VSConstants.S_FALSE; } } 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... // The sample engine does not support this, but a real world engine will want to send an instance of IDebugBreakpointErrorEvent2 to the // UI and return a valid instance of IDebugErrorBreakpoint2 from IDebugPendingBreakpoint2::EnumErrorBreakpoints. The debugger will then // display information about why the breakpoint did not bind to the user. return VSConstants.S_FALSE; } } //catch (ComponentException e) //{ // return e.HResult; //} catch (Exception e) { return EngineUtils.UnexpectedException(e); } }
// Called by bound breakpoints when they are being deleted. public void OnBoundBreakpointDeleted(AD7BoundBreakpoint boundBreakpoint) { lock (mBoundBPs) { mBoundBPs.Remove(boundBreakpoint); } }
// Binds this pending breakpoint to one or more code locations. int IDebugPendingBreakpoint2.Bind() { try { if (CanBind()) { var xDocPos = (IDebugDocumentPosition2)(Marshal.GetObjectForIUnknown(mBpRequestInfo.bpLocation.unionmember2)); // Get the name of the document that the breakpoint was put in string xDocName; EngineUtils.CheckOk(xDocPos.GetFileName(out xDocName)); xDocName = xDocName.ToLower(); //Bug: Some filenames were returned with the drive letter as lower case but in DocumentGUIDs it was captialised so file-not-found! // Get the location in the document that the breakpoint is in. var xStartPos = new TEXT_POSITION[1]; var xEndPos = new TEXT_POSITION[1]; EngineUtils.CheckOk(xDocPos.GetRange(xStartPos, xEndPos)); UInt32 xAddress = 0; var xDebugInfo = mEngine.mProcess.mDebugInfoDb; // We must check for DocID. This is important because in a solution that contains many projects, // VS will send us BPs from other Cosmos projects (and possibly non Cosmos ones, didnt look that deep) // but we wont have them in our doc list because it contains only ones from the currently project // to run. Guid xDocID; if (xDebugInfo.DocumentGUIDs.TryGetValue(xDocName, out xDocID)) { // Find which Method the Doc, Line, Col are in. // Must add +1 for both Line and Col. They are 0 based, while SP ones are 1 based. // () around << are VERY important.. + has precedence over << Int64 xPos = (((Int64)xStartPos[0].dwLine + 1) << 32) + xStartPos[0].dwColumn + 1; try { var potXMethods = xDebugInfo.Connection.Query(new SQLinq <Method>().Where(x => x.DocumentID == xDocID && x.LineColStart <= xPos && x.LineColEnd >= xPos)); var xMethod = potXMethods.Single(); var asm = xDebugInfo.Connection.Get <AssemblyFile>(xMethod.AssemblyFileID); // We have the method. Now find out what Sequence Point it belongs to. var xSPs = xDebugInfo.GetSequencePoints(asm.Pathname, xMethod.MethodToken); var xSP = xSPs.Single(q => q.LineColStart <= xPos && q.LineColEnd >= xPos); // We have the Sequence Point, find the MethodILOp var xOp = xDebugInfo.Connection.Query(new SQLinq <MethodIlOp>().Where(q => q.MethodID == xMethod.ID && q.IlOffset == xSP.Offset)).First(); // Get the address of the Label xAddress = xDebugInfo.AddressOfLabel(xOp.LabelName); if (xAddress > 0) { var xBPR = new AD7BreakpointResolution(mEngine, xAddress, GetDocumentContext(xAddress)); var xBBP = new AD7BoundBreakpoint(mEngine, xAddress, this, xBPR); mBoundBPs.Add(xBBP); } // Ask the symbol engine to find all addresses in all modules with symbols that match this source and line number. //uint[] addresses = mEngine.DebuggedProcess.GetAddressesForSourceLocation(null, documentName, startPosition[0].dwLine + 1, startPosition[0].dwColumn); lock (mBoundBPs) { //foreach (uint addr in addresses) { // AD7BreakpointResolution breakpointResolution = new AD7BreakpointResolution(mEngine, addr, GetDocumentContext(addr)); // AD7BoundBreakpoint boundBreakpoint = new AD7BoundBreakpoint(mEngine, addr, this, breakpointResolution); // m_boundBreakpoints.Add(boundBreakpoint); // mEngine.DebuggedProcess.SetBreakpoint(addr, boundBreakpoint); //} } } catch (InvalidOperationException) { //No elements in potXMethods sequence! return(VSConstants.S_FALSE); } } 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... // The sample engine does not support this, but a real world engine will want to send an instance of IDebugBreakpointErrorEvent2 to the // UI and return a valid instance of IDebugErrorBreakpoint2 from IDebugPendingBreakpoint2::EnumErrorBreakpoints. The debugger will then // display information about why the breakpoint did not bind to the user. return(VSConstants.S_FALSE); } } //catch (ComponentException e) //{ // return e.HResult; //} catch (Exception e) { return(EngineUtils.UnexpectedException(e)); } }
public AD7BreakpointBoundEvent(AD7PendingBreakpoint pendingBreakpoint, AD7BoundBreakpoint boundBreakpoint) { m_pendingBreakpoint = pendingBreakpoint; m_boundBreakpoint = boundBreakpoint; }