예제 #1
0
        // This function is used to terminate a process that the SampleEngine launched
        // The debugger will call IDebugEngineLaunch2::CanTerminateProcess before calling this method.
        int IDebugEngineLaunch2.TerminateProcess(IDebugProcess2 process)
        {
            /*Debug.Assert(Worker.MainThreadId == Worker.CurrentThreadId);
             * Debug.Assert(m_pollThread != null);
             * Debug.Assert(m_engineCallback != null);*/
            Debug.Assert(debuggedProcess != null);

            try
            {
                int processId = EngineUtils.GetProcessId(process);
                if (processId != debuggedProcess.Id)
                {
                    return(EngineConstants.S_FALSE);
                }

                debuggedProcess.Terminate();

                return(EngineConstants.S_OK);
            }
            catch (ComponentException e)
            {
                return(e.HRESULT);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
예제 #2
0
        // Gets the document context for this stack frame. The debugger will call this when the current stack frame is changed
        // and will use it to open the correct source document for this stack frame.
        int IDebugStackFrame2.GetDocumentContext(out IDebugDocumentContext2 docContext)
        {
            docContext = null;
            try
            {
                if (sqframe.Source != "NATIVE")
                {
                    // Assume all lines begin and end at the beginning of the line.
                    TEXT_POSITION begTp = new TEXT_POSITION();
                    begTp.dwColumn = 0;
                    begTp.dwLine   = (uint)sqframe.Line - 1;
                    TEXT_POSITION endTp = new TEXT_POSITION();
                    endTp.dwColumn = 0;
                    endTp.dwLine   = (uint)sqframe.Line - 1;

                    docContext = new AD7DocumentContext(sqframe.Source, begTp, endTp, null);
                    return(EngineConstants.S_OK);
                }
            }
            catch (ComponentException e)
            {
                return(e.HRESULT);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }

            return(EngineConstants.S_FALSE);
        }
예제 #3
0
        // Resume a process launched by IDebugEngineLaunch2.LaunchSuspended
        int IDebugEngineLaunch2.ResumeProcess(IDebugProcess2 process)
        {
            //Debug.Assert(Worker.MainThreadId == Worker.CurrentThreadId);

            /*Debug.Assert(m_pollThread != null);
             * Debug.Assert(m_engineCallback != null);
             * Debug.Assert(m_debuggedProcess != null);
             * Debug.Assert(m_ad7ProgramId == Guid.Empty);*/

            try
            {
                int processId = EngineUtils.GetProcessId(process);

                if (processId != debuggedProcess.Id)
                {
                    return(EngineConstants.S_FALSE);
                }

                // Send a program node to the SDM. This will cause the SDM to turn around and call IDebugEngine2.Attach
                // which will complete the hookup with AD7
                IDebugPort2 port;
                EngineUtils.RequireOk(process.GetPort(out port));

                IDebugDefaultPort2 defaultPort = (IDebugDefaultPort2)port;

                IDebugPortNotify2 portNotify;
                EngineUtils.RequireOk(defaultPort.GetPortNotify(out portNotify));

                EngineUtils.RequireOk(portNotify.AddProgramNode(new AD7ProgramNode(debuggedProcess.Id)));

                if (m_ad7ProgramId == Guid.Empty)
                {
                    Debug.Fail("Unexpected problem -- IDebugEngine2.Attach wasn't called");
                    return(EngineConstants.E_FAIL);
                }

                debuggedProcess.ResumeFromLaunch();

                // Resume the threads in the debuggee process

                /*m_pollThread.RunOperation(new Operation(delegate
                 * {
                 *  m_debuggedProcess.ResumeFromLaunch();
                 * }));*/

                return(EngineConstants.S_OK);
            }
            catch (ComponentException e)
            {
                return(e.HRESULT);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
        // 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)
                    {
                        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);
                            ((IDebugBoundBreakpoint2)boundBreakpoint).Enable(m_enabled ? 1 : 0);
                        }
                    }

                    return(EngineConstants.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(EngineConstants.S_FALSE);
                }
            }
            catch (ComponentException e)
            {
                return(e.HRESULT);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
예제 #5
0
        // Gets properties that describe a thread.
        int IDebugThread2.GetThreadProperties(uint dwFields, THREADPROPERTIES[] propertiesArray)
        {
            try
            {
                THREADPROPERTIES props = new THREADPROPERTIES();

                if ((dwFields & (uint)enum_THREADPROPERTY_FIELDS.TPF_ID) != 0)
                {
                    props.dwThreadId = (uint)m_debuggedThread.Id;
                    props.dwFields  |= (uint)enum_THREADPROPERTY_FIELDS.TPF_ID;
                }
                if ((dwFields & (uint)enum_THREADPROPERTY_FIELDS.TPF_SUSPENDCOUNT) != 0)
                {
                    // sample debug engine doesn't support suspending threads
                    props.dwFields |= (uint)enum_THREADPROPERTY_FIELDS.TPF_SUSPENDCOUNT;
                }
                if ((dwFields & (uint)enum_THREADPROPERTY_FIELDS.TPF_STATE) != 0)
                {
                    props.dwThreadState = (uint)enum_THREADSTATE.THREADSTATE_RUNNING;
                    props.dwFields     |= (uint)enum_THREADPROPERTY_FIELDS.TPF_STATE;
                }
                if ((dwFields & (uint)enum_THREADPROPERTY_FIELDS.TPF_PRIORITY) != 0)
                {
                    props.bstrPriority = "Normal";
                    props.dwFields    |= (uint)enum_THREADPROPERTY_FIELDS.TPF_PRIORITY;
                }
                if ((dwFields & (uint)enum_THREADPROPERTY_FIELDS.TPF_NAME) != 0)
                {
                    props.bstrName  = ThreadNameString;
                    props.dwFields |= (uint)enum_THREADPROPERTY_FIELDS.TPF_NAME;
                }
                if ((dwFields & (uint)enum_THREADPROPERTY_FIELDS.TPF_LOCATION) != 0)
                {
                    props.bstrLocation = GetCurrentLocation(true);
                    props.dwFields    |= (uint)enum_THREADPROPERTY_FIELDS.TPF_LOCATION;
                }

                return(EngineConstants.S_OK);
            }
            catch (ComponentException e)
            {
                return(e.HRESULT);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
예제 #6
0
        // Creates a pending breakpoint in the engine. A pending breakpoint is contains all the information needed to bind a breakpoint to
        // a location in the debuggee.
        int IDebugEngine2.CreatePendingBreakpoint(IDebugBreakpointRequest2 pBPRequest, out IDebugPendingBreakpoint2 ppPendingBP)
        {
            Debug.Assert(m_breakpointManager != null);
            ppPendingBP = null;

            try
            {
                m_breakpointManager.CreatePendingBreakpoint(pBPRequest, out ppPendingBP);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }

            return(EngineConstants.S_OK);
        }
예제 #7
0
        // Gets a description of the stack frame.
        int IDebugStackFrame2.GetInfo(enum_FRAMEINFO_FLAGS dwFieldSpec, uint nRadix, FRAMEINFO[] pFrameInfo)
        {
            try
            {
                SetFrameInfo(dwFieldSpec, out pFrameInfo[0]);

                return(EngineConstants.S_OK);
            }
            catch (ComponentException e)
            {
                return(e.HRESULT);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
예제 #8
0
        // Retrieves a list of the stack frames for this thread.
        // For the sample engine, enumerating the stack frames requires walking the callstack in the debuggee for this thread
        // and coverting that to an implementation of IEnumDebugFrameInfo2.
        // Real engines will most likely want to cache this information to avoid recomputing it each time it is asked for,
        // and or construct it on demand instead of walking the entire stack.
        int IDebugThread2.EnumFrameInfo(enum_FRAMEINFO_FLAGS dwFieldSpec, uint nRadix, out IEnumDebugFrameInfo2 enumObject)
        {
            // Ask the lower-level to perform a stack walk on this thread
            // m_engine.DebuggedProcess.DoStackWalk(this.m_debuggedThread);
            enumObject = null;

            try
            {
                //AD7StackFrame[] stackFrames = this.stackFrames;
                //System.Collections.Generic.List<X86ThreadContext> stackFrames = this.m_debuggedThread.StackFrames;
                int         numStackFrames = sqframes.Count;
                FRAMEINFO[] frameInfoArray;

                if (numStackFrames == 0)
                {
                    // failed to walk any frames. Only return the top frame.
                    frameInfoArray = new FRAMEINFO[1];
                    AD7StackFrame frame = new AD7StackFrame(engine, this, ctx, new SquirrelStackFrame());
                    frame.SetFrameInfo(dwFieldSpec, out frameInfoArray[0]);
                    return(EngineConstants.E_FAIL);
                }
                else
                {
                    frameInfoArray = new FRAMEINFO[numStackFrames];

                    for (int i = 0; i < numStackFrames; i++)
                    {
                        AD7StackFrame frame = new AD7StackFrame(engine, this, ctx, sqframes[i]);
                        frame.SetFrameInfo(dwFieldSpec, out frameInfoArray[i]);
                    }
                }

                enumObject = new AD7FrameInfoEnum(frameInfoArray);
                return(EngineConstants.S_OK);
            }
            catch (ComponentException e)
            {
                return(e.HRESULT);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
            throw new NotImplementedException();
        }
예제 #9
0
        // Gets the code context for this stack frame. The code context represents the current instruction pointer in this stack frame.
        int IDebugStackFrame2.GetCodeContext(out IDebugCodeContext2 memoryAddress)
        {
            memoryAddress = null;

            try
            {
                memoryAddress = new AD7MemoryAddress(m_engine, (uint)sqframe.Address);
                return(EngineConstants.S_OK);
            }
            catch (ComponentException e)
            {
                return(e.HRESULT);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
예제 #10
0
        // Gets the name of the stack frame.
        // The name of a stack frame is typically the name of the method being executed.
        int IDebugStackFrame2.GetName(out string name)
        {
            name = null;

            try
            {
                name = sqframe.Function;// EngineUtils.GetAddressDescription(null, sqframe.Address);

                return(EngineConstants.S_OK);
            }
            catch (ComponentException e)
            {
                return(e.HRESULT);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
예제 #11
0
        // Creates an enumerator for properties associated with the stack frame, such as local variables.
        // The sample engine only supports returning locals and parameters. Other possible values include
        // class fields (this pointer), registers, exceptions...
        int IDebugStackFrame2.EnumProperties(enum_DEBUGPROP_INFO_FLAGS dwFields, uint nRadix, ref Guid guidFilter, uint dwTimeout, out uint elementsReturned, out IEnumDebugPropertyInfo2 enumObject)
        {
            int hr;

            elementsReturned = 0;
            enumObject       = null;
            bool hex = nRadix == 16;

            try
            {
                if (guidFilter == AD7Guids.guidFilterLocalsPlusArgs ||
                    guidFilter == AD7Guids.guidFilterAllLocalsPlusArgs ||
                    guidFilter == AD7Guids.guidFilterAllLocals)
                {
                    CreateLocalsPlusArgsProperties(out elementsReturned, out enumObject, hex);
                    hr = EngineConstants.S_OK;
                }
                else if (guidFilter == AD7Guids.guidFilterLocals)
                {
                    CreateLocalProperties(out elementsReturned, out enumObject, hex);
                    hr = EngineConstants.S_OK;
                }
                else if (guidFilter == AD7Guids.guidFilterArgs)
                {
                    CreateParameterProperties(out elementsReturned, out enumObject);
                    hr = EngineConstants.S_OK;
                }
                else
                {
                    hr = EngineConstants.E_NOTIMPL;
                }
            }
            catch (ComponentException e)
            {
                return(e.HRESULT);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }

            return(hr);
        }
예제 #12
0
 // Retrieves a list of all code contexts associated with this document context.
 // The engine sample only supports one code context per document context and
 // the code contexts are always memory addresses.
 int IDebugDocumentContext2.EnumCodeContexts(out IEnumDebugCodeContexts2 ppEnumCodeCxts)
 {
     ppEnumCodeCxts = null;
     try
     {
         AD7MemoryAddress[] codeContexts = new AD7MemoryAddress[1];
         codeContexts[0] = m_codeContext;
         ppEnumCodeCxts  = new AD7CodeContextEnum(codeContexts);
         return(EngineConstants.S_OK);
     }
     catch (ComponentException e)
     {
         return(e.HRESULT);
     }
     catch (Exception e)
     {
         return(EngineUtils.UnexpectedException(e));
     }
 }
예제 #13
0
        // Called by the SDM to indicate that a synchronous debug event, previously sent by the DE to the SDM,
        // was received and processed. The only event the sample engine sends in this fashion is Program Destroy.
        // It responds to that event by shutting down the engine.
        int IDebugEngine2.ContinueFromSynchronousEvent(IDebugEvent2 eventObject)
        {
            // Debug.Assert(Worker.MainThreadId == Worker.CurrentThreadId);

            try
            {
                if (eventObject is AD7ProgramDestroyEvent)
                {
                    //WorkerThread pollThread = m_pollThread;
                    SquirrelProcess _debuggedProcess = debuggedProcess;

                    m_engineCallback = null;
                    debuggedProcess  = null;
                    //m_pollThread = null;
                    m_ad7ProgramId = Guid.Empty;

                    _debuggedProcess.Close();
                    //pollThread.Close();
                }
                else if (eventObject is ErrorEvent)
                {
                    ErrorEvent errorEventObject = eventObject as ErrorEvent;
                    if (errorEventObject != null)
                    {
                        Debug.WriteLine("Debugger received errorevent " + errorEventObject.ErrorMessage + "\n");
                    }

                    return(EngineConstants.E_FAIL);
                    // m_engineCallback.Send(new AD7ProgramDestroyEvent(0), AD7ProgramDestroyEvent.IID, null);
                }
                else
                {
                    Debug.Fail("Debug engine received unknown synchronous event");
                }
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }

            return(EngineConstants.S_OK);
        }
예제 #14
0
        // 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(EngineConstants.S_OK);
        }
예제 #15
0
        // 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(EngineConstants.S_OK);
            }
            catch (ComponentException e)
            {
                return(e.HRESULT);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
예제 #16
0
        // Launches a process by means of the debug engine.
        // Normally, Visual Studio launches a program using the IDebugPortEx2::LaunchSuspended method and then attaches the debugger
        // to the suspended program. However, there are circumstances in which the debug engine may need to launch a program
        // (for example, if the debug engine is part of an interpreter and the program being debugged is an interpreted language),
        // in which case Visual Studio uses the IDebugEngineLaunch2::LaunchSuspended method
        // The IDebugEngineLaunch2::ResumeProcess method is called to start the process after the process has been successfully launched in a suspended state.
        int IDebugEngineLaunch2.LaunchSuspended(string pszServer, IDebugPort2 port, string exe, string args, string dir, string env, string options, enum_LAUNCH_FLAGS launchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 ad7Callback, out IDebugProcess2 process)
        {
            //Debug.Assert(Worker.MainThreadId == Worker.CurrentThreadId);
            //Debug.Assert(m_pollThread == null);
            Debug.Assert(m_engineCallback == null);
            Debug.Assert(debuggedProcess == null);
            Debug.Assert(m_ad7ProgramId == Guid.Empty);

            process = null;

            try
            {
                //string commandLine = EngineUtils.BuildCommandLine(exe, args);

                //ProcessLaunchInfo processLaunchInfo = new ProcessLaunchInfo(exe, commandLine, dir, env, options, (uint)launchFlags, hStdInput, hStdOutput, hStdError);

                // We are being asked to debug a process when we currently aren't debugging anything
                //m_pollThread = new WorkerThread();
                string portname;
                port.GetPortName(out portname);
                m_engineCallback = new EngineCallback(this, ad7Callback);

                XmlDocument doc = new XmlDocument();
                doc.LoadXml(options);
                XmlElement root                      = (XmlElement)doc.ChildNodes[0];
                string     ipaddress                 = root.GetAttribute("targetaddress");
                int        ipport                    = Int32.Parse(root.GetAttribute("port"));
                int        connectiontries           = Int32.Parse(root.GetAttribute("connectiontries"));
                int        connectiondelay           = Int32.Parse(root.GetAttribute("connectiondelay"));
                bool       autoruninterpreter        = Boolean.Parse(root.GetAttribute("autoruninterpreter"));
                bool       suspendonstartup          = Boolean.Parse(root.GetAttribute("suspendonstartup"));
                List <SquirrelDebugFileContext> ctxs = new List <SquirrelDebugFileContext>();
                foreach (XmlElement e in doc.GetElementsByTagName("context"))
                {
                    string rootpath  = e.GetAttribute("rootpath");
                    string pathfixup = e.GetAttribute("pathfixup");
                    SquirrelDebugFileContext sdfc = new SquirrelDebugFileContext(rootpath, pathfixup);
                    ctxs.Add(sdfc);
                }

                // Complete the win32 attach on the poll thread
                //THIS IS A MASSIVE HACK
                //the 'options' parameter is formatted this way "targetaddress,port,autorunintepreter,suspendonstartup,projectfolder,pathfixup"
                //I should find a better way to pass this params

                //fix working dir)
                dir = dir.Replace('/', '\\');
                Process proc = null;
                if (autoruninterpreter)
                {
                    proc = new Process();
                    proc.EnableRaisingEvents       = false;
                    proc.StartInfo.UseShellExecute = false;
                    baseDir = proc.StartInfo.WorkingDirectory = dir;
                    proc.StartInfo.FileName = exe;

                    proc.StartInfo.Arguments = args;
                    proc.StartInfo.RedirectStandardOutput = false;
                    proc.StartInfo.RedirectStandardError  = false;

                    proc.Start();
                }

                AD_PROCESS_ID adProcessId = new AD_PROCESS_ID();

                if (proc != null)
                {
                    adProcessId.ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_SYSTEM;
                    adProcessId.dwProcessId   = (uint)proc.Id;
                }
                else
                {
                    adProcessId.ProcessIdType = (uint)enum_AD_PROCESS_ID.AD_PROCESS_ID_GUID;
                    adProcessId.guidProcessId = Guid.NewGuid();
                }


                EngineUtils.RequireOk(port.GetProcess(adProcessId, out process));

                debuggedProcess                  = (SquirrelProcess)process;
                debuggedProcess.Engine           = this;
                debuggedProcess.Process          = proc;
                debuggedProcess.Name             = proc != null? proc.StartInfo.FileName : "remoteprocess";
                debuggedProcess.EngineCallback   = m_engineCallback;
                debuggedProcess.IpAddress        = ipaddress;
                debuggedProcess.IpPort           = ipport;
                debuggedProcess.SuspendOnStartup = suspendonstartup;
                debuggedProcess.FileContexts     = ctxs.ToArray();
                //debuggedProcess.ConnectionTries = connectiontries;
                //debuggedProcess.ConnectionDelay = connectiondelay;
                //debuggedProcess.PathFixup = pathfixup;
                //debuggedProcess.ProjectFolder = projectfolder;

                /*DebuggedThread thread = new DebuggedThread(1);
                 * DebuggedModule module = new DebuggedModule("the module");
                 *
                 * m_engineCallback.OnModuleLoad(module);
                 * m_engineCallback.OnSymbolSearch(module, "nothing", 0);
                 * m_engineCallback.OnThreadStart(thread);
                 * m_engineCallback.OnLoadComplete(thread);*/

                return(EngineConstants.S_OK);
            }
            catch (ComponentException e)
            {
                return(e.HRESULT);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
예제 #17
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);
            // MessageBox.Show("IDebugEngine2.Attach", "Debugger debugging", MessageBoxButtons.OK, 0);

            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(EngineConstants.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 EngineConstants.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(EngineConstants.S_OK);
            }
            catch (ComponentException e)
            {
                return(e.HRESULT);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
예제 #18
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 (pszCode.Length == 0)
            {
                pbstrError = "Invalid Expression";
                pichError  = (uint)pbstrError.Length;
                return(EngineConstants.S_FALSE);
            }

            try
            {
                bool iswatch = true;
                //HACK WARNING
                //I put a $ in front of the expression so I know that is not a watch in
                //is done by SquirrelAuthoringScope::GetDataTipText (alberto)
                if (pszCode[0] == '$')
                {
                    Debug.WriteLine("!Evaluating " + pszCode);
                    iswatch = false;
                    pszCode = pszCode.Substring(1);
                    if (pszCode.Length == 0)
                    {
                        pbstrError = "Invalid Expression";
                        pichError  = (uint)pbstrError.Length;
                        return(EngineConstants.S_FALSE);
                    }
                }
                if (sqframe.Locals != null)
                {
                    Debug.WriteLine("Evaluating " + pszCode);
                    string[]            targets = pszCode.Split(new char[] { '.' });
                    SquirrelDebugObject val;
                    if (EvaluateSquirrelObject(sqframe.Locals, targets, 0, out val))
                    {
                        ppExpr = new AD7Expression(new SquirrelDebugObject(pszCode, val.Value));

                        return(EngineConstants.S_OK);
                    }

                    if (targets[0] != "this")
                    {
                        List <string> trgswiththis = new List <string>();
                        trgswiththis.Add("this");
                        trgswiththis.AddRange(targets);
                        if (EvaluateSquirrelObject(sqframe.Locals, trgswiththis.ToArray(), 0, out val))
                        {
                            ppExpr = new AD7Expression(new SquirrelDebugObject(pszCode, val.Value));
                            Debug.WriteLine("Succeeded with 'this'" + pszCode);
                            return(EngineConstants.S_OK);
                        }
                    }
                }

                //if(sqframe.Watches.ContainsKey(pszCode))
                if (iswatch)
                {
                    ctx.AddWatch(pszCode);
                    SquirrelDebugObject val;
                    if (sqframe.Watches.TryGetValue(pszCode, out val))
                    {
                        ppExpr = new AD7Expression(val);
                        return(EngineConstants.S_OK);
                    }
                }


                pbstrError = "Invalid Expression";
                pichError  = (uint)pbstrError.Length;
                return(EngineConstants.S_FALSE);
            }
            catch (ComponentException e)
            {
                return(e.HRESULT);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
예제 #19
0
        // 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;

                    /*Alberto
                     * 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(EngineConstants.E_NOTIMPL);
                    }

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

                return(EngineConstants.S_FALSE);
            }
            catch (ComponentException e)
            {
                return(e.HRESULT);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
예제 #20
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 & (uint)enum_MODULE_INFO_FIELDS.MIF_LOADADDRESS) != 0)
                 * {
                 *  info.m_addrLoadAddress = (ulong)this.DebuggedModule.BaseAddress;
                 *  info.dwValidFields |= (uint)enum_MODULE_INFO_FIELDS.MIF_LOADADDRESS;
                 * }
                 * if ((dwFields & (uint)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 |= (uint)enum_MODULE_INFO_FIELDS.MIF_PREFFEREDADDRESS; ;
                 * }
                 * if ((dwFields & (uint)enum_MODULE_INFO_FIELDS.MIF_SIZE) != 0)
                 * {
                 *  info.m_dwSize = this.DebuggedModule.Size;
                 *  info.dwValidFields |= (uint)enum_MODULE_INFO_FIELDS.MIF_SIZE;
                 * }
                 * if ((dwFields & (uint)enum_MODULE_INFO_FIELDS.MIF_LOADORDER) != 0)
                 * {
                 *  info.m_dwLoadOrder = this.DebuggedModule.GetLoadOrder();
                 *  info.dwValidFields |= (uint)enum_MODULE_INFO_FIELDS.MIF_LOADORDER;
                 * }
                 * if ((dwFields & (uint)enum_MODULE_INFO_FIELDS.MIF_URLSYMBOLLOCATION) != 0)
                 * {
                 *  if (this.DebuggedModule.SymbolsLoaded)
                 *  {
                 *      info.m_bstrUrlSymbolLocation = this.DebuggedModule.SymbolPath;
                 *      info.dwValidFields |= (uint)enum_MODULE_INFO_FIELDS.MIF_URLSYMBOLLOCATION;
                 *  }
                 * }
                 * if ((dwFields & (uint)enum_MODULE_INFO_FIELDS.MIF_FLAGS) != 0)
                 * {
                 *  info.m_dwModuleFlags = 0;
                 *  if (this.DebuggedModule.SymbolsLoaded)
                 *  {
                 *      info.m_dwModuleFlags |= (uint)(enum_MODULE_FLAGS.MODULE_FLAG_SYMBOLS);
                 *  }
                 *  info.dwValidFields |= (uint)enum_MODULE_INFO_FIELDS.MIF_FLAGS;
                 * }*/


                infoArray[0] = info;

                return(EngineConstants.S_OK);
            }
            catch (ComponentException e)
            {
                return(e.HRESULT);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
예제 #21
0
        // Gets properties that describe a thread.
        int IDebugThread2.GetThreadProperties(enum_THREADPROPERTY_FIELDS dwFields, THREADPROPERTIES[] propertiesArray)
        {
            try
            {
                THREADPROPERTIES props;
                if (propertiesArray.Length > 0)
                {
                    props = propertiesArray[0];
                }
                else
                {
                    props = new THREADPROPERTIES();
                }


                if ((dwFields & enum_THREADPROPERTY_FIELDS.TPF_ID) != 0)
                {
                    props.dwThreadId = (uint)Id;
                    props.dwFields  |= enum_THREADPROPERTY_FIELDS.TPF_ID;
                }
                if ((dwFields & enum_THREADPROPERTY_FIELDS.TPF_SUSPENDCOUNT) != 0)
                {
                    // sample debug engine doesn't support suspending threads
                    props.dwSuspendCount = (uint)SuspendCount;
                    props.dwFields      |= enum_THREADPROPERTY_FIELDS.TPF_SUSPENDCOUNT;
                }
                if ((dwFields & enum_THREADPROPERTY_FIELDS.TPF_STATE) != 0)
                {
                    props.dwThreadState = (uint)enum_THREADSTATE.THREADSTATE_RUNNING;
                    props.dwFields     |= enum_THREADPROPERTY_FIELDS.TPF_STATE;
                }
                if ((dwFields & enum_THREADPROPERTY_FIELDS.TPF_PRIORITY) != 0)
                {
                    props.bstrPriority = "Normal";
                    props.dwFields    |= enum_THREADPROPERTY_FIELDS.TPF_PRIORITY;
                }
                if ((dwFields & enum_THREADPROPERTY_FIELDS.TPF_NAME) != 0)
                {
                    props.bstrName  = name;
                    props.dwFields |= enum_THREADPROPERTY_FIELDS.TPF_NAME;
                }
                if ((dwFields & enum_THREADPROPERTY_FIELDS.TPF_LOCATION) != 0)
                {
                    props.bstrLocation = GetCurrentLocation();// "SquirrelThread::GetCurrentLocation!!(alberto fix me)"; //GetCurrentLocation(true);
                    props.dwFields    |= enum_THREADPROPERTY_FIELDS.TPF_LOCATION;
                }

                if (propertiesArray.Length > 0)
                {
                    propertiesArray[0] = props;
                }
                return(EngineConstants.S_OK);
            }
            catch (ComponentException e)
            {
                return(e.HRESULT);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }