Example #1
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public int ReadAt(IDebugMemoryContext2 pStartContext, uint dwCount, byte [] rgbMemory, out uint pdwRead, ref uint pdwUnreadable)
        {
            //
            // Reads a sequence of bytes, starting at a given location.
            //

            LoggingUtils.PrintFunction();

            try
            {
                CONTEXT_INFO [] contextInfoArray = new CONTEXT_INFO [1];

                LoggingUtils.RequireOk(pStartContext.GetInfo(enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE, contextInfoArray));

                string command = string.Format("-data-read-memory-bytes {0} {1}", contextInfoArray [0].bstrAddressAbsolute, dwCount);

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

                MiResultRecord.RequireOk(resultRecord, command);

                MiResultValueList memoryStreamList = (MiResultValueList)resultRecord ["memory"] [0];

                for (int s = 0; s < memoryStreamList.Values.Count; ++s)
                {
                    if (!memoryStreamList [s].HasField("contents"))
                    {
                        throw new InvalidOperationException("-data-read-memory-bytes result missing 'contents' field");
                    }

                    string hexValue = memoryStreamList [s] ["contents"] [0].GetString();

                    if ((hexValue.Length / 2) != dwCount)
                    {
                        throw new InvalidOperationException();
                    }

                    for (int i = 0; i < dwCount; ++i)
                    {
                        rgbMemory [i] = byte.Parse(hexValue.Substring(i * 2, 2), NumberStyles.HexNumber);
                    }
                }

                pdwRead = dwCount;

                pdwUnreadable = 0;

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

                pdwRead = 0;

                pdwUnreadable = dwCount;

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

        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);
            }
        }
Example #3
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);
            }
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public override List <DebuggeeStackFrame> StackTrace(uint depth)
        {
            //
            // Each thread maintains an internal cache of the last reported stack-trace. This is only cleared when threads are resumed via 'SetRunning(true)'.
            //

            LoggingUtils.PrintFunction();

            try
            {
                if (m_threadStackFrames.Count < depth)
                {
                    LoggingUtils.RequireOk(GetThreadId(out uint threadId));

                    m_debugProgram.AttachedEngine.NativeDebugger.RunInterruptOperation(delegate(CLangDebugger debugger)
                    {
                        //
                        // Determine the maximum available stack depth.
                        //

                        string command;

                        MiResultRecord resultRecord;

                        if (depth == uint.MaxValue)
                        {
                            command = string.Format("-stack-info-depth --thread {0}", threadId);

                            resultRecord = debugger.GdbClient.SendSyncCommand(command);

                            MiResultRecord.RequireOk(resultRecord, command);

                            depth = resultRecord ["depth"] [0].GetUnsignedInt();
                        }

                        //
                        // Acquire stack frame information for any levels which we're missing.
                        //

                        if (m_threadStackFrames.Count < depth)
                        {
                            command = string.Format("-stack-list-frames --thread {0} {1} {2}", threadId, m_threadStackFrames.Count, depth - 1);

                            resultRecord = debugger.GdbClient.SendSyncCommand(command);

                            MiResultRecord.RequireOk(resultRecord, command);

                            if (resultRecord.HasField("stack"))
                            {
                                MiResultValueList stackRecord = resultRecord ["stack"] [0] as MiResultValueList;

                                for (int i = 0; i < stackRecord.Values.Count; ++i)
                                {
                                    MiResultValueTuple frameTuple = stackRecord [i] as MiResultValueTuple;

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

                                    string stackFrameId = m_threadName + "#" + stackLevel;

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

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

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

                throw;
            }
        }