public AD7Thread(AD7Engine engine, DebuggedThread debuggedThread)//ThreadMirror threadMirror) { _engine = engine; ThreadMirror = debuggedThread.Thread; _debuggedThread = debuggedThread; }
internal async Task<List<ThreadContext>> StackFrames(DebuggedThread thread) { lock (_threadList) { if (!_threadList.Contains(thread)) { return null; // thread must be dead } if (_stackFrames.ContainsKey(thread.Id)) { return _stackFrames[thread.Id]; } } List<ThreadContext> stack = null; try { stack = await WalkStack(thread); } catch (UnexpectedMIResultException) { Logger.WriteLine("Stack walk failed on thread: " + thread.TargetId); _stateChange = true; // thread may have been seleted. Force a resync } lock (_threadList) { _stackFrames[thread.Id] = stack; _topContext[thread.Id] = (stack != null && stack.Count > 0) ? stack[0] : null; return _stackFrames[thread.Id]; } }
public void OnAsyncBreakComplete(DebuggedThread thread) { // This will get called when the engine receives the breakpoint event that is created when the user // hits the pause button in vs. Debug.Assert(_engine.DebuggedProcess.WorkerThread.IsPollThread()); AD7Thread ad7Thread = (AD7Thread)thread.Client; AD7AsyncBreakCompleteEvent eventObject = new AD7AsyncBreakCompleteEvent(); Send(eventObject, AD7AsyncBreakCompleteEvent.IID, ad7Thread); }
private async Task <List <ThreadContext> > WalkStack(DebuggedThread thread) { List <ThreadContext> stack = null; TupleValue[] frameinfo = await _debugger.MICommandFactory.StackListFrames(thread.Id, 0, 1000); if (frameinfo == null) { _debugger.Logger.WriteLine("Failed to get frame info"); } else { stack = new List <ThreadContext>(); foreach (var frame in frameinfo) { stack.Add(CreateContext(frame)); } } return(stack); }
public void OnBreakpoint(DebuggedThread thread, ReadOnlyCollection<object> clients) { IDebugBoundBreakpoint2[] boundBreakpoints = new IDebugBoundBreakpoint2[clients.Count]; int i = 0; foreach (object objCurrentBreakpoint in clients) { boundBreakpoints[i] = (IDebugBoundBreakpoint2)objCurrentBreakpoint; i++; } // An engine that supports more advanced breakpoint features such as hit counts, conditions and filters // should notify each bound breakpoint that it has been hit and evaluate conditions here. // The sample engine does not support these features. AD7BoundBreakpointsEnum boundBreakpointsEnum = new AD7BoundBreakpointsEnum(boundBreakpoints); AD7BreakpointEvent eventObject = new AD7BreakpointEvent(boundBreakpointsEnum); AD7Thread ad7Thread = (AD7Thread)thread.Client; Send(eventObject, AD7BreakpointEvent.IID, ad7Thread); }
private DebuggedThread FindThread(int id, out bool bNew) { DebuggedThread newthread; bNew = false; var thread = _threadList.Find(t => t.Id == id); if (thread != null) { return(thread); } // thread not found, so create it, and return it newthread = new DebuggedThread(id, _debugger.Engine); if (!IsInParent(id)) { newthread.ChildThread = true; } newthread.Default = false; _threadList.Add(newthread); bNew = true; return(newthread); }
private DebuggedThread SetThreadInfoFromResultValue(ResultValue resVal, out bool newThread) { newThread = false; int threadId = resVal.FindInt("id"); string targetId = resVal.TryFindString("target-id"); DebuggedThread thread = FindThread(threadId, out newThread); thread.Alive = true; if (!String.IsNullOrEmpty(targetId)) { uint tid = 0; if (TryGetTidFromTargetId(targetId, out tid)) { thread.TargetId = tid; } } if (resVal.Contains("name")) { thread.Name = resVal.FindString("name"); } return(thread); }
public void OnBreakpoint(DebuggedThread thread, ReadOnlyCollection <object> clients) { IDebugBoundBreakpoint2[] boundBreakpoints = new IDebugBoundBreakpoint2[clients.Count]; int i = 0; foreach (object objCurrentBreakpoint in clients) { boundBreakpoints[i] = (IDebugBoundBreakpoint2)objCurrentBreakpoint; i++; } // An engine that supports more advanced breakpoint features such as hit counts, conditions and filters // should notify each bound breakpoint that it has been hit and evaluate conditions here. // The sample engine does not support these features. AD7BoundBreakpointsEnum boundBreakpointsEnum = new AD7BoundBreakpointsEnum(boundBreakpoints); AD7BreakpointEvent eventObject = new AD7BreakpointEvent(boundBreakpointsEnum); AD7Thread ad7Thread = (AD7Thread)thread.Client; Send(eventObject, AD7BreakpointEvent.IID, ad7Thread); }
public void Execute(DebuggedThread thread) { // Should clear stepping state _worker.PostOperation(CmdContinueAsync); }
private async Task HandleBreakModeEvent(ResultEventArgs results) { string reason = results.Results.TryFindString("reason"); int tid; if (!results.Results.Contains("thread-id")) { Results res = await MICommandFactory.ThreadInfo(); tid = res.FindInt("id"); } else { tid = results.Results.FindInt("thread-id"); } ThreadCache.MarkDirty(); MICommandFactory.DefineCurrentThread(tid); DebuggedThread thread = await ThreadCache.GetThread(tid); await ThreadCache.StackFrames(thread); // prepopulate the break thread in the thread cache ThreadContext cxt = await ThreadCache.GetThreadContext(thread); ThreadCache.SendThreadEvents(this, null); // make sure that new threads have been pushed to the UI //always delete breakpoints pending deletion on break mode //the flag tells us if we hit an existing breakpoint pending deletion that we need to continue await _breakpointManager.DeleteBreakpointsPendingDeletion(); //delete varialbes that have been GC'd List <string> variablesToDelete = new List <string>(); lock (VariablesToDelete) { foreach (var variable in VariablesToDelete) { variablesToDelete.Add(variable); } VariablesToDelete.Clear(); } foreach (var variable in variablesToDelete) { try { await MICommandFactory.VarDelete(variable); } catch (MIException) { //not much to do really, we're leaking MI debugger variables. Debug.Fail("Failed to delete variable: " + variable + ". This is leaking memory in the MI Debugger."); } } if (String.IsNullOrWhiteSpace(reason) && !_bEntrypointHit) { // CLRDBG TODO: Try to verify this code path _bEntrypointHit = true; CmdContinueAsync(); FireDeviceAppLauncherResume(); } else if (reason == "breakpoint-hit") { string bkptno = results.Results.FindString("bkptno"); ulong addr = cxt.pc ?? 0; AD7BoundBreakpoint bkpt = null; bool fContinue; TupleValue frame = results.Results.TryFind <TupleValue>("frame"); bkpt = _breakpointManager.FindHitBreakpoint(bkptno, addr, frame, out fContinue); // use breakpoint number to resolve breakpoint if (bkpt != null) { List <object> bplist = new List <object>(); bplist.Add(bkpt); _callback.OnBreakpoint(thread, bplist.AsReadOnly()); } else if (!_bEntrypointHit) { _bEntrypointHit = true; _callback.OnEntryPoint(thread); } else { if (fContinue) { //we hit a bp pending deletion //post the CmdContinueAsync operation so it does not happen until we have deleted all the pending deletes CmdContinueAsync(); } else { // not one of our breakpoints, so stop with a message _callback.OnException(thread, "Unknown breakpoint", "", 0); } } } else if (reason == "end-stepping-range" || reason == "function-finished") { _callback.OnStepComplete(thread); } else if (reason == "signal-received") { string name = results.Results.TryFindString("signal-name"); if ((name == "SIG32") || (name == "SIG33")) { // we are going to ignore these (Sigma) signals for now CmdContinueAsync(); } else if (MICommandFactory.IsAsyncBreakSignal(results.Results)) { _callback.OnAsyncBreakComplete(thread); } else { uint code = 0; string sigName = results.Results.TryFindString("signal-name"); code = results.Results.Contains("signal") ? results.Results.FindUint("signal") : 0; if (String.IsNullOrEmpty(sigName) && code != 0 && EngineUtils.SignalMap.Instance.ContainsValue(code)) { sigName = EngineUtils.SignalMap.Instance.First((p) => p.Value == code).Key; } else if (!String.IsNullOrEmpty(sigName) && code == 0 && EngineUtils.SignalMap.Instance.ContainsKey(sigName)) { code = EngineUtils.SignalMap.Instance[sigName]; } _callback.OnException(thread, sigName, results.Results.TryFindString("signal-meaning"), code); } } else if (reason == "exception-received") { string exception = results.Results.FindString("exception"); _callback.OnException(thread, "Exception", exception, 0); } else { Debug.Fail("Unknown stopping reason"); _callback.OnException(thread, "Unknown", "Unknown stopping event", 0); } }
internal async Task<ThreadContext> GetThreadContext(DebuggedThread thread) { lock (_threadList) { if (_topContext.ContainsKey(thread.Id)) { return _topContext[thread.Id]; } if (_full) { return null; // no context available for this thread } } return await CollectThreadsInfo(thread.Id); }
/// <summary> /// On First run /// </summary> /// <param name="thread"></param> internal void Continue(DebuggedThread thread) { //_vm.Resume(); }
public async Task Execute(DebuggedThread thread) { await ExceptionManager.EnsureSettingsUpdated(); // Should clear stepping state if (_worker.IsPollThread()) { CmdContinueAsync(); } else { _worker.PostOperation(CmdContinueAsync); } }
public void Continue(DebuggedThread thread) { // Called after Stopping event Execute(thread); }
public void OnLoadComplete(DebuggedThread thread) { AD7Thread ad7Thread = (AD7Thread)thread.Client; AD7LoadCompleteEvent eventObject = new AD7LoadCompleteEvent(); Send(eventObject, AD7LoadCompleteEvent.IID, ad7Thread); }
public void OnStepComplete(DebuggedThread thread) { // Step complete is sent when a step has finished AD7StepCompleteEvent eventObject = new AD7StepCompleteEvent(); AD7Thread ad7Thread = (AD7Thread)thread.Client; Send(eventObject, AD7StepCompleteEvent.IID, ad7Thread); }
public void OnEntryPoint(DebuggedThread thread) { AD7EntryPointEvent eventObject = new AD7EntryPointEvent(); Send(eventObject, AD7EntryPointEvent.IID, (AD7Thread)thread.Client); }
// Exception events are sent when an exception occurs in the debuggee that the debugger was not expecting. public void OnException(DebuggedThread thread, string name, string description, uint code, Guid? exceptionCategory = null, ExceptionBreakpointState state = ExceptionBreakpointState.None) { AD7ExceptionEvent eventObject = new AD7ExceptionEvent(name, description, code, exceptionCategory, state); AD7Thread ad7Thread = (AD7Thread)thread.Client; Send(eventObject, AD7ExceptionEvent.IID, ad7Thread); }
private async Task <ThreadContext> CollectThreadsInfo(int cxtThreadId) { ThreadContext ret = null; // set of threads has changed or thread locations have been asked for Results threadsinfo = await _debugger.MICommandFactory.ThreadInfo(); if (threadsinfo.ResultClass != ResultClass.done) { Debug.Fail("Failed to get thread info"); } else { var tlist = threadsinfo.Find <ValueListValue>("threads"); // update our thread list lock (_threadList) { foreach (var thread in _threadList) { thread.Alive = false; } foreach (var t in tlist.Content) { int threadId = t.FindInt("id"); string targetId = t.TryFindString("target-id"); string state = t.FindString("state"); TupleValue[] frames = ((TupleValue)t).FindAll <TupleValue>("frame"); bool bNew; DebuggedThread thread = FindThread(threadId, out bNew); thread.Alive = true; if (!String.IsNullOrEmpty(targetId)) { uint tid = 0; if (System.UInt32.TryParse(targetId, out tid) && tid != 0) { thread.TargetId = tid; } else if (targetId.StartsWith("Thread") && System.UInt32.TryParse(targetId.Substring("Thread ".Length), out tid) && tid != 0 ) { thread.TargetId = tid; } } if (t.Contains("name")) { thread.Name = t.FindString("name"); } if (bNew) { if (_newThreads == null) { _newThreads = new List <DebuggedThread>(); } _newThreads.Add(thread); } var stack = new List <ThreadContext>(); foreach (var frame in frames) { stack.Add(CreateContext(frame)); } if (stack.Count > 0) { _topContext[threadId] = stack[0]; if (threadId == cxtThreadId) { ret = _topContext[threadId]; } if (stack.Count > 1) { _stackFrames[threadId] = stack; } } } foreach (var thread in _threadList) { if (!thread.Alive) { if (_deadThreads == null) { _deadThreads = new List <DebuggedThread>(); } _deadThreads.Add(thread); } } if (_deadThreads != null) { foreach (var dead in _deadThreads) { _threadList.Remove(dead); } } _stateChange = false; _full = true; } } return(ret); }
private DebuggedThread FindThread(int id, out bool bNew) { DebuggedThread newthread; bNew = false; var thread = _threadList.Find(t => t.Id == id); if (thread != null) return thread; // thread not found, so create it, and return it newthread = new DebuggedThread(id, _debugger.Engine); newthread.Default = false; _threadList.Add(newthread); bNew = true; return newthread; }
private async Task<List<ThreadContext>> WalkStack(DebuggedThread thread) { List<ThreadContext> stack = null; TupleValue[] frameinfo = await _debugger.MICommandFactory.StackListFrames(thread.Id, 0, 1000); if (frameinfo == null) { Logger.WriteLine("Failed to get frame info"); } else { stack = new List<ThreadContext>(); foreach (var frame in frameinfo) { stack.Add(CreateContext(frame)); } } return stack; }
public AD7Thread(AD7Engine engine, DebuggedThread debuggedThread) { _engine = engine; _debuggedThread = debuggedThread; }
private async Task <ThreadContext> CollectThreadsInfo(int cxtThreadId) { ThreadContext ret = null; // set of threads has changed or thread locations have been asked for Results threadsinfo = await _debugger.MICommandFactory.ThreadInfo(); if (threadsinfo.ResultClass != ResultClass.done) { Debug.Fail("Failed to get thread info"); } else { var tlist = threadsinfo.Find <ValueListValue>("threads"); // update our thread list lock (_threadList) { foreach (var thread in _threadList) { thread.Alive = false; } foreach (var t in tlist.Content) { int threadId = t.FindInt("id"); string targetId = t.TryFindString("target-id"); string state = t.FindString("state"); TupleValue[] frames = ((TupleValue)t).FindAll <TupleValue>("frame"); bool bNew; DebuggedThread thread = FindThread(threadId, out bNew); thread.Alive = true; if (!String.IsNullOrEmpty(targetId)) { uint tid = 0; if (System.UInt32.TryParse(targetId, out tid) && tid != 0) { thread.TargetId = tid; } else if (targetId.StartsWith("Thread ", StringComparison.OrdinalIgnoreCase) && System.UInt32.TryParse(targetId.Substring("Thread ".Length), out tid) && tid != 0 ) { thread.TargetId = tid; } else if (targetId.StartsWith("Process ", StringComparison.OrdinalIgnoreCase) && System.UInt32.TryParse(targetId.Substring("Process ".Length), out tid) && tid != 0 ) { // First thread in a linux process has tid == pid thread.TargetId = tid; } else if (targetId.StartsWith("Thread ", StringComparison.OrdinalIgnoreCase)) { // In processes with pthreads the thread name is in form: "Thread <0x123456789abc> (LWP <thread-id>)" int lwp_pos = targetId.IndexOf("(LWP "); int paren_pos = targetId.LastIndexOf(')'); int len = paren_pos - (lwp_pos + 5); if (len > 0 && System.UInt32.TryParse(targetId.Substring(lwp_pos + 5, len), out tid) && tid != 0) { thread.TargetId = tid; } } else { thread.TargetId = --s_targetId; } } if (t.Contains("name")) { thread.Name = t.FindString("name"); } if (bNew) { if (_newThreads == null) { _newThreads = new List <DebuggedThread>(); } _newThreads.Add(thread); } var stack = new List <ThreadContext>(); foreach (var frame in frames) { stack.Add(CreateContext(frame)); } if (stack.Count > 0) { _topContext[threadId] = stack[0]; if (threadId == cxtThreadId) { ret = _topContext[threadId]; } if (stack.Count > 1) { _stackFrames[threadId] = stack; } } } foreach (var thread in _threadList) { if (!thread.Alive) { if (_deadThreads == null) { _deadThreads = new List <DebuggedThread>(); } _deadThreads.Add(thread); } } if (_deadThreads != null) { foreach (var dead in _deadThreads) { _threadList.Remove(dead); } } _stateChange = false; _full = true; } } return(ret); }
public void OnThreadStart(DebuggedThread debuggedThread) { // This will get called when the entrypoint breakpoint is fired because the engine sends a thread start event // for the main thread of the application. if (_engine.DebuggedProcess != null) { Debug.Assert(_engine.DebuggedProcess.WorkerThread.IsPollThread()); } AD7ThreadCreateEvent eventObject = new AD7ThreadCreateEvent(); Send(eventObject, AD7ThreadCreateEvent.IID, (IDebugThread2)debuggedThread.Client); }
public Task Continue(DebuggedThread thread) { // Called after Stopping event return(Execute(thread)); }
public Task Continue(DebuggedThread thread) { // Called after Stopping event return Execute(thread); }
// Exception events are sent when an exception occurs in the debuggee that the debugger was not expecting. public void OnException(DebuggedThread thread, string name, string description, uint code) { AD7ExceptionEvent eventObject = new AD7ExceptionEvent(name, description, code); AD7Thread ad7Thread = (AD7Thread)thread.Client; Send(eventObject, AD7ExceptionEvent.IID, ad7Thread); }
public void OnStopComplete(DebuggedThread thread) { var eventObject = new AD7StopCompleteEvent(); Send(eventObject, AD7StopCompleteEvent.IID, (AD7Thread)thread.Client); }
public void OnThreadExit(DebuggedThread debuggedThread, uint exitCode) { Debug.Assert(_engine.DebuggedProcess.WorkerThread.IsPollThread()); AD7Thread ad7Thread = (AD7Thread)debuggedThread.Client; Debug.Assert(ad7Thread != null); AD7ThreadDestroyEvent eventObject = new AD7ThreadDestroyEvent(exitCode); Send(eventObject, AD7ThreadDestroyEvent.IID, ad7Thread); }