public void EnumCodeContexts(int numLocations)
        {
            var mockDocumentPosition = Substitute.For <IDebugDocumentPosition2>();

            mockDocumentPosition.GetRange(Arg.Any <TEXT_POSITION[]>(), null).Returns(x =>
            {
                var startPositions       = x[0] as TEXT_POSITION[];
                startPositions[0].dwLine = LINE;
                return(VSConstants.S_OK);
            });

            mockDocumentPosition.GetFileName(out string _).Returns(x =>
            {
                x[0] = Path.Combine(DIRECTORY, FILE_NAME);
                return(VSConstants.S_OK);
            });
            var mockBreakpoint   = Substitute.For <RemoteBreakpoint>();
            var mockCodeContexts = new IDebugCodeContext2[numLocations];

            for (uint i = 0; i < numLocations; ++i)
            {
                var mockAddress = Substitute.For <SbAddress>();
                mockAddress.GetLoadAddress(mockRemoteTarget).Returns(ADDRESS + i);
                var mockFunction = Substitute.For <SbFunction>();
                mockFunction.GetName().Returns(NAME + i);
                mockAddress.GetFunction().Returns(mockFunction);
                var lineEntry = new LineEntryInfo();
                mockAddress.GetLineEntry().Returns(lineEntry);
                var mockDocumentContext = Substitute.For <IDebugDocumentContext2>();
                mockDocumentContextFactory.Create(lineEntry).Returns(mockDocumentContext);
                var mockCodeContext = Substitute.For <IDebugCodeContext2>();
                mockCodeContextFactory
                .Create(ADDRESS + i, NAME + i, mockDocumentContext, Guid.Empty)
                .Returns(mockCodeContext);
                var mockBreakpointLocation = Substitute.For <SbBreakpointLocation>();
                mockBreakpointLocation.GetAddress().Returns(mockAddress);
                mockBreakpoint.GetLocationAtIndex(i).Returns(mockBreakpointLocation);
                mockCodeContexts[i] = mockCodeContext;
            }
            mockBreakpoint.GetNumLocations().Returns((uint)numLocations);
            mockRemoteTarget.BreakpointCreateByLocation(Path.Combine(DIRECTORY, FILE_NAME),
                                                        LINE + 1).Returns(mockBreakpoint);
            int result = program.EnumCodeContexts(mockDocumentPosition,
                                                  out IEnumDebugCodeContexts2 enumCodeContexts);

            Assert.AreEqual(VSConstants.S_OK, result);
            enumCodeContexts.GetCount(out uint count);
            Assert.AreEqual(numLocations, count);
            IDebugCodeContext2[] codeContexts = new IDebugCodeContext2[count];
            uint actual = 0;

            enumCodeContexts.Next(count, codeContexts, ref actual);
            Assert.AreEqual(count, actual);
            Assert.AreEqual(mockCodeContexts, codeContexts);
        }
        public void BindBreakpointFailed()
        {
            mockTarget.BreakpointCreateByLocation(TEST_FILE_NAME, LINE_NUMBER).Returns(
                (RemoteBreakpoint)null);
            MockDocumentPosition(TEST_FILE_NAME, LINE_NUMBER, COLUMN_NUMBER);

            var result = pendingBreakpoint.Bind();
            IDebugErrorBreakpoint2 breakpointError = GetBreakpointError();

            mockBreakpointManager.Received().ReportBreakpointError(
                Arg.Any <DebugBreakpointError>());
            Assert.AreNotEqual(null, breakpointError);
            Assert.AreEqual(VSConstants.S_FALSE, result);
        }
Example #3
0
        public int Bind()
        {
            if (_deleted)
            {
                return(AD7Constants.E_BP_DELETED);
            }

            switch ((enum_BP_LOCATION_TYPE)_requestInfo.bpLocation.bpLocationType)
            {
            case enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE:
                IDebugDocumentPosition2 documentPosition =
                    _marshal.GetDocumentPositionFromIntPtr(_requestInfo.bpLocation.unionmember2);
                if (documentPosition.GetFileName(out string fileName) != 0)
                {
                    SetError(enum_BP_ERROR_TYPE.BPET_GENERAL_WARNING, _noSourceFilename);
                    return(VSConstants.S_FALSE);
                }

                TEXT_POSITION[] startPosition = new TEXT_POSITION[1];
                // TODO: Check if we need the end position or not.  This might
                // matter when setting a breakpoint on a comment.  It's possible LLDB will just
                // handle this for us and we don't need to worry about the end position.
                if (documentPosition.GetRange(startPosition, null) != VSConstants.S_OK)
                {
                    SetError(enum_BP_ERROR_TYPE.BPET_GENERAL_WARNING, _noSourceLineNumber);
                    return(VSConstants.S_FALSE);
                }

                // Visual Studio uses a zero based index for line numbers, where LLDB uses a one
                // based index for line numbers.  We need to add one to the line number here to
                // convert visual studio line numbers to LLDB line numbers.
                _lldbBreakpoint =
                    _target.BreakpointCreateByLocation(fileName, startPosition[0].dwLine + 1);
                break;

            case enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET:
                IDebugFunctionPosition2 functionPosition =
                    _marshal.GetFunctionPositionFromIntPtr(_requestInfo.bpLocation.unionmember2);
                uint offset = 0;
                if (functionPosition.GetFunctionName(out string functionName) != 0)
                {
                    SetError(enum_BP_ERROR_TYPE.BPET_GENERAL_WARNING, _noFunctionName);
                    return(VSConstants.S_FALSE);
                }
                MatchCollection matches = _funcOffsetRegex.Matches(functionName);
                if (matches.Count == 1)
                {
                    functionName = matches[0].Groups["name"].Value;
                    string offsetString = matches[0].Groups["offset"].Value;
                    if (!string.IsNullOrWhiteSpace(offsetString))
                    {
                        offset = uint.Parse(offsetString);
                    }
                }

                if (offset > 0)
                {
                    BreakpointErrorPair breakpointErrorPair =
                        _target.CreateFunctionOffsetBreakpoint(functionName, offset);
                    _lldbBreakpoint = breakpointErrorPair.breakpoint;
                    if (_lldbBreakpoint == null)
                    {
                        switch (breakpointErrorPair.error)
                        {
                        case BreakpointError.NoFunctionFound:
                            SetError(enum_BP_ERROR_TYPE.BPET_GENERAL_WARNING, _noFunctionFound);
                            break;

                        case BreakpointError.NoFunctionLocation:
                            SetError(enum_BP_ERROR_TYPE.BPET_GENERAL_WARNING,
                                     _breakpointLocationNotSet);
                            break;

                        case BreakpointError.PositionNotAvailable:
                            SetError(enum_BP_ERROR_TYPE.BPET_GENERAL_WARNING,
                                     _positionNotAvailable);
                            break;

                        default:
                            SetError(enum_BP_ERROR_TYPE.BPET_GENERAL_WARNING,
                                     _positionNotAvailable);
                            break;
                        }
                        return(VSConstants.S_FALSE);
                    }
                }
                else
                {
                    _lldbBreakpoint = _target.BreakpointCreateByName(functionName);
                }
                break;

            case enum_BP_LOCATION_TYPE.BPLT_CODE_CONTEXT:
                IDebugCodeContext2 codeContext =
                    _marshal.GetCodeContextFromIntPtr(_requestInfo.bpLocation.unionmember1);
                if (codeContext == null)
                {
                    SetError(enum_BP_ERROR_TYPE.BPET_GENERAL_WARNING, _noCodeContext);
                    return(VSConstants.S_FALSE);
                }
                ulong address = codeContext.GetAddress();
                _lldbBreakpoint = _target.BreakpointCreateByAddress(address);
                break;

            case enum_BP_LOCATION_TYPE.BPLT_CODE_ADDRESS:
                string strAddress =
                    _marshal.GetStringFromIntPtr(_requestInfo.bpLocation.unionmember4);
                if (strAddress == null)
                {
                    SetError(enum_BP_ERROR_TYPE.BPET_GENERAL_WARNING, _noCodeAddress);
                    return(VSConstants.S_FALSE);
                }
                ulong address2 = Convert.ToUInt64(strAddress, 16);
                _lldbBreakpoint = _target.BreakpointCreateByAddress(address2);
                break;

            default:
                SetError(enum_BP_ERROR_TYPE.BPET_GENERAL_WARNING, _breakpointNotSupported);
                return(VSConstants.S_FALSE);
            }

            if (_lldbBreakpoint == null)
            {
                SetError(enum_BP_ERROR_TYPE.BPET_GENERAL_WARNING, _breakpointNotSet);
                return(VSConstants.S_FALSE);
            }

            UpdateLocations();
            _breakpointManager.RegisterPendingBreakpoint(Self);

            return(_boundBreakpoints.Count == 0
                ? VSConstants.S_FALSE
                : VSConstants.S_OK);
        }