Example #1
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
            {
                if (_functionName != null)
                {
                    name = _functionName;
                }
                else
                {
                    name = EngineUtils.GetAddressDescription(Engine.DebuggedProcess, ThreadContext.pc.Value);
                }

                return(Constants.S_OK);
            }
            catch (MIException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Example #2
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;

            if (_codeContext == null)
            {
                return(Constants.E_FAIL);
            }

            try
            {
                AD7MemoryAddress[] codeContexts = new AD7MemoryAddress[1];
                codeContexts[0] = _codeContext;
                ppEnumCodeCxts  = new AD7CodeContextEnum(codeContexts);
                return(Constants.S_OK);
            }
            catch (MIException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Example #3
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(_pollThread != null);
            Debug.Assert(_engineCallback != null);
            Debug.Assert(_debuggedProcess != null);

            try
            {
                AD_PROCESS_ID processId = EngineUtils.GetProcessId(process);
                if (!EngineUtils.ProcIdEquals(processId, _debuggedProcess.Id))
                {
                    return(Constants.S_FALSE);
                }

                _pollThread.RunOperation(() => _debuggedProcess.CmdTerminate());
                _debuggedProcess.Terminate();

                return(Constants.S_OK);
            }
            catch (MIException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Example #4
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 = null;
            pichError  = 0;
            ppExpr     = null;

            try
            {
                // we have no "parser" as such, so we accept anything that isn't blank and let the Evaluate method figure out the errors
                ppExpr = new AD7Expression(Engine, Engine.DebuggedProcess.Natvis.GetVariable(pszCode, this));
                return(Constants.S_OK);
            }
            catch (MIException 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())
                {
                    Task bindTask = null;

                    _engine.DebuggedProcess.WorkerThread.RunOperation(() =>
                    {
                        bindTask = _engine.DebuggedProcess.AddInternalBreakAction(this.BindAsync);
                    });

                    bindTask.Wait(250); //wait a quarter of a second

                    if (!bindTask.IsCompleted)
                    {
                        //send a low severity warning bp. This will allow the UI to respond quickly, and if the mi debugger doesn't end up binding, this warning will get
                        //replaced by the real mi debugger error text
                        _BPError = new AD7ErrorBreakpoint(this, ResourceStrings.LongBind, enum_BP_ERROR_TYPE.BPET_SEV_LOW | enum_BP_ERROR_TYPE.BPET_TYPE_WARNING);
                        _engine.Callback.OnBreakpointError(_BPError);
                        return(Constants.S_FALSE);
                    }
                    else
                    {
                        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...
                    _engine.Callback.OnBreakpointError(_BPError);
                    return(Constants.S_FALSE);
                }
            }
            catch (MIException e)
            {
                return(e.HResult);
            }
            catch (AggregateException e)
            {
                if (e.GetBaseException() is InvalidCoreDumpOperationException)
                {
                    return(AD7_HRESULT.E_CRASHDUMP_UNSUPPORTED);
                }
                else
                {
                    return(EngineUtils.UnexpectedException(e));
                }
            }
            catch (InvalidCoreDumpOperationException)
            {
                return(AD7_HRESULT.E_CRASHDUMP_UNSUPPORTED);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Example #6
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 | enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE)) != 0)
                {
                    string addr = EngineUtils.AsAddr(_address, _engine.DebuggedProcess.Is64BitArch);
                    if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS) != 0)
                    {
                        pinfo[0].bstrAddress = addr;
                        pinfo[0].dwFields   |= enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS;
                    }
                    if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE) != 0)
                    {
                        pinfo[0].bstrAddressAbsolute = addr;
                        pinfo[0].dwFields           |= enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSABSOLUTE;
                    }
                }
                // Fields not supported by the sample
                if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_ADDRESSOFFSET) != 0)
                {
                }
                if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_MODULEURL) != 0)
                {
                    DebuggedModule module = _engine.DebuggedProcess.ResolveAddress(_address);
                    if (module != null)
                    {
                        pinfo[0].bstrModuleUrl = module.Name;
                        pinfo[0].dwFields     |= enum_CONTEXT_INFO_FIELDS.CIF_MODULEURL;
                    }
                }
                if ((dwFields & enum_CONTEXT_INFO_FIELDS.CIF_FUNCTION) != 0)
                {
                    if (string.IsNullOrEmpty(_functionName))
                    {
                        _functionName = Engine.GetAddressDescription(_address);
                    }

                    if (!(string.IsNullOrEmpty(_functionName)))
                    {
                        pinfo[0].bstrFunction = _functionName;
                        pinfo[0].dwFields    |= enum_CONTEXT_INFO_FIELDS.CIF_FUNCTION;
                    }
                }

                return(Constants.S_OK);
            }
            catch (MIException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Example #7
0
        // Gets properties that describe a thread.
        int IDebugThread2.GetThreadProperties(enum_THREADPROPERTY_FIELDS dwFields, THREADPROPERTIES[] ptp)
        {
            try
            {
                THREADPROPERTIES props = new THREADPROPERTIES();

                if ((dwFields & enum_THREADPROPERTY_FIELDS.TPF_ID) != 0)
                {
                    props.dwThreadId = _debuggedThread.TargetId;
                    props.dwFields  |= enum_THREADPROPERTY_FIELDS.TPF_ID;
                }
                if ((dwFields & enum_THREADPROPERTY_FIELDS.TPF_SUSPENDCOUNT) != 0)
                {
                    // sample debug engine doesn't support suspending threads
                    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  = _debuggedThread.Name;
                    props.dwFields |= enum_THREADPROPERTY_FIELDS.TPF_NAME;
                }
                if ((dwFields & enum_THREADPROPERTY_FIELDS.TPF_LOCATION) != 0)
                {
                    props.bstrLocation = GetCurrentLocation(true);
                    props.dwFields    |= enum_THREADPROPERTY_FIELDS.TPF_LOCATION;
                    if (props.bstrLocation == null)
                    {
                        // Thread deletion events may be delayed, in which case the thread object may still be present in the cache
                        // but the engine is unable to retrieve new data for it. So handle failure to get info for a dead thread.
                        props.dwThreadState = (uint)enum_THREADSTATE.THREADSTATE_DEAD;
                        props.dwFields     |= enum_THREADPROPERTY_FIELDS.TPF_STATE;
                        props.bstrLocation  = ResourceStrings.ThreadExited;
                    }
                }

                ptp[0] = props;
                return(Constants.S_OK);
            }
            catch (MIException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Example #8
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(_ad7ProgramId == Guid.Empty);

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

            try
            {
                AD_PROCESS_ID processId = EngineUtils.GetProcessId(rgpPrograms[0]);

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

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

                    _engineCallback = new EngineCallback(this, ad7Callback);

                    // Complete the win32 attach on the poll thread
                    _pollThread.RunOperation(new Operation(delegate
                    {
                        throw new NotImplementedException();
                    }));

                    _pollThread.PostedOperationErrorEvent += _debuggedProcess.OnPostedOperationError;
                }
                else
                {
                    if (!EngineUtils.ProcIdEquals(processId, _debuggedProcess.Id))
                    {
                        Debug.Fail("Asked to attach to a process while we are debugging");
                        return(Constants.E_FAIL);
                    }
                }

                AD7EngineCreateEvent.Send(this);
                AD7ProgramCreateEvent.Send(this);
                this.ProgramCreateEventSent = true;

                return(Constants.S_OK);
            }
            catch (MIException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Example #9
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;

            try
            {
                if (guidFilter == AD7Guids.guidFilterAllLocals ||
                    guidFilter == AD7Guids.guidFilterAllLocalsPlusArgs ||
                    guidFilter == AD7Guids.guidFilterArgs ||
                    guidFilter == AD7Guids.guidFilterLocals ||
                    guidFilter == AD7Guids.guidFilterLocalsPlusArgs)
                {
                    EnsureLocalsAndParameters();
                }

                if (guidFilter == AD7Guids.guidFilterLocalsPlusArgs ||
                    guidFilter == AD7Guids.guidFilterAllLocalsPlusArgs ||
                    guidFilter == AD7Guids.guidFilterAllLocals)
                {
                    CreateLocalsPlusArgsProperties(dwFields, out elementsReturned, out enumObject);
                    hr = Constants.S_OK;
                }
                else if (guidFilter == AD7Guids.guidFilterLocals)
                {
                    CreateLocalProperties(dwFields, out elementsReturned, out enumObject);
                    hr = Constants.S_OK;
                }
                else if (guidFilter == AD7Guids.guidFilterArgs)
                {
                    CreateParameterProperties(dwFields, out elementsReturned, out enumObject);
                    hr = Constants.S_OK;
                }
                else if (guidFilter == AD7Guids.guidFilterRegisters)
                {
                    CreateRegisterContent(dwFields, out elementsReturned, out enumObject);
                    hr = Constants.S_OK;
                }
                else
                {
                    hr = Constants.E_NOTIMPL;
                }
            }
            catch (MIException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }

            return(hr);
        }
Example #10
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)
        {
            enumObject = null;
            try
            {
                // get the thread's stack frames
                System.Collections.Generic.List <ThreadContext> stackFrames = null;
                _engine.DebuggedProcess.WorkerThread.RunOperation(async() => stackFrames = await _engine.DebuggedProcess.ThreadCache.StackFrames(_debuggedThread));
                int         numStackFrames = stackFrames != null ? stackFrames.Count : 0;
                FRAMEINFO[] frameInfoArray;

                if (numStackFrames == 0)
                {
                    // failed to walk any frames. Return an empty stack.
                    frameInfoArray = new FRAMEINFO[0];
                }
                else
                {
                    uint low  = stackFrames[0].Level;
                    uint high = stackFrames[stackFrames.Count - 1].Level;
                    FilterUnknownFrames(stackFrames);
                    numStackFrames = stackFrames.Count;
                    frameInfoArray = new FRAMEINFO[numStackFrames];
                    List <ArgumentList> parameters = null;

                    if ((dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS) != 0)
                    {
                        _engine.DebuggedProcess.WorkerThread.RunOperation(async() => parameters = await _engine.DebuggedProcess.GetParameterInfoOnly(this, (dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_VALUES) != 0,
                                                                                                                                                     (dwFieldSpec & enum_FRAMEINFO_FLAGS.FIF_FUNCNAME_ARGS_TYPES) != 0, low, high));
                    }

                    for (int i = 0; i < numStackFrames; i++)
                    {
                        var p = parameters != null?parameters.Find((ArgumentList t) => t.Item1 == stackFrames[i].Level) : null;

                        AD7StackFrame frame = new AD7StackFrame(_engine, this, stackFrames[i]);
                        frame.SetFrameInfo(dwFieldSpec, out frameInfoArray[i], p != null ? p.Item2 : null);
                    }
                }

                enumObject = new AD7FrameInfoEnum(frameInfoArray);
                return(Constants.S_OK);
            }
            catch (MIException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Example #11
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.
        public int ContinueFromSynchronousEvent(IDebugEvent2 eventObject)
        {
            try
            {
                if (eventObject is AD7ProgramCreateEvent)
                {
                    Exception exception = null;

                    try
                    {
                        _engineCallback.OnLoadComplete();
                        // At this point breakpoints and exception settings have been sent down, so we can resume the target
                        _pollThread.RunOperation(() =>
                        {
                            return(_debuggedProcess.ResumeFromLaunch());
                        });
                    }
                    catch (Exception e)
                    {
                        exception = e;
                        // Return from the catch block so that we can let the exception unwind - the stack can get kind of big
                    }

                    if (exception != null)
                    {
                        // If something goes wrong, report the error and then stop debugging. The SDM will drop errors
                        // from ContinueFromSynchronousEvent, so we want to deal with them ourself.
                        SendStartDebuggingError(exception);
                        _debuggedProcess.Terminate();
                    }

                    return(Constants.S_OK);
                }
                else if (eventObject is AD7ProgramDestroyEvent)
                {
                    Dispose();
                }
                else
                {
                    Debug.Fail("Unknown syncronious event");
                }
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }

            return(Constants.S_OK);
        }
Example #12
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.
        public int CreatePendingBreakpoint(IDebugBreakpointRequest2 pBPRequest, out IDebugPendingBreakpoint2 ppPendingBP)
        {
            Debug.Assert(_breakpointManager != null);
            ppPendingBP = null;

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

            return(Constants.S_OK);
        }
Example #13
0
        // Resume a process launched by IDebugEngineLaunch2.LaunchSuspended
        int IDebugEngineLaunch2.ResumeProcess(IDebugProcess2 process)
        {
            Debug.Assert(_pollThread != null);
            Debug.Assert(_engineCallback != null);
            Debug.Assert(_debuggedProcess != null);
            Debug.Assert(_ad7ProgramId == Guid.Empty);

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

                if (!EngineUtils.ProcIdEquals(processId, _debuggedProcess.Id))
                {
                    return(Constants.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, _engineGuid)));

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

                // NOTE: We wait for the program create event to be continued before we really resume the process

                return(Constants.S_OK);
            }
            catch (MIException e)
            {
                return(e.HResult);
            }
            catch (Exception e) when(ExceptionHelper.BeforeCatch(e, Logger, reportOnlyCorrupting: true))
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Example #14
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(Constants.S_OK);
            }
            catch (MIException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Example #15
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 = _textPosition.BeginPosition.dwColumn;
                pBegPosition[0].dwLine   = _textPosition.BeginPosition.dwLine;

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

            return(Constants.S_OK);
        }
Example #16
0
        // Binds this pending breakpoint to one or more code locations.
        int IDebugPendingBreakpoint2.Bind()
        {
            try
            {
                if (CanBind())
                {
                    // Make sure that HostMarshal calls happen on main thread instead of poll thread.
                    lock (_boundBreakpoints)
                    {
                        if (_bp != null)   // already bound
                        {
                            Debug.Fail("Breakpoint already bound");
                            return(Constants.S_FALSE);
                        }
                        if ((_bpRequestInfo.dwFields & enum_BPREQI_FIELDS.BPREQI_CONDITION) != 0 &&
                            _bpRequestInfo.bpCondition.styleCondition == enum_BP_COND_STYLE.BP_COND_WHEN_TRUE)
                        {
                            _condition = _bpRequestInfo.bpCondition.bstrCondition;
                        }
                        if ((_bpRequestInfo.dwFields & enum_BPREQI_FIELDS.BPREQI_BPLOCATION) != 0)
                        {
                            switch ((enum_BP_LOCATION_TYPE)_bpRequestInfo.bpLocation.bpLocationType)
                            {
                            case enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET:
                                try
                                {
                                    IDebugFunctionPosition2 functionPosition = HostMarshal.GetDebugFunctionPositionForIntPtr(_bpRequestInfo.bpLocation.unionmember2);
                                    EngineUtils.CheckOk(functionPosition.GetFunctionName(out _functionName));
                                }
                                finally
                                {
                                    HostMarshal.Release(_bpRequestInfo.bpLocation.unionmember2);
                                }
                                break;

                            case enum_BP_LOCATION_TYPE.BPLT_CODE_CONTEXT:
                                try
                                {
                                    IDebugCodeContext2 codePosition = HostMarshal.GetDebugCodeContextForIntPtr(_bpRequestInfo.bpLocation.unionmember1);
                                    if (!(codePosition is AD7MemoryAddress))
                                    {
                                        goto default;       // context is not from this engine
                                    }
                                    _codeAddress = ((AD7MemoryAddress)codePosition).Address;
                                }
                                finally
                                {
                                    HostMarshal.Release(_bpRequestInfo.bpLocation.unionmember1);
                                }
                                break;

                            case enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE:
                                try
                                {
                                    IDebugDocumentPosition2 docPosition = HostMarshal.GetDocumentPositionForIntPtr(_bpRequestInfo.bpLocation.unionmember2);
                                    // Get the name of the document that the breakpoint was put in
                                    EngineUtils.CheckOk(docPosition.GetFileName(out _documentName));

                                    // Get the location in the document that the breakpoint is in.
                                    EngineUtils.CheckOk(docPosition.GetRange(_startPosition, _endPosition));
                                }
                                finally
                                {
                                    HostMarshal.Release(_bpRequestInfo.bpLocation.unionmember2);
                                }

                                // Get the document checksum
                                if (_engine.DebuggedProcess.MICommandFactory.SupportsBreakpointChecksums())
                                {
                                    try
                                    {
                                        _checksums = GetSHA1Checksums();
                                    }
                                    catch (Exception)
                                    {
                                        // If we fail to get a checksum there's nothing else we can do
                                    }
                                }

                                break;

                            case enum_BP_LOCATION_TYPE.BPLT_DATA_STRING:
                                string address = HostMarshal.GetDataBreakpointStringForIntPtr(_bpRequestInfo.bpLocation.unionmember3);
                                if (address.Contains(","))
                                {
                                    this.AddressId = address;
                                    _address       = address.Split(',')[0];
                                }
                                else
                                {
                                    this.AddressId = null;
                                    _address       = address;
                                }
                                _size = (uint)_bpRequestInfo.bpLocation.unionmember4;
                                if (_condition != null)
                                {
                                    goto default;       // mi has no conditions on watchpoints
                                }
                                break;

                            default:
                                this.SetError(new AD7ErrorBreakpoint(this, ResourceStrings.UnsupportedBreakpoint), true);
                                return(Constants.S_FALSE);
                            }
                        }
                    }

                    if (!_enabled && IsHardwareBreakpoint)
                    {
                        return(Constants.S_OK);
                    }

                    return(BindWithTimeout());
                }
                else
                {
                    // The breakpoint could not be bound. This may occur for many reasons such as an invalid location, an invalid expression, etc...
                    _engine.Callback.OnBreakpointError(_BPError);
                    return(Constants.S_FALSE);
                }
            }
            catch (MIException e)
            {
                return(e.HResult);
            }
            catch (AggregateException e)
            {
                if (e.GetBaseException() is InvalidCoreDumpOperationException)
                {
                    return(AD7_HRESULT.E_CRASHDUMP_UNSUPPORTED);
                }
                else
                {
                    return(EngineUtils.UnexpectedException(e));
                }
            }
            catch (InvalidCoreDumpOperationException)
            {
                return(AD7_HRESULT.E_CRASHDUMP_UNSUPPORTED);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Example #17
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 contextCompare, IDebugMemoryContext2[] compareToItems, uint compareToLength, out uint foundIndex)
        {
            foundIndex = uint.MaxValue;

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

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

                    bool result;

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

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

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

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

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

                    // The debug engine doesn't understand scopes
                    case enum_CONTEXT_COMPARE.CONTEXT_SAME_SCOPE:
                        result = (_address == compareTo._address);
                        break;

                    case enum_CONTEXT_COMPARE.CONTEXT_SAME_FUNCTION:
                        if (_address == compareTo._address)
                        {
                            result = true;
                            break;
                        }
                        string funcThis = Engine.GetAddressDescription(_address);
                        if (string.IsNullOrEmpty(funcThis))
                        {
                            result = false;
                            break;
                        }
                        string funcCompareTo = Engine.GetAddressDescription(compareTo._address);
                        result = (funcThis == funcCompareTo);
                        break;

                    case enum_CONTEXT_COMPARE.CONTEXT_SAME_MODULE:
                        result = (_address == compareTo._address);
                        if (result == false)
                        {
                            DebuggedModule module = _engine.DebuggedProcess.ResolveAddress(_address);

                            if (module != null)
                            {
                                result = module.AddressInModule(compareTo._address);
                            }
                        }
                        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 (MIException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Example #18
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 read 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       = (uint)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 (this.Process.LaunchOptions is LocalLaunchOptions localLaunchOptions &&
                    string.IsNullOrWhiteSpace(localLaunchOptions.MIDebuggerServerAddress) && string.IsNullOrWhiteSpace(localLaunchOptions.DebugServer) &&
                    (dwFields & enum_MODULE_INFO_FIELDS.MIF_TIMESTAMP) != 0 &&
                    this.DebuggedModule.Name != null)
                {
                    try
                    {
                        long ft   = File.GetLastWriteTimeUtc(this.DebuggedModule.Name).ToFileTime();
                        uint low  = (uint)(ft & 0xFFFFFFFF);
                        uint high = (uint)((ulong)(ft >> 32));
                        info.m_TimeStamp = new FILETIME()
                        {
                            dwLowDateTime  = low,
                            dwHighDateTime = high
                        };
                        info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_TIMESTAMP;
                    } catch {}
                }
                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);
                    }

                    if (this.Process.Is64BitArch)
                    {
                        info.m_dwModuleFlags |= enum_MODULE_FLAGS.MODULE_FLAG_64BIT;
                    }

                    info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_FLAGS;
                }


                infoArray[0] = info;

                return(Constants.S_OK);
            }
            catch (MIException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Example #19
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 read 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       = (uint)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);
                    }

                    if (this.Process.Is64BitArch)
                    {
                        info.m_dwModuleFlags |= enum_MODULE_FLAGS.MODULE_FLAG_64BIT;
                    }

                    info.dwValidFields |= enum_MODULE_INFO_FIELDS.MIF_FLAGS;
                }


                infoArray[0] = info;

                return(Constants.S_OK);
            }
            catch (MIException e)
            {
                return(e.HResult);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }
Example #20
0
        // Binds this pending breakpoint to one or more code locations.
        int IDebugPendingBreakpoint2.Bind()
        {
            try
            {
                if (CanBind())
                {
                    // Make sure that HostMarshal calls happen on main thread instead of poll thread.
                    lock (_boundBreakpoints)
                    {
                        if (_bp != null)   // already bound
                        {
                            Debug.Fail("Breakpoint already bound");
                            return(Constants.S_FALSE);
                        }
                        if ((_bpRequestInfo.dwFields & enum_BPREQI_FIELDS.BPREQI_CONDITION) != 0 &&
                            _bpRequestInfo.bpCondition.styleCondition == enum_BP_COND_STYLE.BP_COND_WHEN_TRUE)
                        {
                            _condition = _bpRequestInfo.bpCondition.bstrCondition;
                        }
                        if ((_bpRequestInfo.dwFields & enum_BPREQI_FIELDS.BPREQI_BPLOCATION) != 0)
                        {
                            switch ((enum_BP_LOCATION_TYPE)_bpRequestInfo.bpLocation.bpLocationType)
                            {
                            case enum_BP_LOCATION_TYPE.BPLT_CODE_FUNC_OFFSET:
                                try
                                {
                                    IDebugFunctionPosition2 functionPosition = HostMarshal.GetDebugFunctionPositionForIntPtr(_bpRequestInfo.bpLocation.unionmember2);
                                    EngineUtils.CheckOk(functionPosition.GetFunctionName(out _functionName));
                                }
                                finally
                                {
                                    HostMarshal.Release(_bpRequestInfo.bpLocation.unionmember2);
                                }
                                break;

                            case enum_BP_LOCATION_TYPE.BPLT_CODE_CONTEXT:
                                try
                                {
                                    IDebugCodeContext2 codePosition = HostMarshal.GetDebugCodeContextForIntPtr(_bpRequestInfo.bpLocation.unionmember1);
                                    if (!(codePosition is AD7MemoryAddress))
                                    {
                                        goto default;       // context is not from this engine
                                    }
                                    _codeAddress = ((AD7MemoryAddress)codePosition).Address;
                                }
                                finally
                                {
                                    HostMarshal.Release(_bpRequestInfo.bpLocation.unionmember1);
                                }
                                break;

                            case enum_BP_LOCATION_TYPE.BPLT_CODE_FILE_LINE:
                                try
                                {
                                    IDebugDocumentPosition2 docPosition = HostMarshal.GetDocumentPositionForIntPtr(_bpRequestInfo.bpLocation.unionmember2);
                                    // Get the name of the document that the breakpoint was put in
                                    EngineUtils.CheckOk(docPosition.GetFileName(out _documentName));

                                    // Get the location in the document that the breakpoint is in.
                                    EngineUtils.CheckOk(docPosition.GetRange(_startPosition, _endPosition));
                                }
                                finally
                                {
                                    HostMarshal.Release(_bpRequestInfo.bpLocation.unionmember2);
                                }

                                // Get the document checksum
                                if (_engine.DebuggedProcess.MICommandFactory.SupportsBreakpointChecksums())
                                {
                                    try
                                    {
                                        _checksums = GetSHA1Checksums();
                                    }
                                    catch (Exception)
                                    {
                                        // If we fail to get a checksum there's nothing else we can do
                                    }
                                }

                                break;

                            case enum_BP_LOCATION_TYPE.BPLT_DATA_STRING:
                                _address = HostMarshal.GetDataBreakpointStringForIntPtr(_bpRequestInfo.bpLocation.unionmember3);
                                _size    = (uint)_bpRequestInfo.bpLocation.unionmember4;
                                if (_condition != null)
                                {
                                    goto default;       // mi has no conditions on watchpoints
                                }
                                break;

                            default:
                                this.SetError(new AD7ErrorBreakpoint(this, ResourceStrings.UnsupportedBreakpoint), true);
                                return(Constants.S_FALSE);
                            }
                        }
                    }

                    Task bindTask = null;
                    _engine.DebuggedProcess.WorkerThread.RunOperation(() =>
                    {
                        bindTask = _engine.DebuggedProcess.AddInternalBreakAction(this.BindAsync);
                    });

                    bindTask.Wait(_engine.GetBPLongBindTimeout());
                    if (!bindTask.IsCompleted)
                    {
                        //send a low severity warning bp. This will allow the UI to respond quickly, and if the mi debugger doesn't end up binding, this warning will get
                        //replaced by the real mi debugger error text
                        this.SetError(new AD7ErrorBreakpoint(this, ResourceStrings.LongBind, enum_BP_ERROR_TYPE.BPET_SEV_LOW | enum_BP_ERROR_TYPE.BPET_TYPE_WARNING), true);
                        return(Constants.S_FALSE);
                    }
                    else
                    {
                        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...
                    _engine.Callback.OnBreakpointError(_BPError);
                    return(Constants.S_FALSE);
                }
            }
            catch (MIException e)
            {
                return(e.HResult);
            }
            catch (AggregateException e)
            {
                if (e.GetBaseException() is InvalidCoreDumpOperationException)
                {
                    return(AD7_HRESULT.E_CRASHDUMP_UNSUPPORTED);
                }
                else
                {
                    return(EngineUtils.UnexpectedException(e));
                }
            }
            catch (InvalidCoreDumpOperationException)
            {
                return(AD7_HRESULT.E_CRASHDUMP_UNSUPPORTED);
            }
            catch (Exception e)
            {
                return(EngineUtils.UnexpectedException(e));
            }
        }