public AD7StackFrame(AD7Engine engine, AD7Thread thread, ThreadContext threadContext) { Debug.Assert(threadContext != null, "ThreadContext is null"); Engine = engine; Thread = thread; ThreadContext = threadContext; _textPosition = threadContext.TextPosition; _functionName = threadContext.Function; if (threadContext.pc.HasValue) { _codeCxt = new AD7MemoryAddress(this.Engine, threadContext.pc.Value, _functionName); } if (_textPosition != null) { _documentCxt = new AD7DocumentContext(_textPosition, _codeCxt); if (_codeCxt != null) { _codeCxt.SetDocumentContext(_documentCxt); } } }
private VariableInformation(ThreadContext ctx, AD7Engine engine, AD7Thread thread) { _engine = engine; _debuggedProcess = _engine.DebuggedProcess; _ctx = ctx; Client = thread; IsParameter = false; IsChild = false; _attribsFetched = false; Access = enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_NONE; _fullname = null; lock (this._debuggedProcess.ActiveVariables) { this._debuggedProcess.ActiveVariables.Add(this); } }
public AD7StackFrame(AD7Engine engine, AD7Thread thread, ThreadContext threadContext) { Debug.Assert(threadContext != null, "ThreadContext is null"); Engine = engine; Thread = thread; ThreadContext = threadContext; _textPosition = threadContext.TextPosition; _functionName = threadContext.Function; if (threadContext.pc.HasValue) { _codeCxt = new AD7MemoryAddress(this.Engine, threadContext.pc.Value, _functionName); } if (_textPosition != null) { var docContext = new AD7DocumentContext(_textPosition, _codeCxt); _codeCxt.SetDocumentContext(docContext); } }
private void FilterUnknownFrames(System.Collections.Generic.List <ThreadContext> stackFrames) { bool lastWasQuestion = false; for (int i = 0; i < stackFrames.Count;) { // replace sequences of "??" with one UnknownCode frame if (stackFrames[i].Function == null || stackFrames[i].Function.Equals("??", StringComparison.Ordinal)) { if (lastWasQuestion) { stackFrames.RemoveAt(i); continue; } lastWasQuestion = true; stackFrames[i] = new ThreadContext(stackFrames[i].pc, stackFrames[i].TextPosition, ResourceStrings.UnknownCode, stackFrames[i].Level, null); } else { lastWasQuestion = false; } i++; } }
private void FilterUnknownFrames(System.Collections.Generic.List<ThreadContext> stackFrames) { bool lastWasQuestion = false; for (int i = 0; i < stackFrames.Count;) { // replace sequences of "??" with one UnknownCode frame if (stackFrames[i].Function == null || stackFrames[i].Function.Equals("??", StringComparison.Ordinal)) { if (lastWasQuestion) { stackFrames.RemoveAt(i); continue; } lastWasQuestion = true; stackFrames[i] = new ThreadContext(stackFrames[i].pc, stackFrames[i].TextPosition, ResourceStrings.UnknownCode, stackFrames[i].Level, null); } else { lastWasQuestion = false; } i++; } }
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) { bool bNew = false; var thread = SetThreadInfoFromResultValue(t, out bNew); int threadId = thread.Id; if (bNew) { NewThreads.Add(thread); } TupleValue[] frames = ((TupleValue)t).FindAll <TupleValue>("frame"); if (frames.Any()) { List <ThreadContext> stack = new List <ThreadContext>(); stack.AddRange(frames.Select(frame => CreateContext(frame))); _topContext[threadId] = stack[0]; if (threadId == cxtThreadId) { ret = _topContext[threadId]; } if (stack.Count > 1) { _stackFrames[threadId] = stack; } } } foreach (var thread in _threadList.ToList()) { if (!thread.Alive) { DeadThreads.Add(thread); _threadList.Remove(thread); } } _stateChange = false; _full = true; } } return(ret); }
//This method gets the value/type info for the method parameters without creating an MI debugger variable for them. For use in the callstack window //NOTE: eval is not called public async Task<List<SimpleVariableInformation>> GetParameterInfoOnly(AD7Thread thread, ThreadContext ctx) { List<SimpleVariableInformation> parameters = new List<SimpleVariableInformation>(); ValueListValue localAndParameters = await MICommandFactory.StackListVariables(PrintValues.SimpleValues, thread.Id, ctx.Level); foreach (var results in localAndParameters.Content.Where(r => r.TryFindString("arg") == "1")) { parameters.Add(new SimpleVariableInformation(results.FindString("name"), /*isParam*/ true, results.FindString("value"), results.FindString("type"))); } return parameters; }
//This method gets the locals and parameters and creates an MI debugger variable for each one so that we can manipulate them (and expand children, etc.) //NOTE: Eval is called internal async Task<List<VariableInformation>> GetLocalsAndParameters(AD7Thread thread, ThreadContext ctx) { List<VariableInformation> variables = new List<VariableInformation>(); ValueListValue localsAndParameters = await MICommandFactory.StackListVariables(PrintValues.NoValues, thread.Id, ctx.Level); foreach (var localOrParamResult in localsAndParameters.Content) { string name = localOrParamResult.FindString("name"); bool isParam = localOrParamResult.TryFindString("arg") == "1"; SimpleVariableInformation simpleInfo = new SimpleVariableInformation(name, isParam); VariableInformation vi = await simpleInfo.CreateMIDebuggerVariable(ctx, Engine, thread); variables.Add(vi); } return variables; }
//This method gets the value/type info for the method parameters without creating an MI debugger varialbe for them. For use in the callstack window //NOTE: eval is not called public async Task <List <SimpleVariableInformation> > GetParameterInfoOnly(AD7Thread thread, ThreadContext ctx) { List <SimpleVariableInformation> parameters = new List <SimpleVariableInformation>(); ValueListValue localAndParameters = await MICommandFactory.StackListVariables(PrintValues.SimpleValues, thread.Id, ctx.Level); foreach (var results in localAndParameters.Content.Where(r => r.TryFindString("arg") == "1")) { parameters.Add(new SimpleVariableInformation(results.FindString("name"), /*isParam*/ true, results.FindString("value"), results.FindString("type"))); } return(parameters); }
//This method gets the locals and parameters and creates an MI debugger variable for each one so that we can manipulate them (and expand children, etc.) //NOTE: Eval is called internal async Task <List <VariableInformation> > GetLocalsAndParameters(AD7Thread thread, ThreadContext ctx) { List <VariableInformation> variables = new List <VariableInformation>(); ValueListValue localsAndParameters = await MICommandFactory.StackListVariables(PrintValues.NoValues, thread.Id, ctx.Level); foreach (var localOrParamResult in localsAndParameters.Content) { string name = localOrParamResult.FindString("name"); bool isParam = localOrParamResult.TryFindString("arg") == "1"; SimpleVariableInformation simpleInfo = new SimpleVariableInformation(name, isParam); VariableInformation vi = await simpleInfo.CreateMIDebuggerVariable(ctx, Engine, thread); variables.Add(vi); } return(variables); }
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); } }
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 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); }