/// <summary> /// Try to get a thread by it's id. /// </summary> public bool TryGet(ThreadId id, out DalvikThread thread) { lock (threadsLock) { return(threads.TryGetValue(id, out thread)); } }
/// <summary> /// Try to get a thread by it's id. /// </summary> public bool TryGet(ThreadId id, out DalvikThread thread) { lock (threadsLock) { return threads.TryGetValue(id, out thread); } }
protected override void OnThreadEnd(DalvikThread thread) { base.OnThreadEnd(thread); if (thread == Dot42Debugger.Instance.CurrentThread) { Dot42Debugger.Instance.CurrentThread = null; } }
/// <summary> /// Process the given exception event. /// </summary> protected internal virtual void OnExceptionEvent(Events.Jdwp.Exception @event, DalvikThread thread) { // Log DLog.Debug(DContext.VSDebuggerEvent, "OnExceptionEvent location: {0}", @event.Location); // Save exception in thread thread.CurrentException = @event.ExceptionObject; }
/// <summary> /// Refresh the thread list and notify all threads that's we've justed suspended the process. /// </summary> /// <param name="reason">The reason the VM is suspended</param> /// <param name="thread">The thread involved in the suspend. This can be null depending on the reason.</param> internal void OnProcessSuspended(SuspendReason reason, DalvikThread thread) { // Ask all threads to cleanup foreach (var t in Threads) { t.OnProcessSuspended(reason, (t == thread)); } // Refresh threads RefreshThreadsAsync().Wait(); }
/// <summary> /// Process the given exception event. /// </summary> protected override void OnExceptionEvent(DebuggerLib.Events.Jdwp.Exception @event, DalvikThread thread) { base.OnExceptionEvent(@event, thread); // Get information about the exception var exceptionTypeId = Debugger.ObjectReference.ReferenceTypeAsync(@event.ExceptionObject.Object).Await(DalvikProcess.VmTimeout); var exceptionType = Process.ReferenceTypeManager[exceptionTypeId]; // Prepare VS event var info = new EXCEPTION_INFO(); info.bstrExceptionName = exceptionType.GetNameAsync().Await(DalvikProcess.VmTimeout); var caught = @event.IsCaught; info.dwState = caught ? enum_EXCEPTION_STATE.EXCEPTION_STOP_FIRST_CHANCE : enum_EXCEPTION_STATE.EXCEPTION_STOP_USER_UNCAUGHT; program.GetName(out info.bstrProgramName); info.pProgram = program; info.guidType = GuidList.Guids.guidDot42DebuggerId; // Send VS event var vsEvent = new ExceptionEvent(info, info.bstrExceptionName, false); Send((DebugThread) thread, vsEvent); }
/// <summary> /// Notify listeners that we're suspended. /// </summary> /// <param name="reason">The reason the VM is suspended</param> /// <param name="thread">The thread involved in the suspend. This can be null depending on the reason.</param> /// <returns>True if the suspend is performed, false if execution is continued.</returns> protected internal virtual bool OnSuspended(SuspendReason reason, DalvikThread thread) { if ((reason == SuspendReason.SingleStep) && (thread != null)) { // Make sure we're are a location where we have a source. thread.OnProcessSuspended(reason, true); var topFrame = thread.GetCallStack().FirstOrDefault(); if (topFrame != null) { var location = topFrame.GetDocumentLocationAsync().Await(VmTimeout); if (location.Document == null) { // Not my code StepOutLastRequestAsync(); return(false); } } } ThreadManager.OnProcessSuspended(reason, thread); ReferenceTypeManager.OnProcessSuspended(reason); isSuspended = true; IsSuspendedChanged.Fire(this); return(true); }
/// <summary> /// Default ctor /// </summary> public DalvikStackFrame(FrameId id, Location location, DalvikThread thread) { Id = id; Location = location; this.thread = thread; }
/// <summary> /// Notify listeners that we're suspended. /// </summary> protected override bool OnSuspended(SuspendReason reason, DalvikThread thread) { var rc = base.OnSuspended(reason, thread); if (rc) { if (reason == SuspendReason.ProcessSuspend) { foreach (var threadx in ThreadManager.Threads) { eventCallback.Send(threadx, new ASyncBreakCompleteEvent()); } } if (reason == SuspendReason.SingleStep) { eventCallback.Send((DebugThread) thread, new StepCompleteEvent()); } } return rc; }
/// <summary> /// Notify listeners that we're suspended. /// </summary> /// <param name="reason">The reason the VM is suspended</param> /// <param name="thread">The thread involved in the suspend. This can be null depending on the reason.</param> /// <param name="request">A step request, if any.</param> /// <returns>True if the suspend is performed, false if execution is continued.</returns> protected internal virtual bool OnSuspended(SuspendReason reason, DalvikThread thread, StepRequest request = null) { if (reason == SuspendReason.SingleStep && thread != null && request != null && request.Thread != null) { // Make sure we're are a location where we have a source. thread.OnProcessSuspended(reason, true); var topFrame = thread.GetCallStack().FirstOrDefault(); if (topFrame != null) { var location = topFrame.GetDocumentLocationAsync().Await(VmTimeout); if (location.SourceCode == null) { // Not my code StepOutLastRequestAsync(request); return false; } // check if we have a valid source code position, or if this is // compiler generated code (in which case dalvik will perform single stepping) if (request.StepMode != StepMode.SingleInstruction) { if (location.SourceCode == null || location.SourceCode.IsSpecial || location.Location.Index < (ulong)location.SourceCode.Position.MethodOffset) { var stepDepth = request.StepDepth == Jdwp.StepDepth.Out ? Jdwp.StepDepth.Over : request.StepDepth; StepAsync(new StepRequest(request.Thread, stepDepth, request.StepMode)); return false; } } } } ThreadManager.OnProcessSuspended(reason, thread); ReferenceTypeManager.OnProcessSuspended(reason); isSuspended = true; IsSuspendedChanged.Fire(this); return true; }
/// <summary> /// Process the given exception event. /// </summary> protected internal virtual void OnExceptionEvent(Events.Jdwp.Exception @event, DalvikThread thread) { // Log DLog.Debug(DContext.VSDebuggerEvent, "OnExceptionEvent location: {0}", @event.Location); // Note that Process.OnSuspended() has not been called yet, and needs to be called // if the implementation does not decide to continue in spite of the exception. Debugger.Process.OnSuspended(SuspendReason.Exception, thread); // Save exception in thread if(thread != null) thread.CurrentException = @event.ExceptionObject; }
/// <summary> /// The given thread has ended. /// </summary> protected virtual void OnThreadEnd(DalvikThread thread) { }
/// <summary> /// Process the given exception event. /// </summary> protected internal virtual void OnExceptionEvent(Events.Jdwp.Exception @event, DalvikThread thread) { // Log DLog.Debug(DContext.VSDebuggerEvent, "OnExceptionEvent location: {0}", @event.Location); // Note that Process.OnSuspended() has not been called yet, and needs to be called // if the implementation does not decide to continue in spite of the exception. Debugger.Process.OnSuspended(SuspendReason.Exception, thread); // Save exception in thread if (thread != null) { thread.CurrentException = @event.ExceptionObject; } }
/// <summary> /// The given thread has ended. /// </summary> protected override void OnThreadEnd(DalvikThread thread) { var dthread = (DebugThread)thread; base.OnThreadEnd(dthread); eventCallback.Send(dthread, new ThreadDestroyEvent()); }
/// <summary> /// The given thread has been created. /// </summary> protected virtual void OnThreadCreated(DalvikThread thread) { }
private static string GetThreadId(DalvikThread thread) { return thread == null ? "(none)" : thread.Id.ToString(); }
/// <summary> /// Process the given exception event. /// </summary> protected override void OnExceptionEvent(Exception @event, DalvikThread thread) { var prev = Interlocked.CompareExchange(ref processing, @event, null); if (prev != null) { if (@event.ExceptionObject.Equals(prev.ExceptionObject) && @event.ThreadId.Equals(prev.ThreadId)) { // the same exception is reported multiple times. just ignore. Debugger.VirtualMachine.ResumeAsync(); return; } DLog.Error(DContext.VSDebuggerMessage, "Multiple exceptions in debuggee or exceptions while retrieving exception information. " +"Current Exception/Thread: {0}/{1}; previous Exception/Thread: {2}/{3} ", @event.ThreadId, @event.ExceptionObject, prev.ThreadId, prev.ExceptionObject); Debugger.VirtualMachine.ResumeAsync(); return; // This cancelling might not be neccessary any more; check this. //// I have no idea why we have to resume twice, but if we dont, the debuggee will hang. //Debugger.Process.ResumeAsync(); //if(cancelProcessing != null) // cancelProcessing.Cancel(); } cancelProcessing = new CancellationTokenSource(); var cancelToken = cancelProcessing.Token; bool wasThreadNull = thread == null; bool caught; string exceptionName = "(unknown)"; string catchingClass = "(unknown)"; string exceptionMessage = null; try { // Get information about the exception var exceptionTypeId = Debugger.ObjectReference.ReferenceTypeAsync(@event.ExceptionObject.Object) .Await(DalvikProcess.VmTimeout, cancelToken); var exceptionType = Process.ReferenceTypeManager[exceptionTypeId]; exceptionName = exceptionType.GetNameAsync() .Await(DalvikProcess.VmTimeout, cancelToken); caught = @event.IsCaught; if (!ShouldHandle(exceptionName, caught)) { DLog.Debug(DContext.VSDebuggerMessage, "not handling exception {0}", exceptionName); Debugger.VirtualMachine.ResumeAsync(); return; } if (caught && @event.CatchLocation != null) { // filter out internal exceptions, that are used for control flow. catchingClass = Process.ReferenceTypeManager[@event.CatchLocation.Class].GetNameAsync() .Await(DalvikProcess.VmTimeout, cancelToken); if (CaughtExceptionLocationExcludePattern.IsMatch(catchingClass)) { DLog.Debug(DContext.VSDebuggerMessage, "not handling exception {0}, catching class={1}", exceptionName, catchingClass); Debugger.VirtualMachine.ResumeAsync(); return; } } if (wasThreadNull) thread = Debugger.Process.ThreadManager.Threads.First(); base.OnExceptionEvent(@event, thread); exceptionMessage = GetExceptionMessageAsync(@event.ExceptionObject).Await(DalvikProcess.VmTimeout); } catch(System.Exception ex) { DLog.Error(DContext.VSDebuggerMessage, "Exception in debugger while processing exception: {0}. involved thread: {1}; exception.object={2}; exception type: {3}; ccatching class: {4}", ex.Message, GetThreadId(thread), @event.ExceptionObject.Object, exceptionName, catchingClass); Debugger.VirtualMachine.ResumeAsync(); return; } finally { Interlocked.Exchange(ref processing, null); } // Prepare VS event var info = new EXCEPTION_INFO(); info.bstrExceptionName = exceptionName; info.dwState = caught ? enum_EXCEPTION_STATE.EXCEPTION_STOP_FIRST_CHANCE : enum_EXCEPTION_STATE.EXCEPTION_STOP_USER_UNCAUGHT; program.GetName(out info.bstrProgramName); info.pProgram = program; info.guidType = GuidList.Guids.guidDot42DebuggerId; string description = info.bstrExceptionName; if (exceptionMessage != null) description += ": \"" + exceptionMessage + "\""; if (caught) description += "\n(first chance, caught by debuggee)"; else description += "\n(not caught by debugee)"; if (thread == null) { DLog.Warning(DContext.VSDebuggerEvent, "Exception without a thread: {0}. Original thread id: {1}.", exceptionName, @event.ThreadId); description += "\n The exceptions thread has already died, the VS call stack window has no meaning. The exception was raised on thread "+ @event.ThreadId; } // Send VS event var vsEvent = new ExceptionEvent(info, description, false); Send((DebugThread)thread, vsEvent); }
/// <summary> /// Refresh the thread list and notify all threads that's we've justed suspended the process. /// </summary> /// <param name="reason">The reason the VM is suspended</param> /// <param name="thread">The thread involved in the suspend. This can be null depending on the reason.</param> internal void OnProcessSuspended(SuspendReason reason, DalvikThread thread) { // Ask all threads to cleanup foreach (var t in Threads) { t.OnProcessSuspended(reason, (t == thread)); } // Refresh threads RefreshThreadsAsync().Wait(); }
/// <summary> /// The given thread has been created. /// </summary> protected virtual void OnThreadCreated(DalvikThread thread) { }
/// <summary> /// The given thread has ended. /// </summary> protected virtual void OnThreadEnd(DalvikThread thread) { }
/// <summary> /// Default ctor /// </summary> public DalvikStackFrame(FrameId id, Location location, DalvikThread thread) { Id = id; Location = location; this.thread = thread; }
/// <summary> /// Process the given exception event. /// </summary> protected internal virtual void OnExceptionEvent(Events.Jdwp.Exception @event, DalvikThread thread) { // Log DLog.Debug(DContext.VSDebuggerEvent, "OnExceptionEvent location: {0}", @event.Location); // Save exception in thread thread.CurrentException = @event.ExceptionObject; }