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); }
/// <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); }
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); }
/// <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); }
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; }
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); }