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

        public int Subtract(ulong count, out IDebugMemoryContext2 offsetAddressContext)
        {
            //
            // Subtracts a specified value to the current context's address to create a new context.
            //

            LoggingUtils.PrintFunction();

            try
            {
                DebuggeeAddress offsetAddress = m_address.Subtract(count);

                offsetAddressContext = new DebuggeeCodeContext(m_engine, DocumentContext, offsetAddress);

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

                offsetAddressContext = null;

                return(Constants.E_FAIL);
            }
        }
Exemplo n.º 2
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public DebuggeeCodeContext(DebugEngine engine, DebuggeeDocumentContext documentContext, DebuggeeAddress address)
        {
            m_engine = engine;

            m_documentContext = documentContext ?? throw new ArgumentNullException(nameof(documentContext));

            m_address = address ?? throw new ArgumentNullException(nameof(address));
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public DebuggeeCodeContext(DebugEngine engine, DebuggeeDocumentContext documentContext, DebuggeeAddress address)
        {
            if (documentContext == null)
            {
                throw new ArgumentNullException("documentContext");
            }

            if (address == null)
            {
                throw new ArgumentNullException("address");
            }

            m_engine = engine;

            m_documentContext = documentContext;

            m_address = address;
        }
Exemplo n.º 4
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        private void GetInfoFromCurrentLevel(MiResultValueTuple frameTuple)
        {
            LoggingUtils.PrintFunction();

            try
            {
                if (frameTuple == null)
                {
                    throw new ArgumentNullException("frameTuple");
                }

                if (frameTuple.HasField("level"))
                {
                    m_stackLevel = frameTuple ["level"] [0].GetUnsignedInt();
                }

                //
                // Discover the function or shared library location.
                //

                if (frameTuple.HasField("addr"))
                {
                    m_locationAddress = new DebuggeeAddress(frameTuple ["addr"] [0].GetString());
                }
                else
                {
                    m_locationAddress = new DebuggeeAddress("0x0");
                }

                if (frameTuple.HasField("func"))
                {
                    m_locationFunction = frameTuple ["func"] [0].GetString();
                }
                else
                {
                    m_locationFunction = "??";
                }

                m_locationIsSymbolicated = !(m_locationFunction.Equals("??"));

                if (frameTuple.HasField("from"))
                {
                    m_locationModule = Path.GetFileName(frameTuple ["from"] [0].GetString());
                }
                else
                {
                    m_locationModule = string.Empty;
                }

                //
                // Generate code and document contexts for this frame location.
                //

                if (frameTuple.HasField("fullname") && frameTuple.HasField("line"))
                {
                    //
                    // If the symbol table isn't yet loaded, we'll need to specify exactly the location of this stack frame.
                    //

                    TEXT_POSITION [] textPositions = new TEXT_POSITION [2];

                    textPositions [0].dwLine = frameTuple ["line"] [0].GetUnsignedInt() - 1;

                    textPositions [0].dwColumn = 0;

                    textPositions [1].dwLine = textPositions [0].dwLine;

                    textPositions [1].dwColumn = textPositions [0].dwColumn;

                    string filename = PathUtils.ConvertPathCygwinToWindows(frameTuple ["fullname"] [0].GetString());

                    m_documentContext = new DebuggeeDocumentContext(m_debugger.Engine, filename, textPositions [0], textPositions [1]);

                    m_codeContext = CLangDebuggeeCodeContext.GetCodeContextForLocation(m_debugger, m_locationAddress.ToString());

                    if (m_codeContext == null)
                    {
                        throw new InvalidOperationException();
                    }
                }
                else
                {
                    m_codeContext = CLangDebuggeeCodeContext.GetCodeContextForLocation(m_debugger, m_locationAddress.ToString());

                    m_documentContext = (m_codeContext != null) ? m_codeContext.DocumentContext : null;
                }
            }
            catch (Exception e)
            {
                LoggingUtils.HandleException(e);
            }
        }
Exemplo n.º 5
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public CLangDebuggeeCodeContext(CLangDebugger debugger, DebuggeeAddress address, DebuggeeDocumentContext documentContext)
            : base(debugger.Engine, documentContext, address)
        {
            m_debugger = debugger;

            try
            {
                string command = string.Format("-interpreter-exec console \"info symbol {0}\"", m_address.ToString());

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

                MiResultRecord.RequireOk(resultRecord, command);

                string pattern = "(?<symbol>.+)( [\\+] (?<offset>[0-9]+))? (in section (?<section>[^ ]+) of) (?<module>.+)";

                Regex regExMatcher = new Regex(pattern, RegexOptions.IgnoreCase);

                foreach (MiStreamRecord record in resultRecord.Records)
                {
                    if (!record.Stream.StartsWith("No symbol"))
                    {
                        continue; // early rejection.
                    }

                    StringBuilder sanitisedStream = new StringBuilder(record.Stream);

                    sanitisedStream.Length -= 2; // Strip trailing "\\n"

                    Match regExLineMatch = regExMatcher.Match(sanitisedStream.ToString());

                    if (regExLineMatch.Success)
                    {
                        string symbol = regExLineMatch.Result("${symbol}");

                        string offset = regExLineMatch.Result("${offset}");

                        string section = regExLineMatch.Result("${section}");

                        string module = regExLineMatch.Result("${module}");

                        ulong addressOffset = 0ul;

                        ulong.TryParse(offset, out addressOffset);

                        m_symbolName = symbol;

                        m_symbolOffset = addressOffset.ToString();

                        //string moduleFile = Path.GetFileName (module);

                        //CLangDebuggeeModule module = m_debugger.NativeProgram.GetModule (moduleFile);

                        //MODULE_INFO [] moduleArray = new MODULE_INFO [1];

                        //LoggingUtils.RequireOk (module.GetInfo (enum_MODULE_INFO_FIELDS.MIF_URL, moduleArray));

                        //infoArray [0].bstrModuleUrl = moduleArray [0].m_bstrUrl;

                        m_symbolModule = PathUtils.ConvertPathMingwToWindows(module);
                    }
                }
            }
            catch (Exception e)
            {
                LoggingUtils.HandleException(e);
            }
        }
Exemplo n.º 6
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public static CLangDebuggeeCodeContext GetCodeContextForLocation(CLangDebugger debugger, string location)
        {
            LoggingUtils.PrintFunction();

            try
            {
                if (string.IsNullOrEmpty(location))
                {
                    throw new ArgumentNullException("location");
                }

                if (location.StartsWith("0x"))
                {
                    location = "*" + location;
                }
                else if (location.StartsWith("\""))
                {
                    location = location.Replace("\\", "/");

                    location = location.Replace("\"", "\\\""); // required to escape the nested string.
                }

                string command = string.Format("-interpreter-exec console \"info line {0}\"", location);

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

                MiResultRecord.RequireOk(resultRecord, command);

                string pattern = "Line (?<line>[0-9]+) of ([\\]*\"(?<file>.+)[\\]*[\"]+) starts at address (?<startaddr>[^ ]+) (?<startsym>[^+]+[+]?[0-9]*[>]?) (but contains no code|and ends at (?<endaddr>[^ ]+) (?<endsym>[^+]+[+]?[0-9]*[>]?)?)";

                pattern = pattern.Replace("\\", "\\\\");

                Regex regExMatcher = new Regex(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase);

                foreach (MiStreamRecord record in resultRecord.Records)
                {
                    if (!record.Stream.StartsWith("Line"))
                    {
                        continue; // early rejection.
                    }

                    StringBuilder sanitisedStream = new StringBuilder(record.Stream);

                    sanitisedStream.Replace("\\\"", "\"");

                    sanitisedStream.Replace("\\\\", "\\");

                    Match regExLineMatch = regExMatcher.Match(sanitisedStream.ToString());

                    if (regExLineMatch.Success)
                    {
                        string line = regExLineMatch.Result("${line}");

                        string file = regExLineMatch.Result("${file}");

                        string startaddr = regExLineMatch.Result("${startaddr}");

                        string startsym = regExLineMatch.Result("${startsym}");

                        string endaddr = regExLineMatch.Result("${endaddr}");

                        string endsym = regExLineMatch.Result("${endsym}");

                        TEXT_POSITION [] documentPositions = new TEXT_POSITION [2];

                        documentPositions [0].dwLine = uint.Parse(line) - 1;

                        documentPositions [0].dwColumn = 0;

                        documentPositions [1].dwLine = documentPositions [0].dwLine;

                        documentPositions [1].dwColumn = uint.MaxValue;

                        DebuggeeAddress startAddress = new DebuggeeAddress(startaddr);

                        DebuggeeDocumentContext documentContext = new DebuggeeDocumentContext(debugger.Engine, file, documentPositions [0], documentPositions [1]);

                        CLangDebuggeeCodeContext codeContext = new CLangDebuggeeCodeContext(debugger, startAddress, documentContext);

                        documentContext.SetCodeContext(codeContext);

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

            return(null);
        }
Exemplo n.º 7
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 int CreateBoundBreakpoint(MiBreakpoint breakpoint, DebuggeeDocumentContext documentContext, DebuggeeCodeContext codeContext)
        {
            LoggingUtils.PrintFunction();

            try
            {
                if (breakpoint == null)
                {
                    throw new ArgumentNullException("breakpoint");
                }

                if (breakpoint.IsPending())
                {
                    //
                    // Address can't be satisfied. Unsatisfied likely indicates the modules or symbols associated with the context aren't loaded, yet.
                    //

                    DebuggeeAddress pendingAddress = new DebuggeeAddress(MiBreakpoint.Pending);

                    DebuggeeCodeContext pendingContext = new CLangDebuggeeCodeContext(m_debugger, pendingAddress, documentContext);

                    LoggingUtils.RequireOk(CreateErrorBreakpoint("Additional library symbols required.", breakpoint, documentContext, pendingContext));
                }
                else if (breakpoint.IsMultiple())
                {
                    //
                    // Breakpoint satisfied to multiple locations, no single memory address available.
                    //

                    CLangDebuggeeBreakpointBound boundBreakpoint = new CLangDebuggeeBreakpointBound(m_debugger, m_breakpointManager, this, codeContext, breakpoint);

                    lock (m_boundBreakpoints)
                    {
                        m_boundBreakpoints.Clear();

                        m_boundBreakpoints.Add(boundBreakpoint);
                    }

                    m_debugger.Engine.Broadcast(new DebugEngineEvent.BreakpointBound(this, boundBreakpoint), m_debugger.NativeProgram.DebugProgram, m_debugger.NativeProgram.GetThread(m_debugger.NativeProgram.CurrentThreadId));
                }
                else
                {
                    //
                    // Address satisfied, and the breakpoint is legitimately bound.
                    //

                    DebuggeeAddress boundAddress = new DebuggeeAddress(breakpoint.Address);

                    DebuggeeCodeContext addressContext = new CLangDebuggeeCodeContext(m_debugger, boundAddress, documentContext);

                    CLangDebuggeeBreakpointBound boundBreakpoint = new CLangDebuggeeBreakpointBound(m_debugger, m_breakpointManager, this, addressContext, breakpoint);

                    lock (m_boundBreakpoints)
                    {
                        m_boundBreakpoints.Clear();

                        m_boundBreakpoints.Add(boundBreakpoint);
                    }

                    m_debugger.Engine.Broadcast(new DebugEngineEvent.BreakpointBound(this, boundBreakpoint), m_debugger.NativeProgram.DebugProgram, m_debugger.NativeProgram.GetThread(m_debugger.NativeProgram.CurrentThreadId));
                }

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

                return(Constants.E_FAIL);
            }
        }