public bool ProcessEvent(Inferior.ChildEvent cevent) { Report.Debug (DebugFlags.EventLoop, "{0} received event {1}", this, cevent); if (killed) { if (cevent.Type == Inferior.ChildEventType.CHILD_INTERRUPTED) { inferior.Continue (); return true; } else if (cevent.Type != Inferior.ChildEventType.CHILD_EXITED) { Report.Debug (DebugFlags.EventLoop, "{0} received event {1} when already killed", this, cevent); return true; } } if ((cevent.Type == Inferior.ChildEventType.CHILD_EXITED) || (cevent.Type == Inferior.ChildEventType.CHILD_SIGNALED)) { Report.Debug (DebugFlags.EventLoop, "{0} received {1} while running {2}", this, cevent, current_operation); // we can't remove the breakpoint anymore after // the target exited, but we need to clear this id. temp_breakpoint = null; dead = true; } else { string frame_text = ""; Inferior.StackFrame iframe = inferior.GetCurrentFrame (true); if (iframe != null) frame_text = " at " + iframe.Address.ToString (); string running_text; if (HasThreadLock) running_text = String.Format ("being thread-locked ({0})", thread_lock); else running_text = String.Format ("running {0}", current_operation); string event_text; if (cevent.Type == Inferior.ChildEventType.CHILD_NOTIFICATION) event_text = String.Format ("notification {0} ({1})", cevent, (NotificationType) cevent.Argument); else event_text = "event " + cevent.ToString (); Report.Debug (DebugFlags.EventLoop, "{0} received {1}{2} while {3}", this, event_text, frame_text, running_text); if (HasThreadLock) { thread_lock.SetStopEvent (cevent); return false; } } if (Process.IsAttached && !attach_initialized) { attach_initialized = true; if (cevent.Type == Inferior.ChildEventType.CHILD_INTERRUPTED) cevent = new Inferior.ChildEvent (Inferior.ChildEventType.CHILD_STOPPED, 0, 0, 0); } bool resume_target; if (manager.HandleChildEvent (this, inferior, ref cevent, out resume_target)) { Report.Debug (DebugFlags.EventLoop, "{0} done handling event: {1}{2}{3}{4}", this, cevent, resume_target ? " resume-target" : "" , stop_requested ? " stop-requested" : "", HasThreadLock ? " thread-lock" : ""); if (stop_requested) { OperationInterrupted (); } else if (resume_target) { if (!current_operation.ResumeOperation ()) inferior.Continue (); } return true; } Inferior.ChildEventType message = cevent.Type; int arg = (int) cevent.Argument; switch (message) { case Inferior.ChildEventType.CHILD_INTERRUPTED: if (current_operation != null) OperationInterrupted (); return true; case Inferior.ChildEventType.CHILD_SIGNALED: if (killed) OperationCompleted (new TargetEventArgs (TargetEventType.TargetExited, 0)); else OperationCompleted (new TargetEventArgs (TargetEventType.TargetSignaled, arg)); return true; case Inferior.ChildEventType.INTERNAL_ERROR: frame_changed (inferior.CurrentFrame, null); Report.Error ("{0} got {1} at {2} while executing {3}", this, message, inferior.CurrentFrame, current_operation); OperationCompleted (new TargetEventArgs (TargetEventType.TargetSignaled, -1)); return true; case Inferior.ChildEventType.CHILD_EXITED: OperationCompleted (new TargetEventArgs (TargetEventType.TargetExited, arg)); return true; case Inferior.ChildEventType.CHILD_CALLBACK_COMPLETED: frame_changed (inferior.CurrentFrame, null); OperationCompleted (new TargetEventArgs (TargetEventType.TargetStopped, 0, current_frame)); return true; case Inferior.ChildEventType.RUNTIME_INVOKE_DONE: OperationRuntimeInvoke rti = rti_stack.Pop (); if (rti.ID != cevent.Argument) throw new InternalError ("{0} got unknown RUNTIME_INVOKE_DONE: {1} {2}", this, rti.ID, cevent); frame_changed (inferior.CurrentFrame, null); rti.Completed (cevent.Data1, cevent.Data2); if (rti.IsSuspended) { InterruptibleOperation io = nested_break_stack.Pop (); if (io != rti) throw new InternalError ("{0} unexpected item on nested break state stack: {1}", this, io); process.Debugger.OnLeaveNestedBreakState (thread); } if (current_operation != rti) { OperationCommandResult result = current_operation.Result as OperationCommandResult; if (result != null) result.Completed (this, null); current_operation.Result.Completed (); } current_operation = rti; TargetEventArgs args = rti.OperationCompleted (current_frame, false); OperationCompleted (args); return true; } if (stop_requested) { switch (message) { case Inferior.ChildEventType.CHILD_STOPPED: case Inferior.ChildEventType.CHILD_CALLBACK: case Inferior.ChildEventType.CHILD_HIT_BREAKPOINT: OperationInterrupted (); return true; case Inferior.ChildEventType.UNHANDLED_EXCEPTION: case Inferior.ChildEventType.THROW_EXCEPTION: case Inferior.ChildEventType.HANDLE_EXCEPTION: case Inferior.ChildEventType.CHILD_NOTIFICATION: inferior.RestartNotification (); OperationInterrupted (); return true; default: OperationInterrupted (); return false; } } DoProcessEvent (cevent); return true; }
void remove_temporary_breakpoint() { if (temp_breakpoint != null) { Report.Debug (DebugFlags.SSE, "{0} removing temp breakpoint {1}", this, temp_breakpoint); inferior.RemoveBreakpoint (temp_breakpoint.ID); temp_breakpoint = null; } }
void remove_lmf_breakpoint() { if (lmf_breakpoint == null) return; /* * We reused an already existing single-stepping breakpoint at the requested location. */ if (lmf_breakpoint.Breakpoint == lmf_breakpoint.StolenBreakpoint) return; inferior.RemoveBreakpoint (lmf_breakpoint.Breakpoint.ID); /* * We stole the single-stepping breakpoint -> restore it here. */ if (lmf_breakpoint.StolenBreakpoint != null) { int dr_index; TargetAddress address = lmf_breakpoint.StolenBreakpoint.Address; int id = inferior.InsertHardwareBreakpoint (address, true, out dr_index); temp_breakpoint = new TemporaryBreakpointData (id, address); Report.Debug (DebugFlags.SSE, "{0} restored stolen breakpoint: {1}", this, temp_breakpoint); } lmf_breakpoint = null; }
void insert_temporary_breakpoint(TargetAddress address) { check_inferior (); if (temp_breakpoint != null) throw new InternalError ("temp_breakpoint_id != 0"); int dr_index; int id = inferior.InsertHardwareBreakpoint (address, true, out dr_index); temp_breakpoint = new TemporaryBreakpointData (id, address); Report.Debug (DebugFlags.SSE, "{0} inserted temp breakpoint {1}:{2} at {3}", this, id, dr_index, address); }
void insert_lmf_breakpoint(TargetAddress lmf_address) { lmf_breakpoint = new LMFBreakpointData (lmf_address); /* * Insert a breakpoint on the last managed frame (LMF). We use a hardware breakpoint for this * since the JIT might inspect / modify the callsite and we don't know whether we're at a safe * spot right now. * * If we already have a single-stepping breakpoint, we "steal" it here, so we only use one single * hardware register internally in the SSE. * */ if (temp_breakpoint != null) { Report.Debug (DebugFlags.SSE, "{0} stealing temporary breakpoint {1} at {2} -> lmf breakpoint at {2}.", temp_breakpoint.ID, temp_breakpoint.Address, lmf_address); lmf_breakpoint.StolenBreakpoint = temp_breakpoint; temp_breakpoint = null; /* * The breakpoint is already at the requested location -> keep and reuse it. */ if (lmf_address == temp_breakpoint.Address) { lmf_breakpoint.Breakpoint = lmf_breakpoint.StolenBreakpoint; return; } inferior.RemoveBreakpoint (lmf_breakpoint.StolenBreakpoint.ID); } /* * The SSE's internal hardware breakpoint register is now free. */ int dr_index; int id = inferior.InsertHardwareBreakpoint (lmf_address, true, out dr_index); Report.Debug (DebugFlags.SSE, "{0} inserted lmf breakpoint: {1} {2} {3}", this, lmf_address, id, dr_index); lmf_breakpoint.Breakpoint = new TemporaryBreakpointData (id, lmf_address); }
internal void OnThreadExited(Inferior.ChildEvent cevent) { TargetEventArgs result; int arg = (int) cevent.Argument; if (killed) result = new TargetEventArgs (TargetEventType.TargetExited, 0); else if (cevent.Type == Inferior.ChildEventType.CHILD_SIGNALED) result = new TargetEventArgs (TargetEventType.TargetSignaled, arg); else result = new TargetEventArgs (TargetEventType.TargetExited, arg); temp_breakpoint = null; dead = true; if (current_operation != null) OperationCompleted (result); else process.Debugger.OnTargetEvent (thread, result); process.OnThreadExitedEvent (this); Dispose (); }