public void BindFunctionBreakpointWithOffset()
        {
            SetBreakpointType(enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET);
            pendingBreakpoint = debugPendingBreakpointFactory.Create(
                mockBreakpointManager, mockProgram, mockBreakpointRequest, mockTarget,
                mockMarshal);

            MockFunctionBreakpoint(1);
            MockFunctionPosition(TEST_FUNCTION_NAME_WITH_OFFSET);

            uint offset = 10;

            mockTarget.CreateFunctionOffsetBreakpoint(TEST_FUNCTION_NAME, offset).Returns(
                new BreakpointErrorPair(mockLldbBreakpoint, BreakpointError.Success));

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

            Assert.AreEqual(1, boundBreakpoints.Count);
            mockBreakpointManager.Received().RegisterPendingBreakpoint(pendingBreakpoint);

            Assert.AreEqual(null, breakpointError);
            Assert.AreEqual(VSConstants.S_OK, result);
        }
        public void BindFunctionBreakpointWithOffset()
        {
            MockFunctionBreakpoint(1);

            uint startPosition = 75u;
            uint endPosition   = 100u;
            uint offset        = 10;
            uint newPosition   = startPosition + offset + 1;

            string path = Path.Combine(TEST_DIRECTORY, TEST_FILENAME);

            MockFunctionData(startPosition, endPosition, TEST_DIRECTORY, TEST_FILENAME);

            mockTarget.BreakpointCreateByLocation(path, newPosition)
            .Returns(mockBreakpoint);

            var testBreakpoint = remoteTarget.CreateFunctionOffsetBreakpoint(TEST_FUNCTION_NAME,
                                                                             offset);

            mockTarget.Received().BreakpointDelete(EXPECTED_ID);
            mockTarget.Received().BreakpointCreateByLocation(path, newPosition);
            Assert.AreEqual(mockBreakpoint.GetId(), remoteBreakpoint.GetId());
        }
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);
        }