// 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)); uint 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 << long xPos = (((long)xStartPos[0].dwLine + 1) << 32) + xStartPos[0].dwColumn + 1; try { var xMethod = xDebugInfo.GetMethodByDocumentIDAndLinePosition(xDocID, xPos, xPos); var asm = xDebugInfo.GetAssemblyFileById(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.GetFirstMethodIlOpByMethodIdAndILOffset(xMethod.ID, xSP.Offset); // Get the address of the Label xAddress = xDebugInfo.GetAddressOfLabel(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 AD7BoundBreakpoint(AD7Engine aEngine, uint aAddress, AD7PendingBreakpoint aPendingBP, AD7BreakpointResolution breakpointResolution) { mEngine = aEngine; mAddress = aAddress; m_pendingBreakpoint = aPendingBP; m_breakpointResolution = breakpointResolution; mRemoteID = mEngine.BPMgr.RemoteEnable(this); }