// Gets the file statement range of the document context.
        // A statement range is the range of the lines that contributed the code to which this document context refers.
        int IDebugDocumentContext2.GetStatementRange(TEXT_POSITION[] pBegPosition, TEXT_POSITION[] pEndPosition)
        {
            try
            {
                pBegPosition[0].dwColumn = m_begPos.dwColumn;
                pBegPosition[0].dwLine   = m_begPos.dwLine;

                pEndPosition[0].dwColumn = m_endPos.dwColumn;
                pEndPosition[0].dwLine   = m_endPos.dwLine;
            }
            catch (ComponentException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }

            return(Constants.S_OK);
        }
        // Gets information that describes this context.
        public int GetInfo(enum_CONTEXT_INFO_FIELDS dwFields, CONTEXT_INFO[] pinfo)
        {
            try
            {
                pinfo[0].dwFields = 0;

                if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS) != 0)
                {
                    pinfo[0].bstrAddress = m_address.ToString();
                    pinfo[0].dwFields   |= enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS;
                }

                // Fields not supported by the sample
                if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSOFFSET) != 0)
                {
                }
                if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE) != 0)
                {
                }
                if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_MODULEURL) != 0)
                {
                }
                if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_FUNCTION) != 0)
                {
                }
                if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_FUNCTIONOFFSET) != 0)
                {
                }

                return(Constants.S_OK);
            }
            catch (ComponentException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
        // Compares the memory context to each context in the given array in the manner indicated by compare flags,
        // returning an index of the first context that matches.
        public int Compare(enum_CONTEXT_COMPARE uContextCompare, IDebugMemoryContext2[] compareToItems, uint compareToLength, out uint foundIndex)
        {
            foundIndex = uint.MaxValue;

            try
            {
                enum_CONTEXT_COMPARE contextCompare = (enum_CONTEXT_COMPARE)uContextCompare;

                for (uint c = 0; c < compareToLength; c++)
                {
                    AD7MemoryAddress compareTo = compareToItems[c] as AD7MemoryAddress;
                    if (compareTo == null)
                    {
                        continue;
                    }

                    if (!AD7Engine.ReferenceEquals(this.m_engine, compareTo.m_engine))
                    {
                        continue;
                    }

                    bool result;

                    switch (contextCompare)
                    {
                    case enum_CONTEXT_COMPARE.CONTEXT_EQUAL:
                        result = (this.m_address == compareTo.m_address);
                        break;

                    case enum_CONTEXT_COMPARE.CONTEXT_LESS_THAN:
                        result = (this.m_address < compareTo.m_address);
                        break;

                    case enum_CONTEXT_COMPARE.CONTEXT_GREATER_THAN:
                        result = (this.m_address > compareTo.m_address);
                        break;

                    case enum_CONTEXT_COMPARE.CONTEXT_LESS_THAN_OR_EQUAL:
                        result = (this.m_address <= compareTo.m_address);
                        break;

                    case enum_CONTEXT_COMPARE.CONTEXT_GREATER_THAN_OR_EQUAL:
                        result = (this.m_address >= compareTo.m_address);
                        break;

                    // The sample debug engine doesn't understand scopes or functions
                    case enum_CONTEXT_COMPARE.CONTEXT_SAME_SCOPE:
                    case enum_CONTEXT_COMPARE.CONTEXT_SAME_FUNCTION:
                        result = (this.m_address == compareTo.m_address);
                        break;

                    case enum_CONTEXT_COMPARE.CONTEXT_SAME_MODULE:
                        result = (this.m_address == compareTo.m_address);
                        if (result == false)
                        {
                            DebuggedModule module = m_engine.DebuggedProcess.ResolveAddress(m_address);

                            if (module != null)
                            {
                                result = (compareTo.m_address >= module.BaseAddress) &&
                                         (compareTo.m_address < module.BaseAddress + module.Size);
                            }
                        }
                        break;

                    case enum_CONTEXT_COMPARE.CONTEXT_SAME_PROCESS:
                        result = true;
                        break;

                    default:
                        // A new comparison was invented that we don't support
                        return(Constants.E_NOTIMPL);
                    }

                    if (result)
                    {
                        foundIndex = c;
                        return(Constants.S_OK);
                    }
                }

                return(Constants.S_FALSE);
            }
            catch (ComponentException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
        // Construct a FRAMEINFO for this stack frame with the requested information.
        public void SetFrameInfo(enum_FRAMEINFO_FLAGS dwFieldSpec, out FRAMEINFO frameInfo)
        {
            frameInfo = new FRAMEINFO();

            uint ip = m_threadContext.eip;
            DebuggedModule module = m_engine.DebuggedProcess.ResolveAddress(ip);

            // The debugger is asking for the formatted name of the function which is displayed in the callstack window.
            // There are several optional parts to this name including the module, argument types and values, and line numbers.
            // The optional information is requested by setting flags in the dwFieldSpec parameter.
            if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME) != 0)
            {
                // If there is source information, construct a string that contains the module name, function name, and optionally argument names and values.
                if (m_hasSource)
                {
                    frameInfo.m_bstrFuncName = "";

                    if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_MODULE) != 0)
                    {
                        frameInfo.m_bstrFuncName = System.IO.Path.GetFileName(module.Name) + "!";
                    }

                    frameInfo.m_bstrFuncName += m_functionName;

                    if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS) != 0 && m_numParameters > 0)
                    {
                        frameInfo.m_bstrFuncName += "(";
                        for (int i = 0; i < m_parameters.Length; i++)
                        {
                            if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_TYPES) != 0)
                            {
                                frameInfo.m_bstrFuncName += m_parameters[i].m_typeName + " ";
                            }

                            if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_NAMES) != 0)
                            {
                                frameInfo.m_bstrFuncName += m_parameters[i].m_name;
                            }

                            if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_VALUES) != 0)
                            {
                                frameInfo.m_bstrFuncName += "=" + m_parameters[i].m_value;
                            }

                            if (i < m_parameters.Length - 1)
                            {
                                frameInfo.m_bstrFuncName += ", ";
                            }
                        }
                        frameInfo.m_bstrFuncName += ")";
                    }

                    if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_LINES) != 0)
                    {
                        frameInfo.m_bstrFuncName += " Line:" + m_lineNum.ToString();
                    }
                }
                else
                {
                    // No source information, so only return the module name and the instruction pointer.
                    if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_MODULE) != 0)
                    {
                        frameInfo.m_bstrFuncName = EngineUtils.GetAddressDescription(module, ip);
                    }
                    else
                    {
                        frameInfo.m_bstrFuncName = EngineUtils.GetAddressDescription(null, ip);
                    }
                }
                frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_FUNCNAME;
            }

            // The debugger is requesting the name of the module for this stack frame.
            if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_MODULE) != 0 && module != null)
            {
                frameInfo.m_bstrModule = module.Name;
                frameInfo.m_dwValidFields |=  enum_FRAMEINFO_FLAGS.FIF_MODULE;
            }

            // The debugger is requesting the range of memory addresses for this frame.
            // For the sample engine, this is the contents of the frame pointer.
            if ((dwFieldSpec &  enum_FRAMEINFO_FLAGS.FIF_STACKRANGE) != 0)
            {
                frameInfo.m_addrMin = m_threadContext.ebp;
                frameInfo.m_addrMax = m_threadContext.ebp;
                frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_STACKRANGE;
            }

            // The debugger is requesting the IDebugStackFrame2 value for this frame info.
            if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FRAME) != 0)
            {
                frameInfo.m_pFrame = this;
                frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_FRAME;
            }

            // Does this stack frame of symbols loaded?
            if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_DEBUGINFO) != 0)
            {
                frameInfo.m_fHasDebugInfo = m_hasSource ? 1 : 0;
                frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_DEBUGINFO;
            }

            // Is this frame stale?
            if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_STALECODE) != 0)
            {
                frameInfo.m_fStaleCode = 0;
                frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_STALECODE;
            }

            // The debugger would like a pointer to the IDebugModule2 that contains this stack frame.
            if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_DEBUG_MODULEP) != 0)
            {
                if (module != null)
                {
                    AD7Module ad7Module = (AD7Module)module.Client;
                    Debug.Assert(ad7Module != null);
                    frameInfo.m_pModule = ad7Module;
                    frameInfo.m_dwValidFields |= enum_FRAMEINFO_FLAGS.FIF_DEBUG_MODULEP;
                }
            }
        }
        // Binds this pending breakpoint to one or more code locations.
        int IDebugPendingBreakpoint2.Bind()
        {
            try
            {
                if (CanBind())
                {
                    IDebugDocumentPosition2 docPosition = (IDebugDocumentPosition2)(Marshal.GetObjectForIUnknown(m_bpRequestInfo.bpLocation.unionmember2));

                    // Get the name of the document that the breakpoint was put in
                    string documentName;
                    EngineUtils.CheckOk(docPosition.GetFileName(out documentName));

                    // Get the location in the document that the breakpoint is in.
                    TEXT_POSITION[] startPosition = new TEXT_POSITION[1];
                    TEXT_POSITION[] endPosition   = new TEXT_POSITION[1];
                    EngineUtils.CheckOk(docPosition.GetRange(startPosition, endPosition));


                    // Ask the symbol engine to find all addresses in all modules with symbols that match this source and line number.
                    uint[] addresses = m_engine.DebuggedProcess.GetAddressesForSourceLocation(null,
                                                                                              documentName,
                                                                                              startPosition[0].dwLine + 1,
                                                                                              startPosition[0].dwColumn);
                    lock (m_boundBreakpoints)
                    {
                        if (addresses.Length > 0)
                        {
                            foreach (uint addr in addresses)
                            {
                                AD7BreakpointResolution breakpointResolution = new AD7BreakpointResolution(m_engine, addr, GetDocumentContext(addr));
                                AD7BoundBreakpoint      boundBreakpoint      = new AD7BoundBreakpoint(m_engine, addr, this, breakpointResolution);
                                m_boundBreakpoints.Add(boundBreakpoint);
                                m_engine.DebuggedProcess.SetBreakpoint(addr, boundBreakpoint);
                            }
                        }
                        else
                        {
                            // A real debug engine should send a warning breakpoint here
                        }
                    }

                    return(Constants.S_OK);
                }
                else
                {
                    // The breakpoint could not be bound. This may occur for many reasons such as an invalid location, an invalid expression, etc...
                    // The sample engine does not support this, but a real world engine will want to send an instance of IDebugBreakpointErrorEvent2 to the
                    // UI and return a valid instance of IDebugErrorBreakpoint2 from IDebugPendingBreakpoint2::EnumErrorBreakpoints. The debugger will then
                    // display information about why the breakpoint did not bind to the user.
                    return(Constants.S_FALSE);
                }
            }
            catch (ComponentException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Example #6
0
        // Parses a text-based expression for evaluation.
        // The engine sample only supports locals and parameters so the only task here is to check the names in those collections.
        int IDebugExpressionContext2.ParseText(string pszCode,
                                               enum_PARSEFLAGS dwFlags,
                                               uint nRadix,
                                               out IDebugExpression2 ppExpr,
                                               out string pbstrError,
                                               out uint pichError)
        {
            pbstrError = "";
            pichError  = 0;
            ppExpr     = null;

            if (IsDebuggingNPL())
            {
                VariableInformation varInfo = VariableInformation.Create(m_engine.DebuggedProcess, pszCode);
                if (varInfo != null)
                {
                    ppExpr = new AD7Expression(varInfo);
                    return(Constants.S_OK);
                }
                else
                {
                    return(Constants.S_FALSE);
                }
            }

            try
            {
                if (m_parameters != null)
                {
                    foreach (VariableInformation currVariable in m_parameters)
                    {
                        if (String.CompareOrdinal(currVariable.m_name, pszCode) == 0)
                        {
                            ppExpr = new AD7Expression(currVariable);
                            return(Constants.S_OK);
                        }
                    }
                }

                if (m_locals != null)
                {
                    foreach (VariableInformation currVariable in m_locals)
                    {
                        if (String.CompareOrdinal(currVariable.m_name, pszCode) == 0)
                        {
                            ppExpr = new AD7Expression(currVariable);
                            return(Constants.S_OK);
                        }
                    }
                }

                pbstrError = "Invalid Expression";
                pichError  = (uint)pbstrError.Length;
                return(Constants.S_FALSE);
            }
            catch (ComponentException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Example #7
0
        // Attach the debug engine to a program.
        int IDebugEngine2.Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 ad7Callback, enum_ATTACH_REASON dwReason)
        {
            Debug.Assert(Worker.MainThreadId == Worker.CurrentThreadId);
            Debug.Assert(m_ad7ProgramId == Guid.Empty);

            if (celtPrograms != 1)
            {
                Debug.Fail("SampleEngine only expects to see one program in a process");
                throw new ArgumentException();
            }

            try
            {
                int processId = EngineUtils.GetProcessId(rgpPrograms[0]);
                if (processId == 0)
                {
                    return(Constants.E_NOTIMPL); // sample engine only supports system processes
                }

                EngineUtils.RequireOk(rgpPrograms[0].GetProgramId(out m_ad7ProgramId));

                // Attach can either be called to attach to a new process, or to complete an attach
                // to a launched process
                if (m_pollThread == null)
                {
                    // We are being asked to debug a process when we currently aren't debugging anything
                    m_pollThread = new WorkerThread();

                    m_engineCallback = new EngineCallback(this, ad7Callback);

                    // Complete the win32 attach on the poll thread
                    m_pollThread.RunOperation(new Operation(delegate
                    {
                        m_debuggedProcess = Worker.AttachToProcess(m_engineCallback, processId);
                    }));

                    m_pollThread.SetDebugProcess(m_debuggedProcess);
                }
                else
                {
                    if (processId != m_debuggedProcess.Id)
                    {
                        Debug.Fail("Asked to attach to a process while we are debugging");
                        return(Constants.E_FAIL);
                    }

                    m_pollThread.SetDebugProcess(m_debuggedProcess);
                }

                AD7EngineCreateEvent.Send(this);
                AD7ProgramCreateEvent.Send(this);

                // start polling for debug events on the poll thread
                m_pollThread.RunOperationAsync(new Operation(delegate
                {
                    m_debuggedProcess.ResumeEventPump();
                }));

                return(Constants.S_OK);
            }
            catch (ComponentException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Example #8
0
        public string GetAddressDescription(uint ip)
        {
            DebuggedModule module = m_debuggedProcess.ResolveAddress(ip);

            return(EngineUtils.GetAddressDescription(module, ip));
        }
Example #9
0
        // Gets the MODULE_INFO that describes this module.
        // This is how the debugger obtains most of the information about the module.
        int IDebugModule2.GetInfo(enum_MODULE_INFO_FIELDS dwFields, MODULE_INFO[] infoArray)
        {
            try
            {
                MODULE_INFO info = new MODULE_INFO();

                if ((dwFields & enum_MODULE_INFO_FIELDS.MIF_NAME) != 0)
                {
                    info.m_bstrName     = System.IO.Path.GetFileName(this.DebuggedModule.Name);
                    info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_NAME;
                }
                if ((dwFields & enum_MODULE_INFO_FIELDS.MIF_URL) != 0)
                {
                    info.m_bstrUrl      = this.DebuggedModule.Name;
                    info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_URL;
                }
                if ((dwFields & enum_MODULE_INFO_FIELDS.MIF_LOADADDRESS) != 0)
                {
                    info.m_addrLoadAddress = (ulong)this.DebuggedModule.BaseAddress;
                    info.dwValidFields    |= enum_MODULE_INFO_FIELDS.MIF_LOADADDRESS;
                }
                if ((dwFields & enum_MODULE_INFO_FIELDS.MIF_PREFFEREDADDRESS) != 0)
                {
                    // A debugger that actually supports showing the preferred base should crack the PE header and get
                    // that field. This debugger does not do that, so assume the module loaded where it was suppose to.
                    info.m_addrPreferredLoadAddress = (ulong)this.DebuggedModule.BaseAddress;
                    info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_PREFFEREDADDRESS;;
                }
                if ((dwFields & enum_MODULE_INFO_FIELDS.MIF_SIZE) != 0)
                {
                    info.m_dwSize       = this.DebuggedModule.Size;
                    info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_SIZE;
                }
                if ((dwFields & enum_MODULE_INFO_FIELDS.MIF_LOADORDER) != 0)
                {
                    info.m_dwLoadOrder  = this.DebuggedModule.GetLoadOrder();
                    info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_LOADORDER;
                }
                if ((dwFields & enum_MODULE_INFO_FIELDS.MIF_URLSYMBOLLOCATION) != 0)
                {
                    if (this.DebuggedModule.SymbolsLoaded)
                    {
                        info.m_bstrUrlSymbolLocation = this.DebuggedModule.SymbolPath;
                        info.dwValidFields          |= enum_MODULE_INFO_FIELDS.MIF_URLSYMBOLLOCATION;
                    }
                }
                if ((dwFields & enum_MODULE_INFO_FIELDS.MIF_FLAGS) != 0)
                {
                    info.m_dwModuleFlags = 0;
                    if (this.DebuggedModule.SymbolsLoaded)
                    {
                        info.m_dwModuleFlags |= (enum_MODULE_FLAGS.MODULE_FLAG_SYMBOLS);
                    }
                    info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_FLAGS;
                }


                infoArray[0] = info;

                return(Constants.S_OK);
            }
            catch (ComponentException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }