Beispiel #1
0
        public void Bind(JavaDebugProgram program, JavaDebugThread thread, IReferenceType type, IEnumerable <string> sourcePaths)
        {
            IVirtualMachine virtualMachine = program.VirtualMachine;

            IEnumerable <string> validPaths = sourcePaths.Where(i => string.Equals(Path.GetFileName(RequestLocation.DocumentPosition.GetFileName()), Path.GetFileName(i), StringComparison.OrdinalIgnoreCase));

            List <JavaDebugBoundBreakpoint> boundBreakpoints = new List <JavaDebugBoundBreakpoint>();
            List <IDebugErrorBreakpoint2>   errorBreakpoints = new List <IDebugErrorBreakpoint2>();

            foreach (var path in validPaths)
            {
                TextSpan range = RequestLocation.DocumentPosition.GetRange();
                try
                {
                    ReadOnlyCollection <ILocation> locations = type.GetLocationsOfLine(range.iStartLine + 1);
                    ILocation bindLocation = locations.OrderBy(i => i.GetCodeIndex()).FirstOrDefault();
                    if (bindLocation != null && IsFirstOnLine())
                    {
                        IEventRequestManager eventRequestManager = virtualMachine.GetEventRequestManager();

                        IBreakpointRequest eventRequest = eventRequestManager.CreateBreakpointRequest(bindLocation);
                        eventRequest.SuspendPolicy = SuspendPolicy.All;

                        JavaDebugCodeContext             codeContext     = new JavaDebugCodeContext(program, bindLocation);
                        BreakpointResolutionLocationCode location        = new BreakpointResolutionLocationCode(codeContext);
                        DebugBreakpointResolution        resolution      = new DebugBreakpointResolution(program, thread, enum_BP_TYPE.BPT_CODE, location);
                        JavaDebugBoundBreakpoint         boundBreakpoint = new JavaDebugBoundBreakpoint(this, program, eventRequest, resolution);
                        if (!_disabled)
                        {
                            boundBreakpoint.Enable(1);
                        }

                        boundBreakpoints.Add(boundBreakpoint);
                    }
                }
                catch (MissingInformationException)
                {
                }
            }

            _boundBreakpoints.AddRange(boundBreakpoints);
            if (boundBreakpoints.Count > 0)
            {
                _errorBreakpoints.Clear();
            }

            _errorBreakpoints.AddRange(errorBreakpoints);

            if (boundBreakpoints.Count > 0)
            {
                DebugEvent debugEvent = new DebugBreakpointBoundEvent(enum_EVENTATTRIBUTES.EVENT_SYNCHRONOUS, this, new EnumDebugBoundBreakpoints(boundBreakpoints));
                program.Callback.Event(DebugEngine, program.Process, program, null, debugEvent);
            }

            foreach (var errorBreakpoint in errorBreakpoints)
            {
                DebugEvent debugEvent = new DebugBreakpointErrorEvent(enum_EVENTATTRIBUTES.EVENT_ASYNCHRONOUS, errorBreakpoint);
                program.Callback.Event(DebugEngine, program.Process, program, null, debugEvent);
            }
        }
        /// <summary>
        /// Returns a code context object corresponding to a specified code location identifier.
        /// </summary>
        /// <param name="uCodeLocationId">
        /// [in] Specifies the code location identifier. See the Remarks section for the
        /// IDebugDisassemblyStream2.GetCodeLocationId method for a description of a code location identifier.
        /// </param>
        /// <param name="ppCodeContext">[out] Returns an IDebugCodeContext2 object that represents the associated code context.</param>
        /// <returns>If successful, returns S_OK; otherwise, returns an error code.</returns>
        /// <remarks>
        /// The code location identifier can be returned from a call to the IDebugDisassemblyStream2.GetCurrentLocation
        /// method and can appear in the DisassemblyData structure.
        /// 
        /// To convert a code context into a code location identifier, call the IDebugDisassemblyStream2.GetCodeLocationId
        /// method.
        /// </remarks>
        public int GetCodeContext(ulong uCodeLocationId, out IDebugCodeContext2 ppCodeContext)
        {
            ppCodeContext = null;
            if (uCodeLocationId > (uint)_bytecode.Length)
                return VSConstants.E_INVALIDARG;

            ppCodeContext = new JavaDebugCodeContext(_executionContext.Program, _executionContext.Location.GetMethod().GetLocationOfCodeIndex((long)uCodeLocationId));
            return VSConstants.S_OK;
        }
        /// <summary>
        /// Gets the code context for this stack frame.
        /// </summary>
        /// <param name="ppCodeCxt">Returns an IDebugCodeContext2 object that represents the current instruction pointer in this stack frame.</param>
        /// <returns>If successful, returns S_OK; otherwise, returns an error code.</returns>
        public int GetCodeContext(out IDebugCodeContext2 ppCodeCxt)
        {
            if (_nativeMethod)
            {
                ppCodeCxt = null;
                return(AD7Constants.E_NO_CODE_CONTEXT);
            }

            ppCodeCxt = new JavaDebugCodeContext(_thread.Program, _stackFrame.GetLocation());
            return(VSConstants.S_OK);
        }
Beispiel #4
0
        /// <summary>
        /// Returns a code context object corresponding to a specified code location identifier.
        /// </summary>
        /// <param name="uCodeLocationId">
        /// [in] Specifies the code location identifier. See the Remarks section for the
        /// IDebugDisassemblyStream2.GetCodeLocationId method for a description of a code location identifier.
        /// </param>
        /// <param name="ppCodeContext">[out] Returns an IDebugCodeContext2 object that represents the associated code context.</param>
        /// <returns>If successful, returns S_OK; otherwise, returns an error code.</returns>
        /// <remarks>
        /// The code location identifier can be returned from a call to the IDebugDisassemblyStream2.GetCurrentLocation
        /// method and can appear in the DisassemblyData structure.
        ///
        /// To convert a code context into a code location identifier, call the IDebugDisassemblyStream2.GetCodeLocationId
        /// method.
        /// </remarks>
        public int GetCodeContext(ulong uCodeLocationId, out IDebugCodeContext2 ppCodeContext)
        {
            ppCodeContext = null;
            if (uCodeLocationId > (uint)_bytecode.Length)
            {
                return(VSConstants.E_INVALIDARG);
            }

            ppCodeContext = new JavaDebugCodeContext(_executionContext.Program, _executionContext.Location.GetMethod().GetLocationOfCodeIndex((long)uCodeLocationId));
            return(VSConstants.S_OK);
        }
Beispiel #5
0
        public JavaDebugDisassemblyStream(JavaDebugCodeContext executionContext)
        {
            Contract.Requires <ArgumentNullException>(executionContext != null, "executionContext");

            _executionContext   = executionContext;
            _bytecode           = _executionContext.Location.GetMethod().GetBytecodes();
            _disassembledMethod = BytecodeDisassembler.Disassemble(_bytecode);

            var constantPool   = executionContext.Location.GetDeclaringType().GetConstantPool();
            var exceptionTable = executionContext.Location.GetMethod().GetExceptionTable();

            _evaluationStackDepths = BytecodeDisassembler.GetEvaluationStackDepths(_disassembledMethod, constantPool, exceptionTable);
        }
        public int CanSetNextStatement(IDebugStackFrame2 pStackFrame, IDebugCodeContext2 pCodeContext)
        {
#if HIDE_THREADS
            return(VSConstants.S_FALSE);
#endif

            JavaDebugStackFrame  stackFrame  = pStackFrame as JavaDebugStackFrame;
            JavaDebugCodeContext codeContext = pCodeContext as JavaDebugCodeContext;
            if (stackFrame == null || codeContext == null)
            {
                return(VSConstants.E_INVALIDARG);
            }

            // TODO: implement Set Next Statement
            return(VSConstants.S_FALSE);
        }
Beispiel #7
0
        /// <summary>
        /// Returns a code location identifier for a particular code context.
        /// </summary>
        /// <param name="pCodeContext">[in] An IDebugCodeContext2 object to be converted to an identifier.</param>
        /// <param name="puCodeLocationId">[out] Returns the code location identifier. See Remarks.</param>
        /// <returns>
        /// If successful, returns S_OK; otherwise, returns an error code. Returns E_CODE_CONTEXT_OUT_OF_SCOPE if
        /// the code context is valid but outside the scope.
        /// </returns>
        /// <remarks>
        /// The code location identifier is specific to the debug engine (DE) supporting the disassembly. This
        /// location identifier is used internally by the DE to track positions in the code and is typically an
        /// address or offset of some kind. The only requirement is that if the code context of one location is
        /// less than the code context of another location, then the corresponding code location identifier of
        /// the first code context must also be less than the code location identifier of the second code context.
        ///
        /// To retrieve the code context of a code location identifier, call the IDebugDisassemblyStream2.GetCodeContext method.
        /// </remarks>
        public int GetCodeLocationId(IDebugCodeContext2 pCodeContext, out ulong puCodeLocationId)
        {
            puCodeLocationId = 0;

            JavaDebugCodeContext codeContext = pCodeContext as JavaDebugCodeContext;

            if (codeContext == null)
            {
                return(VSConstants.E_INVALIDARG);
            }
            else if (!codeContext.Location.GetMethod().Equals(this._executionContext.Location.GetMethod()))
            {
                return(AD7Constants.E_CODE_CONTEXT_OUT_OF_SCOPE);
            }

            puCodeLocationId = checked ((ulong)codeContext.Location.GetCodeIndex());
            return(VSConstants.S_OK);
        }
        public int GetDisassemblyStream(enum_DISASSEMBLY_STREAM_SCOPE dwScope, IDebugCodeContext2 pCodeContext, out IDebugDisassemblyStream2 ppDisassemblyStream)
        {
            ppDisassemblyStream = null;

            if (pCodeContext == null)
            {
                throw new ArgumentNullException("pCodeContext");
            }

            JavaDebugCodeContext codeContext = pCodeContext as JavaDebugCodeContext;

            if (codeContext == null)
            {
                return(VSConstants.E_INVALIDARG);
            }

            ppDisassemblyStream = new JavaDebugDisassemblyStream(codeContext);
            return(VSConstants.S_OK);
        }
        public JavaDebugDisassemblyStream(JavaDebugCodeContext executionContext)
        {
            Contract.Requires<ArgumentNullException>(executionContext != null, "executionContext");

            _executionContext = executionContext;
            _bytecode = _executionContext.Location.GetMethod().GetBytecodes();
            _disassembledMethod = BytecodeDisassembler.Disassemble(_bytecode);

            var constantPool = executionContext.Location.GetDeclaringType().GetConstantPool();
            ReadOnlyCollection<ExceptionTableEntry> exceptionTable;
            try
            {
                exceptionTable = executionContext.Location.GetMethod().GetExceptionTable();
            }
            catch (DebuggerException)
            {
                exceptionTable = new ReadOnlyCollection<ExceptionTableEntry>(new ExceptionTableEntry[0]);
            }

            _evaluationStackDepths = BytecodeDisassembler.GetEvaluationStackDepths(_disassembledMethod, constantPool, exceptionTable);
        }
Beispiel #10
0
        public JavaDebugDisassemblyStream(JavaDebugCodeContext executionContext)
        {
            Contract.Requires <ArgumentNullException>(executionContext != null, "executionContext");

            _executionContext   = executionContext;
            _bytecode           = _executionContext.Location.GetMethod().GetBytecodes();
            _disassembledMethod = BytecodeDisassembler.Disassemble(_bytecode);

            var constantPool = executionContext.Location.GetDeclaringType().GetConstantPool();
            ReadOnlyCollection <ExceptionTableEntry> exceptionTable;

            try
            {
                exceptionTable = executionContext.Location.GetMethod().GetExceptionTable();
            }
            catch (DebuggerException)
            {
                exceptionTable = new ReadOnlyCollection <ExceptionTableEntry>(new ExceptionTableEntry[0]);
            }

            _evaluationStackDepths = BytecodeDisassembler.GetEvaluationStackDepths(_disassembledMethod, constantPool, exceptionTable);
        }
        private void AsyncBindImpl()
        {
            UnbindAllBreakpoints(enum_BP_UNBOUND_REASON.BPUR_BREAKPOINT_REBIND);

            string fileName = RequestLocation.DocumentPosition.GetFileName();
            int lineNumber = RequestLocation.DocumentPosition.GetRange().iStartLine + 1;
            bool errorNotFirstOnLine = false;

            List<JavaDebugBoundBreakpoint> boundBreakpoints = new List<JavaDebugBoundBreakpoint>();
            IEnumerable<JavaDebugProgram> programs = DebugEngine.Programs.ToArray();
            foreach (var program in programs)
            {
                if (!program.IsLoaded)
                    continue;

                IVirtualMachine virtualMachine = program.VirtualMachine;
                ReadOnlyCollection<IReferenceType> classes = virtualMachine.GetAllClasses();
                foreach (var @class in classes)
                {
                    if ([email protected]())
                        continue;

                    ReadOnlyCollection<ILocation> locations = @class.GetLocationsOfLine(@class.GetDefaultStratum(), Path.GetFileName(fileName), lineNumber);
                    ILocation bindLocation = locations.OrderBy(i => i.GetCodeIndex()).FirstOrDefault();
                    if (bindLocation != null)
                    {
                        if (!IsFirstOnLine())
                        {
                            errorNotFirstOnLine = true;
                            break;
                        }

                        IEventRequestManager eventRequestManager = virtualMachine.GetEventRequestManager();
                        IBreakpointRequest eventRequest = eventRequestManager.CreateBreakpointRequest(bindLocation);
                        eventRequest.SuspendPolicy = SuspendPolicy.All;

                        JavaDebugCodeContext codeContext = new JavaDebugCodeContext(program, bindLocation);
                        BreakpointResolutionLocationCode location = new BreakpointResolutionLocationCode(codeContext);
                        DebugBreakpointResolution resolution = new DebugBreakpointResolution(program, null, enum_BP_TYPE.BPT_CODE, location);
                        JavaDebugBoundBreakpoint boundBreakpoint = new JavaDebugBoundBreakpoint(this, program, eventRequest, resolution);
                        if (!_disabled)
                            boundBreakpoint.Enable(1);

                        boundBreakpoints.Add(boundBreakpoint);
                    }
                }

                if (errorNotFirstOnLine)
                    break;
            }

            _boundBreakpoints.AddRange(boundBreakpoints);

            if (_boundBreakpoints.Count == 0)
            {
                foreach (var program in programs)
                {
                    JavaDebugThread thread = null;
                    IDebugCodeContext2 codeContext = new DebugDocumentCodeContext(RequestLocation.DocumentPosition);
                    BreakpointResolutionLocation location = new BreakpointResolutionLocationCode(codeContext);
                    string message = "The class is not yet loaded, or the location is not present in the debug symbols for this document.";
                    if (errorNotFirstOnLine)
                        message = "Only breakpoints on the first statement on a line can be bound at this time.";

                    DebugErrorBreakpointResolution resolution = new DebugErrorBreakpointResolution(program, thread, enum_BP_TYPE.BPT_CODE, location, enum_BP_ERROR_TYPE.BPET_GENERAL_WARNING, message);
                    DebugErrorBreakpoint errorBreakpoint = new DebugErrorBreakpoint(this, resolution);
                    _errorBreakpoints.Add(errorBreakpoint);

                    DebugEvent debugEvent = new DebugBreakpointErrorEvent(enum_EVENTATTRIBUTES.EVENT_ASYNCHRONOUS, errorBreakpoint);
                    program.Callback.Event(DebugEngine, program.Process, program, null, debugEvent);
                }
            }

            foreach (var group in boundBreakpoints.GroupBy(i => i.Program))
            {
                DebugEvent debugEvent = new DebugBreakpointBoundEvent(enum_EVENTATTRIBUTES.EVENT_ASYNCHRONOUS, this, new EnumDebugBoundBreakpoints(group));
                group.Key.Callback.Event(DebugEngine, group.Key.Process, group.Key, null, debugEvent);
            }
        }
        public void Bind(JavaDebugProgram program, JavaDebugThread thread, IReferenceType type, IEnumerable<string> sourcePaths)
        {
            IVirtualMachine virtualMachine = program.VirtualMachine;

            IEnumerable<string> validPaths = sourcePaths.Where(i => string.Equals(Path.GetFileName(RequestLocation.DocumentPosition.GetFileName()), Path.GetFileName(i), StringComparison.OrdinalIgnoreCase));

            List<JavaDebugBoundBreakpoint> boundBreakpoints = new List<JavaDebugBoundBreakpoint>();
            List<IDebugErrorBreakpoint2> errorBreakpoints = new List<IDebugErrorBreakpoint2>();
            foreach (var path in validPaths)
            {
                TextSpan range = RequestLocation.DocumentPosition.GetRange();
                try
                {
                    ReadOnlyCollection<ILocation> locations = type.GetLocationsOfLine(range.iStartLine + 1);
                    ILocation bindLocation = locations.OrderBy(i => i.GetCodeIndex()).FirstOrDefault();
                    if (bindLocation != null && IsFirstOnLine())
                    {
                        IEventRequestManager eventRequestManager = virtualMachine.GetEventRequestManager();

                        IBreakpointRequest eventRequest = eventRequestManager.CreateBreakpointRequest(bindLocation);
                        eventRequest.SuspendPolicy = SuspendPolicy.All;

                        JavaDebugCodeContext codeContext = new JavaDebugCodeContext(program, bindLocation);
                        BreakpointResolutionLocationCode location = new BreakpointResolutionLocationCode(codeContext);
                        DebugBreakpointResolution resolution = new DebugBreakpointResolution(program, thread, enum_BP_TYPE.BPT_CODE, location);
                        JavaDebugBoundBreakpoint boundBreakpoint = new JavaDebugBoundBreakpoint(this, program, eventRequest, resolution);
                        if (!_disabled)
                            boundBreakpoint.Enable(1);

                        boundBreakpoints.Add(boundBreakpoint);
                    }
                }
                catch (MissingInformationException)
                {
                }
            }

            _boundBreakpoints.AddRange(boundBreakpoints);
            if (boundBreakpoints.Count > 0)
            {
                _errorBreakpoints.Clear();
            }

            _errorBreakpoints.AddRange(errorBreakpoints);

            if (boundBreakpoints.Count > 0)
            {
                DebugEvent debugEvent = new DebugBreakpointBoundEvent(enum_EVENTATTRIBUTES.EVENT_SYNCHRONOUS, this, new EnumDebugBoundBreakpoints(boundBreakpoints));
                program.Callback.Event(DebugEngine, program.Process, program, null, debugEvent);
            }

            foreach (var errorBreakpoint in errorBreakpoints)
            {
                DebugEvent debugEvent = new DebugBreakpointErrorEvent(enum_EVENTATTRIBUTES.EVENT_ASYNCHRONOUS, errorBreakpoint);
                program.Callback.Event(DebugEngine, program.Process, program, null, debugEvent);
            }
        }
        /// <summary>
        /// Compares the memory context to each context in the given array in the manner indicated by compare flags, returning an index of the first context that matches.
        /// </summary>
        /// <param name="Compare">[in] A value from the CONTEXT_COMPARE enumeration that determines the type of comparison.</param>
        /// <param name="rgpMemoryContextSet">[in] An array of references to the IDebugMemoryContext2 objects to compare against.</param>
        /// <param name="dwMemoryContextSetLen">[in] The number of contexts in the rgpMemoryContextSet array.</param>
        /// <param name="pdwMemoryContext">[out] Returns the index of the first memory context that satisfies the comparison.</param>
        /// <returns>If successful, returns S_OK; otherwise, returns an error code. Returns E_COMPARE_CANNOT_COMPARE if the two contexts cannot be compared.</returns>
        /// <remarks>
        /// A debug engine (DE) does not have to support all types of comparisons, but it must support at least CONTEXT_EQUAL, CONTEXT_LESS_THAN, CONTEXT_GREATER_THAN and CONTEXT_SAME_SCOPE.
        /// </remarks>
        public int Compare(enum_CONTEXT_COMPARE Compare, IDebugMemoryContext2[] rgpMemoryContextSet, uint dwMemoryContextSetLen, out uint pdwMemoryContext)
        {
            if (rgpMemoryContextSet == null)
                throw new ArgumentNullException("rgpMemoryContextSet");
            if (rgpMemoryContextSet.Length < dwMemoryContextSetLen)
                throw new ArgumentException();

            pdwMemoryContext = 0;

            bool relational = false;
            switch (Compare)
            {
            case enum_CONTEXT_COMPARE.CONTEXT_GREATER_THAN:
            case enum_CONTEXT_COMPARE.CONTEXT_GREATER_THAN_OR_EQUAL:
            case enum_CONTEXT_COMPARE.CONTEXT_LESS_THAN:
            case enum_CONTEXT_COMPARE.CONTEXT_LESS_THAN_OR_EQUAL:
                relational = true;
                break;
            }

            JavaDebugCodeContext[] contexts = new JavaDebugCodeContext[dwMemoryContextSetLen];
            for (int i = 0; i < contexts.Length; i++)
            {
                if (rgpMemoryContextSet[i] == null)
                    return VSConstants.E_INVALIDARG;

                contexts[i] = rgpMemoryContextSet[i] as JavaDebugCodeContext;
                if (contexts[i] == null)
                    return AD7Constants.E_COMPARE_CANNOT_COMPARE;

                // relational tests only work if the contexts are in the same scope
                if (relational && !this.Location.GetMethod().Equals(contexts[i].Location.GetMethod()))
                    return AD7Constants.E_COMPARE_CANNOT_COMPARE;
            }

            int index;

            switch (Compare)
            {
            case enum_CONTEXT_COMPARE.CONTEXT_EQUAL:
                index = Array.FindIndex(contexts, i => this.Location.Equals(i.Location));
                break;

            case enum_CONTEXT_COMPARE.CONTEXT_GREATER_THAN:
                index = Array.FindIndex(contexts, i => i.Location.GetCodeIndex() > this.Location.GetCodeIndex());
                break;

            case enum_CONTEXT_COMPARE.CONTEXT_GREATER_THAN_OR_EQUAL:
                index = Array.FindIndex(contexts, i => i.Location.GetCodeIndex() >= this.Location.GetCodeIndex());
                break;

            case enum_CONTEXT_COMPARE.CONTEXT_LESS_THAN:
                index = Array.FindIndex(contexts, i => i.Location.GetCodeIndex() < this.Location.GetCodeIndex());
                break;

            case enum_CONTEXT_COMPARE.CONTEXT_LESS_THAN_OR_EQUAL:
                index = Array.FindIndex(contexts, i => i.Location.GetCodeIndex() <= this.Location.GetCodeIndex());
                break;

            case enum_CONTEXT_COMPARE.CONTEXT_SAME_FUNCTION:
                index = Array.FindIndex(contexts, i => this.Location.GetMethod().Equals(i.Location.GetMethod()));
                break;

            case enum_CONTEXT_COMPARE.CONTEXT_SAME_MODULE:
                throw new NotImplementedException();

            case enum_CONTEXT_COMPARE.CONTEXT_SAME_PROCESS:
                index = Array.FindIndex(contexts, i => this.Program.Process == i.Program.Process);
                break;

            case enum_CONTEXT_COMPARE.CONTEXT_SAME_SCOPE:
                index = Array.FindIndex(contexts, i => this.Location.GetMethod().Equals(i.Location.GetMethod()));
                break;

            default:
                throw new ArgumentException();
            }

            if (index < 0)
            {
                return VSConstants.E_FAIL;
            }

            pdwMemoryContext = (uint)index;
            return VSConstants.S_OK;
        }
Beispiel #14
0
        private void AsyncBindImpl()
        {
            UnbindAllBreakpoints(enum_BP_UNBOUND_REASON.BPUR_BREAKPOINT_REBIND);

            string fileName            = RequestLocation.DocumentPosition.GetFileName();
            int    lineNumber          = RequestLocation.DocumentPosition.GetRange().iStartLine + 1;
            bool   errorNotFirstOnLine = false;

            List <JavaDebugBoundBreakpoint> boundBreakpoints = new List <JavaDebugBoundBreakpoint>();
            IEnumerable <JavaDebugProgram>  programs         = DebugEngine.Programs.ToArray();

            foreach (var program in programs)
            {
                if (!program.IsLoaded)
                {
                    continue;
                }

                IVirtualMachine virtualMachine = program.VirtualMachine;
                ReadOnlyCollection <IReferenceType> classes = virtualMachine.GetAllClasses();
                foreach (var @class in classes)
                {
                    if ([email protected]())
                    {
                        continue;
                    }

                    ReadOnlyCollection <ILocation> locations = @class.GetLocationsOfLine(@class.GetDefaultStratum(), Path.GetFileName(fileName), lineNumber);
                    ILocation bindLocation = locations.OrderBy(i => i.GetCodeIndex()).FirstOrDefault();
                    if (bindLocation != null)
                    {
                        if (!IsFirstOnLine())
                        {
                            errorNotFirstOnLine = true;
                            break;
                        }

                        IEventRequestManager eventRequestManager = virtualMachine.GetEventRequestManager();
                        IBreakpointRequest   eventRequest        = eventRequestManager.CreateBreakpointRequest(bindLocation);
                        eventRequest.SuspendPolicy = SuspendPolicy.All;

                        JavaDebugCodeContext             codeContext     = new JavaDebugCodeContext(program, bindLocation);
                        BreakpointResolutionLocationCode location        = new BreakpointResolutionLocationCode(codeContext);
                        DebugBreakpointResolution        resolution      = new DebugBreakpointResolution(program, null, enum_BP_TYPE.BPT_CODE, location);
                        JavaDebugBoundBreakpoint         boundBreakpoint = new JavaDebugBoundBreakpoint(this, program, eventRequest, resolution);
                        if (!_disabled)
                        {
                            boundBreakpoint.Enable(1);
                        }

                        boundBreakpoints.Add(boundBreakpoint);
                    }
                }

                if (errorNotFirstOnLine)
                {
                    break;
                }
            }

            _boundBreakpoints.AddRange(boundBreakpoints);

            if (_boundBreakpoints.Count == 0)
            {
                foreach (var program in programs)
                {
                    JavaDebugThread              thread      = null;
                    IDebugCodeContext2           codeContext = new DebugDocumentCodeContext(RequestLocation.DocumentPosition);
                    BreakpointResolutionLocation location    = new BreakpointResolutionLocationCode(codeContext);
                    string message = "The class is not yet loaded, or the location is not present in the debug symbols for this document.";
                    if (errorNotFirstOnLine)
                    {
                        message = "Only breakpoints on the first statement on a line can be bound at this time.";
                    }

                    DebugErrorBreakpointResolution resolution      = new DebugErrorBreakpointResolution(program, thread, enum_BP_TYPE.BPT_CODE, location, enum_BP_ERROR_TYPE.BPET_GENERAL_WARNING, message);
                    DebugErrorBreakpoint           errorBreakpoint = new DebugErrorBreakpoint(this, resolution);
                    _errorBreakpoints.Add(errorBreakpoint);

                    DebugEvent debugEvent = new DebugBreakpointErrorEvent(enum_EVENTATTRIBUTES.EVENT_ASYNCHRONOUS, errorBreakpoint);
                    program.Callback.Event(DebugEngine, program.Process, program, null, debugEvent);
                }
            }

            foreach (var group in boundBreakpoints.GroupBy(i => i.Program))
            {
                DebugEvent debugEvent = new DebugBreakpointBoundEvent(enum_EVENTATTRIBUTES.EVENT_ASYNCHRONOUS, this, new EnumDebugBoundBreakpoints(group));
                group.Key.Callback.Event(DebugEngine, group.Key.Process, group.Key, null, debugEvent);
            }
        }
        /// <summary>
        /// Gets the code context for this stack frame.
        /// </summary>
        /// <param name="ppCodeCxt">Returns an IDebugCodeContext2 object that represents the current instruction pointer in this stack frame.</param>
        /// <returns>If successful, returns S_OK; otherwise, returns an error code.</returns>
        public int GetCodeContext(out IDebugCodeContext2 ppCodeCxt)
        {
            if (_nativeMethod)
            {
                ppCodeCxt = null;
                return AD7Constants.E_NO_CODE_CONTEXT;
            }

            ppCodeCxt = new JavaDebugCodeContext(_thread.Program, _stackFrame.GetLocation());
            return VSConstants.S_OK;
        }
        /// <summary>
        /// Compares the memory context to each context in the given array in the manner indicated by compare flags, returning an index of the first context that matches.
        /// </summary>
        /// <param name="Compare">[in] A value from the CONTEXT_COMPARE enumeration that determines the type of comparison.</param>
        /// <param name="rgpMemoryContextSet">[in] An array of references to the IDebugMemoryContext2 objects to compare against.</param>
        /// <param name="dwMemoryContextSetLen">[in] The number of contexts in the rgpMemoryContextSet array.</param>
        /// <param name="pdwMemoryContext">[out] Returns the index of the first memory context that satisfies the comparison.</param>
        /// <returns>If successful, returns S_OK; otherwise, returns an error code. Returns E_COMPARE_CANNOT_COMPARE if the two contexts cannot be compared.</returns>
        /// <remarks>
        /// A debug engine (DE) does not have to support all types of comparisons, but it must support at least CONTEXT_EQUAL, CONTEXT_LESS_THAN, CONTEXT_GREATER_THAN and CONTEXT_SAME_SCOPE.
        /// </remarks>
        public int Compare(enum_CONTEXT_COMPARE Compare, IDebugMemoryContext2[] rgpMemoryContextSet, uint dwMemoryContextSetLen, out uint pdwMemoryContext)
        {
            if (rgpMemoryContextSet == null)
            {
                throw new ArgumentNullException("rgpMemoryContextSet");
            }
            if (rgpMemoryContextSet.Length < dwMemoryContextSetLen)
            {
                throw new ArgumentException();
            }

            pdwMemoryContext = 0;

            bool relational = false;

            switch (Compare)
            {
            case enum_CONTEXT_COMPARE.CONTEXT_GREATER_THAN:
            case enum_CONTEXT_COMPARE.CONTEXT_GREATER_THAN_OR_EQUAL:
            case enum_CONTEXT_COMPARE.CONTEXT_LESS_THAN:
            case enum_CONTEXT_COMPARE.CONTEXT_LESS_THAN_OR_EQUAL:
                relational = true;
                break;
            }

            JavaDebugCodeContext[] contexts = new JavaDebugCodeContext[dwMemoryContextSetLen];
            for (int i = 0; i < contexts.Length; i++)
            {
                if (rgpMemoryContextSet[i] == null)
                {
                    return(VSConstants.E_INVALIDARG);
                }

                contexts[i] = rgpMemoryContextSet[i] as JavaDebugCodeContext;
                if (contexts[i] == null)
                {
                    return(AD7Constants.E_COMPARE_CANNOT_COMPARE);
                }

                // relational tests only work if the contexts are in the same scope
                if (relational && !this.Location.GetMethod().Equals(contexts[i].Location.GetMethod()))
                {
                    return(AD7Constants.E_COMPARE_CANNOT_COMPARE);
                }
            }

            int index;

            switch (Compare)
            {
            case enum_CONTEXT_COMPARE.CONTEXT_EQUAL:
                index = Array.FindIndex(contexts, i => this.Location.Equals(i.Location));
                break;

            case enum_CONTEXT_COMPARE.CONTEXT_GREATER_THAN:
                index = Array.FindIndex(contexts, i => i.Location.GetCodeIndex() > this.Location.GetCodeIndex());
                break;

            case enum_CONTEXT_COMPARE.CONTEXT_GREATER_THAN_OR_EQUAL:
                index = Array.FindIndex(contexts, i => i.Location.GetCodeIndex() >= this.Location.GetCodeIndex());
                break;

            case enum_CONTEXT_COMPARE.CONTEXT_LESS_THAN:
                index = Array.FindIndex(contexts, i => i.Location.GetCodeIndex() < this.Location.GetCodeIndex());
                break;

            case enum_CONTEXT_COMPARE.CONTEXT_LESS_THAN_OR_EQUAL:
                index = Array.FindIndex(contexts, i => i.Location.GetCodeIndex() <= this.Location.GetCodeIndex());
                break;

            case enum_CONTEXT_COMPARE.CONTEXT_SAME_FUNCTION:
                index = Array.FindIndex(contexts, i => this.Location.GetMethod().Equals(i.Location.GetMethod()));
                break;

            case enum_CONTEXT_COMPARE.CONTEXT_SAME_MODULE:
                throw new NotImplementedException();

            case enum_CONTEXT_COMPARE.CONTEXT_SAME_PROCESS:
                index = Array.FindIndex(contexts, i => this.Program.Process == i.Program.Process);
                break;

            case enum_CONTEXT_COMPARE.CONTEXT_SAME_SCOPE:
                index = Array.FindIndex(contexts, i => this.Location.GetMethod().Equals(i.Location.GetMethod()));
                break;

            default:
                throw new ArgumentException();
            }

            if (index < 0)
            {
                return(VSConstants.E_FAIL);
            }

            pdwMemoryContext = (uint)index;
            return(VSConstants.S_OK);
        }