Example #1
0
        public async Task <BreakResponse> Break()
        {
            await BeginRunStateTransition();

            var fbb = BeginRequest();

            BreakRequest.StartBreakRequest(fbb);
            int requestDataOffset = BreakRequest.EndBreakRequest(fbb);
            var response          = await CommitRequest(fbb, RequestData.BreakRequest, requestDataOffset);

            System.Diagnostics.Debug.Assert(response.ResponseDataType ==
                                            ResponseData.BreakResponse);
            var breakResponse = new BreakResponse();

            response.GetResponseData(breakResponse);
            await CompleteRunStateTransition(RunState.Paused);

            return(breakResponse);
        }
Example #2
0
        private async Task HandleBreakModeEvent(ResultEventArgs results, BreakRequest breakRequest)
        {
            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");
            }

            if (_childProcessHandler != null && await _childProcessHandler.Stopped(results.Results, tid))
            {
                return;
            }

            // Any existing variable objects at this point are from the last time we were in break mode, and are
            //  therefore invalid.  Dispose them so they're marked for cleanup.
            lock (this.ActiveVariables)
            {
                foreach (IVariableInformation varInfo in this.ActiveVariables)
                {
                    varInfo.Dispose();
                }
                this.ActiveVariables.Clear();
            }

            ThreadCache.MarkDirty();
            MICommandFactory.DefineCurrentThread(tid);

            DebuggedThread thread = await ThreadCache.GetThread(tid);
            if (thread == null)
            {
                if (!this.IsStopDebuggingInProgress)
                {
                    Debug.Fail("Failed to find thread on break event.");
                    throw new Exception(String.Format(CultureInfo.CurrentUICulture, ResourceStrings.MissingThreadBreakEvent, tid));
                }
                else
                {
                    // It's possible that the SIGINT was sent because GDB is trying to terminate a running debuggee and stop debugging
                    // See https://devdiv.visualstudio.com/DevDiv/VS%20Diag%20IntelliTrace/_workItems?_a=edit&id=236275&triage=true
                    // for a repro
                    return;
                }
            }

            await ThreadCache.StackFrames(thread);  // prepopulate the break thread in the thread cache
            ThreadContext cxt = await ThreadCache.GetThreadContext(thread);

            if (cxt == null)
            {
                // Something went seriously wrong. For instance, this can happen when the primary thread
                // of an app exits on linux while background threads continue to run with pthread_exit on the main thread
                // See https://devdiv.visualstudio.com/DefaultCollection/DevDiv/VS%20Diag%20IntelliTrace/_workItems?_a=edit&id=197616&triage=true
                // for a repro
                Debug.Fail("Failed to find thread on break event.");
                throw new Exception(String.Format(CultureInfo.CurrentUICulture, ResourceStrings.MissingThreadBreakEvent, tid));
            }

            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 GDB variable objects that have been marked for cleanup
            List<string> variablesToDelete = null;
            lock (VariablesToDelete)
            {
                variablesToDelete = new List<string>(this.VariablesToDelete);
                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) && !this.EntrypointHit)
            {
                breakRequest = BreakRequest.None;   // don't let stopping interfere with launch processing
                this.EntrypointHit = true;
                CmdContinueAsync();
                FireDeviceAppLauncherResume();
            }
            else if (reason == "entry-point-hit")
            {
                this.EntrypointHit = true;
                _callback.OnEntryPoint(thread);
            }
            else if (reason == "breakpoint-hit")
            {
                string bkptno = results.Results.FindString("bkptno");
                ulong addr = cxt.pc ?? 0;

                bool fContinue;
                TupleValue frame = results.Results.TryFind<TupleValue>("frame");
                AD7BoundBreakpoint[] bkpt = _breakpointManager.FindHitBreakpoints(bkptno, addr, frame, out fContinue);
                if (bkpt != null)
                {
                    if (frame != null && addr != 0)
                    {
                        string sourceFile = frame.TryFindString("fullname");
                        if (!String.IsNullOrEmpty(sourceFile))
                        {
                            await this.VerifySourceFileTimestamp(addr, sourceFile);
                        }
                    }

                    // Hitting a bp before the entrypoint overrules entrypoint processing.
                    this.EntrypointHit = true;

                    List<object> bplist = new List<object>();
                    bplist.AddRange(bkpt);
                    _callback.OnBreakpoint(thread, bplist.AsReadOnly());
                }
                else if (!this.EntrypointHit)
                {
                    this.EntrypointHit = true;

                    if (this.MICommandFactory.Mode == MIMode.Lldb)
                    {
                        // When the terminal window is closed, a SIGHUP is sent to lldb-mi and LLDB's default is to stop.
                        // We want to not stop (break) when this happens and the SIGHUP to be sent to the debuggee process.
                        // LLDB requires this command to be issued after the process has started.
                        await ConsoleCmdAsync("process handle --pass true --stop false --notify false SIGHUP", true);
                    }

                    _callback.OnEntryPoint(thread);
                }
                else if (bkptno == "<EMBEDDED>")
                {
                    _callback.OnBreakpoint(thread, new ReadOnlyCollection<object>(new AD7BoundBreakpoint[] { }));
                }
                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
                        CmdContinueAsyncConditional(breakRequest);
                    }
                    else
                    {
                        // not one of our breakpoints, so stop with a message
                        _callback.OnException(thread, "Unknown breakpoint", "", 0);
                    }
                }
            }
            else if (reason == "watchpoint-trigger")
            {
                var wpt = results.Results.Find("wpt");
                string bkptno = wpt.FindString("number");
                ulong addr = cxt.pc ?? 0;

                bool fContinue;
                AD7BoundBreakpoint bkpt = _breakpointManager.FindHitWatchpoint(bkptno, out fContinue);
                if (bkpt != null)
                {
                    List<object> bplist = new List<object>();
                    bplist.Add(bkpt);
                    _callback.OnBreakpoint(thread, bplist.AsReadOnly());
                }
                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
                        CmdContinueAsyncConditional(breakRequest);
                    }
                    else
                    {
                        // not one of our breakpoints, so stop with a message
                        _callback.OnException(thread, "Unknown watchpoint", "", 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
                    CmdContinueAsyncConditional(breakRequest);
                }
                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];
                    }
                    bool stoppedAtSIGSTOP = false;
                    if (sigName == "SIGSTOP")
                    {
                        if (AD7Engine.RemoveChildProcess(_launchOptions.ProcessId))
                        {
                            stoppedAtSIGSTOP = true;
                        }
                    }
                    string message = results.Results.TryFindString("signal-meaning");
                    if (stoppedAtSIGSTOP)
                    {
                        await MICommandFactory.Signal("SIGCONT");
                    }
                    else
                    {
                        _callback.OnException(thread, sigName, message, code);
                    }
                }
            }
            else if (reason == "exception-received")
            {
                string exceptionName = results.Results.TryFindString("exception-name");
                if (string.IsNullOrEmpty(exceptionName))
                    exceptionName = "Exception";

                string description = results.Results.FindString("exception");
                Guid? exceptionCategory;
                ExceptionBreakpointState state;
                MICommandFactory.DecodeExceptionReceivedProperties(results.Results, out exceptionCategory, out state);

                _callback.OnException(thread, exceptionName, description, 0, exceptionCategory, state);
            }
            else
            {
                if (breakRequest == BreakRequest.None)
                {
                    Debug.Fail("Unknown stopping reason");
                    _callback.OnException(thread, "Unknown", "Unknown stopping event", 0);
                }
            }
            if (IsExternalBreakRequest(breakRequest))
            {
                _callback.OnStopComplete(thread);
            }
        }
Example #3
0
 private void CmdContinueAsyncConditional(BreakRequest request)
 {
     if (!IsExternalBreakRequest(request))
     {
         CmdContinueAsync();
     }
 }
Example #4
0
 private static bool IsExternalBreakRequest(BreakRequest breakRequest)
 {
     return breakRequest == BreakRequest.Async || breakRequest == BreakRequest.Stop;
 }
Example #5
0
 private void CmdContinueAsyncConditional(BreakRequest request)
 {
     if (request != BreakRequest.None)
     {
         CmdContinueAsync();
     }
 }
Example #6
0
 public Task CmdBreak(BreakRequest request)
 {
     if (request > _requestingRealAsyncBreak)
     {
         _requestingRealAsyncBreak = request;
     }
     return CmdBreakInternal();
 }
Example #7
0
 public StoppingEventArgs(Results results, BreakRequest asyncRequest = BreakRequest.None) : this(results, 0, asyncRequest)
 { }
Example #8
0
 public StoppingEventArgs(Results results, uint id, BreakRequest asyncRequest = BreakRequest.None) : base(results, id)
 {
     AsyncRequest = asyncRequest;
 }