////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public void RefreshThread(uint tid)
        {
            LoggingUtils.PrintFunction();

            try
            {
                m_debugger.RunInterruptOperation(delegate(CLangDebugger debugger)
                {
                    string command = string.Format("-thread-info {0}", (tid == 0) ? "" : tid.ToString());

                    MiResultRecord resultRecord = m_debugger.GdbClient.SendSyncCommand(command);

                    MiResultRecord.RequireOk(resultRecord, command);

                    if (!resultRecord.HasField("threads"))
                    {
                        throw new InvalidOperationException("-thread-info result missing 'threads' field");
                    }

                    MiResultValueList threadsValueList = (MiResultValueList)resultRecord ["threads"] [0];

                    List <MiResultValue> threadsData = threadsValueList.List;

                    bool refreshedProcesses = false;

                    for (int i = threadsData.Count - 1; i >= 0; --i) // reported threads are in descending order.
                    {
                        uint id = threadsData [i] ["id"] [0].GetUnsignedInt();

                        CLangDebuggeeThread thread = GetThread(id) ?? AddThread(id);

                        if (thread.RequiresRefresh)
                        {
                            MiResultValue threadData = threadsData [i];

                            if (!refreshedProcesses)
                            {
                                AndroidDevice hostDevice = DebugProgram.DebugProcess.NativeProcess.HostDevice;

                                hostDevice.RefreshProcesses(DebugProgram.DebugProcess.NativeProcess.Pid);

                                refreshedProcesses = true;
                            }

                            thread.Refresh(ref threadData);
                        }
                    }

                    if (resultRecord.HasField("current-thread-id"))
                    {
                        CurrentThreadId = resultRecord ["current-thread-id"] [0].GetUnsignedInt();
                    }
                });
            }
            catch (Exception e)
            {
                LoggingUtils.HandleException(e);
            }
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public override int CreateBoundBreakpoint(string location, DebuggeeDocumentContext documentContext, DebuggeeCodeContext codeContext)
        {
            //
            // Register a new GDB breakpoint.
            //

            LoggingUtils.PrintFunction();

            try
            {
                if (m_breakpointRequestInfo.bpLocation.bpLocationType == (uint)enum_BP_TYPE.BPT_DATA)
                {
                    throw new NotImplementedException();
                }

                m_debugger.RunInterruptOperation(delegate(CLangDebugger debugger)
                {
                    string command = string.Format("-break-insert -f {0} {1}", ((m_breakpointEnabled) ? "" : "-d"), PathUtils.SantiseWindowsPath(location));

                    debugger.GdbClient.SendCommand(command, delegate(MiResultRecord resultRecord)
                    {
                        if (resultRecord != null)
                        {
                            if (resultRecord.IsError())
                            {
                                string errorReason = "<unknown error>";

                                if (resultRecord.HasField("msg"))
                                {
                                    errorReason = resultRecord ["msg"] [0].GetString();
                                }

                                LoggingUtils.RequireOk(CreateErrorBreakpoint(errorReason, documentContext, codeContext));
                            }
                            else
                            {
                                MiResultValue breakpointData = resultRecord ["bkpt"] [0];

                                MiBreakpoint breakpoint = new MiBreakpoint(breakpointData.Values);

                                LoggingUtils.RequireOk(CreateBoundBreakpoint(breakpoint, documentContext, codeContext));
                            }
                        }
                    });
                });

                return(Constants.S_OK);
            }
            catch (Exception e)
            {
                LoggingUtils.HandleException(e);

                return(Constants.E_FAIL);
            }
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public void Refresh(ref MiResultValue threadData)
        {
            LoggingUtils.PrintFunction();

            if (threadData.HasField("name"))
            {
                m_threadDisplayName = threadData ["name"] [0].GetString(); // user-specified name
            }
            else if (threadData.HasField("target-id"))
            {
                uint threadPid;

                m_threadDisplayName = threadData ["target-id"] [0].GetString(); // usually the raw name, i.e. 'Thread 18771'

                if (m_threadDisplayName.StartsWith("Thread ") && uint.TryParse(m_threadDisplayName.Substring("Thread ".Length), out threadPid))
                {
                    AndroidDevice hostDevice = NativeProgram.DebugProgram.DebugProcess.NativeProcess.HostDevice;

                    AndroidProcess threadProcess = hostDevice.GetProcessFromPid(threadPid);

                    if (threadProcess != null)
                    {
                        m_threadDisplayName = threadProcess.Name;
                    }
                }
            }

            if (threadData.HasField("frame"))
            {
                MiResultValueTuple frameTuple = threadData ["frame"] [0] as MiResultValueTuple;

                uint stackLevel = frameTuple ["level"] [0].GetUnsignedInt();

                string stackFrameId = m_threadName + "#" + stackLevel;

                CLangDebuggeeStackFrame stackFrame = new CLangDebuggeeStackFrame(m_debugger, this, frameTuple, stackFrameId);

                lock (m_threadStackFrames)
                {
                    m_threadStackFrames.Add(stackFrame);
                }
            }

            RequiresRefresh = false;
        }
Example #4
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        protected override int QueryRegisters()
        {
            LoggingUtils.PrintFunction();

            try
            {
                //
                // Returns a list of registers for the current stack level.
                //

                if (!m_queriedRegisters)
                {
                    uint threadId;

                    LoggingUtils.RequireOk(m_thread.GetThreadId(out threadId));

                    string command = string.Format("-data-list-register-values --thread {0} --frame {1} r", threadId, StackLevel);

                    m_debugger.GdbClient.SendCommand(command, delegate(MiResultRecord resultRecord)
                    {
                        MiResultRecord.RequireOk(resultRecord, command);

                        if (!resultRecord.HasField("register-values"))
                        {
                            throw new InvalidOperationException("Failed to retrieve list of register values");
                        }

                        MiResultValue registerValues = resultRecord ["register-values"] [0];

                        int registerValuesCount = registerValues.Values.Count;

                        Dictionary <uint, string> registerIdMapping = m_debugger.GdbClient.GetRegisterIdMapping();

                        for (int i = 0; i < registerValuesCount; ++i)
                        {
                            uint registerId = registerValues [i] ["number"] [0].GetUnsignedInt();

                            string registerValue = registerValues [i] ["value"] [0].GetString();

                            string registerName = registerIdMapping [registerId];

                            string registerNamePrettified = "$" + registerName;

                            CLangDebuggeeProperty property = new CLangDebuggeeProperty(m_debugger, this, registerNamePrettified, registerValue);

                            m_stackRegisters.TryAdd(registerNamePrettified, property);

                            LoggingUtils.RequireOk(m_property.AddChildren(new DebuggeeProperty [] { property }));
                        }

                        m_queriedRegisters = true;
                    });
                }

                return(Constants.S_OK);
            }
            catch (Exception e)
            {
                LoggingUtils.HandleException(e);

                return(Constants.E_FAIL);
            }
        }
Example #5
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        protected override int QueryArgumentsAndLocals()
        {
            LoggingUtils.PrintFunction();

            try
            {
                if (!m_queriedArgumentsAndLocals)
                {
                    uint threadId;

                    LoggingUtils.RequireOk(m_thread.GetThreadId(out threadId));

                    string command = string.Format("-stack-list-variables --thread {0} --frame {1} --no-values", threadId, StackLevel);

                    m_debugger.GdbClient.SendCommand(command, delegate(MiResultRecord resultRecord)
                    {
                        MiResultRecord.RequireOk(resultRecord, command);

                        if (resultRecord.HasField("variables"))
                        {
                            MiResultValue localVariables = resultRecord ["variables"] [0];

                            for (int i = 0; i < localVariables.Values.Count; ++i)
                            {
                                string variableName = localVariables [i] ["name"] [0].GetString();

                                MiVariable variable = m_debugger.VariableManager.CreateVariableFromExpression(this, variableName);

                                if (variable == null)
                                {
                                    continue;
                                }

                                CLangDebuggeeProperty property = m_debugger.VariableManager.CreatePropertyFromVariable(this, variable);

                                if (property == null)
                                {
                                    throw new InvalidOperationException();
                                }

                                if (localVariables [i].HasField("arg"))
                                {
                                    m_stackArguments.TryAdd(variableName, property);

                                    LoggingUtils.RequireOk(m_property.AddChildren(new DebuggeeProperty [] { property }));
                                }
                                else
                                {
                                    m_stackLocals.TryAdd(variableName, property);

                                    LoggingUtils.RequireOk(m_property.AddChildren(new DebuggeeProperty [] { property }));
                                }

                                //LoggingUtils.RequireOk (m_property.AddChildren (new DebuggeeProperty [] { property }));
                            }

                            m_queriedArgumentsAndLocals = true;
                        }
                    });
                }

                return(Constants.S_OK);
            }
            catch (Exception e)
            {
                LoggingUtils.HandleException(e);

                return(Constants.E_FAIL);
            }
        }
Example #6
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public int Read(uint dwInstructions, enum_DISASSEMBLY_STREAM_FIELDS dwFields, out uint pdwInstructionsRead, DisassemblyData [] prgDisassembly)
        {
            //
            // Reads instructions starting from the current position in the disassembly stream.
            //

            LoggingUtils.PrintFunction();

            try
            {
                ulong startAddress = m_codeContext.Address.MemoryAddress;

                ulong endAddress = startAddress + ((ulong)(dwInstructions) * 4); // TODO: 4 for a 32-bit instruction set?

                string disassemblyCommand = string.Format("-data-disassemble -s 0x{0:X8} -e 0x{1:X8} -- 1", startAddress, endAddress);

                MiResultRecord resultRecord = m_debugger.GdbClient.SendSyncCommand(disassemblyCommand);

                MiResultRecord.RequireOk(resultRecord, disassemblyCommand);

                if (!resultRecord.HasField("asm_insns"))
                {
                    throw new InvalidOperationException("-data-disassemble result missing 'asm_insns' field");
                }

                MiResultValueList assemblyRecords = (MiResultValueList)resultRecord ["asm_insns"] [0];

                long maxInstructions = Math.Min(assemblyRecords.Values.Count, dwInstructions);

                if (maxInstructions == 0)
                {
                    throw new InvalidOperationException();
                }

                int currentInstruction = 0;

                for (int i = 0; i < assemblyRecords.Values.Count; ++i)
                {
                    MiResultValue recordValue = assemblyRecords [i];

                    if (recordValue.Variable.Equals("src_and_asm_line"))
                    {
                        //
                        // Parse mixed-mode disassembly reports.
                        //

                        uint line = recordValue ["line"] [0].GetUnsignedInt();

                        string file = recordValue ["file"] [0].GetString();

                        MiResultValueList lineAsmInstructionValues = (MiResultValueList)recordValue ["line_asm_insn"] [0];

                        foreach (MiResultValue instructionValue in lineAsmInstructionValues.Values)
                        {
                            string address = instructionValue ["address"] [0].GetString();

                            if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS) != 0)
                            {
                                prgDisassembly [currentInstruction].bstrAddress = address;

                                prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESS;
                            }

                            if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESSOFFSET) != 0)
                            {
                                string offset = instructionValue ["offset"] [0].GetString();

                                prgDisassembly [currentInstruction].bstrAddressOffset = offset;

                                prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_ADDRESSOFFSET;
                            }

                            if (((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE) != 0) || ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS) != 0) || ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS_SYMBOLS) != 0))
                            {
                                string inst = instructionValue ["inst"] [0].GetString();

                                string [] operations = inst.Split(new string [] { "\\t" }, StringSplitOptions.None);

                                if (operations.Length > 0)
                                {
                                    prgDisassembly [currentInstruction].bstrOpcode = operations [0];

                                    prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPCODE;
                                }

                                if (operations.Length > 1)
                                {
                                    prgDisassembly [currentInstruction].bstrOperands = operations [1];

                                    prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS;
                                }

                                if (operations.Length > 2)
                                {
                                    prgDisassembly [currentInstruction].bstrOperands += " " + operations [2];

                                    prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_OPERANDS_SYMBOLS;
                                }
                            }

                            if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL) != 0)
                            {
                                string functionName = instructionValue ["func-name"] [0].GetString();

                                prgDisassembly [currentInstruction].bstrSymbol = functionName;

                                prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_SYMBOL;
                            }

                            if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID) != 0)
                            {
                                DebuggeeAddress instructionAddress = new DebuggeeAddress(address);

                                prgDisassembly [currentInstruction].uCodeLocationId = instructionAddress.MemoryAddress;

                                prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_CODELOCATIONID;
                            }

                            if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION) != 0)
                            {
                                prgDisassembly [currentInstruction].posBeg.dwLine = line;

                                prgDisassembly [currentInstruction].posBeg.dwColumn = 0;

                                prgDisassembly [currentInstruction].posEnd.dwLine = line;

                                prgDisassembly [currentInstruction].posEnd.dwColumn = uint.MaxValue;

                                prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_POSITION;
                            }

                            if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL) != 0)
                            {
                                prgDisassembly [currentInstruction].bstrDocumentUrl = "file://" + file;

                                prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_DOCUMENTURL;
                            }

                            if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET) != 0)
                            {
                                uint offset = instructionValue ["offset"] [0].GetUnsignedInt();

                                prgDisassembly [currentInstruction].dwByteOffset = offset;

                                prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_BYTEOFFSET;
                            }

                            if ((dwFields & enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS) != 0)
                            {
                                prgDisassembly [currentInstruction].dwFlags |= enum_DISASSEMBLY_FLAGS.DF_HASSOURCE;

                                prgDisassembly [currentInstruction].dwFields |= enum_DISASSEMBLY_STREAM_FIELDS.DSF_FLAGS;
                            }

                            if (++currentInstruction >= maxInstructions)
                            {
                                break;
                            }
                        }
                    }
                }

                pdwInstructionsRead = (uint)currentInstruction;

                return(Constants.S_OK);
            }
            catch (Exception e)
            {
                LoggingUtils.HandleException(e);

                pdwInstructionsRead = 0;

                return(Constants.E_FAIL);
            }
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        private void RefreshBreakpoint(object breakpoint)
        {
            //
            // Validate breakpoint input type. This function can be used for 'bound' and 'error' objects, so we need to handle this appropriately.
            //

            LoggingUtils.PrintFunction();

            CLangDebuggeeBreakpointBound boundBreakpoint = null;

            CLangDebuggeeBreakpointError errorBreakpoint = null;

            MiBreakpoint gdbBreakpoint;

            DebuggeeBreakpointResolution resolution;

            if (breakpoint == null)
            {
                throw new ArgumentNullException("breakpoint");
            }
            else if (breakpoint is CLangDebuggeeBreakpointBound)
            {
                boundBreakpoint = breakpoint as CLangDebuggeeBreakpointBound;

                gdbBreakpoint = boundBreakpoint.GdbBreakpoint;

                IDebugBreakpointResolution2 boundBreakpointResolution;

                int handle = boundBreakpoint.GetBreakpointResolution(out boundBreakpointResolution);

                if (handle == Constants.E_BP_DELETED)
                {
                    return;
                }

                LoggingUtils.RequireOk(handle);

                resolution = (DebuggeeBreakpointResolution)boundBreakpointResolution;
            }
            else if (breakpoint is CLangDebuggeeBreakpointError)
            {
                errorBreakpoint = breakpoint as CLangDebuggeeBreakpointError;

                gdbBreakpoint = errorBreakpoint.GdbBreakpoint;

                IDebugErrorBreakpointResolution2 errorBreakpointResolution;

                int handle = errorBreakpoint.GetBreakpointResolution(out errorBreakpointResolution);

                if (handle == Constants.E_BP_DELETED)
                {
                    return;
                }

                resolution = (DebuggeeBreakpointResolution)errorBreakpointResolution;

                lock (m_errorBreakpoints)
                {
                    m_errorBreakpoints.Remove(errorBreakpoint);
                }
            }
            else
            {
                throw new ArgumentException("breakpoint");
            }

            //
            // Query breakpoint info/status directly from GDB/MI.
            //

            try
            {
                string command = string.Format("-break-info {0}", gdbBreakpoint.ID);

                m_debugger.GdbClient.SendCommand(command, delegate(MiResultRecord resultRecord)
                {
                    if (resultRecord == null)
                    {
                        throw new InvalidOperationException();
                    }
                    else if (resultRecord.IsError())
                    {
                        //
                        // GDB/MI breakpoint info request failed.
                        //

                        gdbBreakpoint.Address = MiBreakpoint.Pending;

                        (resolution as DebuggeeBreakpointResolution).CodeContext.Address = new DebuggeeAddress(gdbBreakpoint.Address);

                        errorBreakpoint = new CLangDebuggeeBreakpointError(m_debugger, m_breakpointManager, this, (resolution as DebuggeeBreakpointResolution).CodeContext, gdbBreakpoint, resultRecord.Records [1].Stream);

                        lock (m_errorBreakpoints)
                        {
                            m_errorBreakpoints.Add(errorBreakpoint);
                        }

                        m_debugger.Engine.Broadcast(new DebugEngineEvent.BreakpointError(errorBreakpoint), m_debugger.NativeProgram.DebugProgram, m_debugger.NativeProgram.GetThread(m_debugger.NativeProgram.CurrentThreadId));
                    }
                    else
                    {
                        //
                        // We've probably got sane breakpoint information back. Update current breakpoint values and re-process.
                        //

                        MiResultValue breakpointData = resultRecord ["BreakpointTable"] [0] ["body"] [0] ["bkpt"] [0];

                        MiBreakpoint currentGdbBreakpoint = new MiBreakpoint(breakpointData.Values);

                        DebuggeeCodeContext codeContext = (resolution as DebuggeeBreakpointResolution).CodeContext;

                        DebuggeeDocumentContext documentContext = codeContext.DocumentContext;

                        LoggingUtils.RequireOk(CreateBoundBreakpoint(currentGdbBreakpoint, documentContext, codeContext));
                    }
                });
            }
            catch (Exception e)
            {
                LoggingUtils.HandleException(e);
            }
        }