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

        public DebuggeeStackFrame(DebugEngine engine, DebuggeeThread thread, string frameName)
        {
            m_debugEngine = engine;

            m_thread = thread;

            m_codeContext = null;

            m_documentContext = null;

            m_property = new DebuggeeProperty(engine, this, frameName, string.Empty);

            m_stackRegisters = new ConcurrentDictionary <string, DebuggeeProperty> ();

            m_stackArguments = new ConcurrentDictionary <string, DebuggeeProperty> ();

            m_stackLocals = new ConcurrentDictionary <string, DebuggeeProperty> ();

            m_customExpressions = new ConcurrentDictionary <string, DebuggeeProperty> ();
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public DebuggeeProperty(DebugEngine engine, DebuggeeStackFrame stackFrame, string expression, string value)
        {
            m_debugEngine = engine;

            m_stackFrame = stackFrame;

            if (string.IsNullOrEmpty(expression))
            {
                throw new ArgumentNullException(nameof(expression));
            }

            m_expression = expression;

            m_value = value;

            m_parent = null;

            m_children = new List <DebuggeeProperty> ();

            //
            // Compound parental expressions to evaluate this property's full identifier.
            //

            StringBuilder expressionBuilder = new StringBuilder(2048);

            DebuggeeProperty parent = m_parent;

            while (parent != null)
            {
                expressionBuilder.Append(parent.m_expression + ".");

                parent = parent.m_parent;
            }

            expressionBuilder.Append(m_expression);

            m_fullExpression = expressionBuilder.ToString();
        }
Example #3
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public DebuggeeProperty EvaluateCustomExpression(enum_EVALFLAGS evaluateFlags, string expression, uint radix)
        {
            //
            // Evaluates a custom property lookup, and registers a new entry for this expression if one can't be found.
            //

            LoggingUtils.PrintFunction();

            DebuggeeProperty property = null;

            try
            {
                if (m_stackRegisters.TryGetValue(expression, out property))
                {
                    return(property);
                }

                if (m_stackArguments.TryGetValue(expression, out property))
                {
                    return(property);
                }

                if (m_stackLocals.TryGetValue(expression, out property))
                {
                    return(property);
                }

                if (m_customExpressions.TryGetValue(expression, out property))
                {
                    return(property);
                }


                //
                // Check if this expression has already been queried via a child property.
                //

                // TODO.

                //
                // Couldn't find a pre-registered matching property for this expression, creating a new custom one.
                //

                MiVariable customExpressionVariable = m_debugger.VariableManager.CreateVariableFromExpression(this, expression);

                if (customExpressionVariable != null)
                {
                    property = m_debugger.VariableManager.CreatePropertyFromVariable(this, customExpressionVariable);

                    if (property != null)
                    {
                        m_customExpressions.TryAdd(expression, property);

                        LoggingUtils.RequireOk(m_property.AddChildren(new DebuggeeProperty [] { property }));
                    }
                }
            }
            catch (Exception e)
            {
                LoggingUtils.HandleException(e);
            }

            return(property);
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        #region IDebugProperty2 Members

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

        public virtual int EnumChildren(enum_DEBUGPROP_INFO_FLAGS dwFields, uint dwRadix, ref Guid guidFilter, enum_DBG_ATTRIB_FLAGS dwAttribFilter, string pszNameFilter, uint dwTimeout, out IEnumDebugPropertyInfo2 ppEnum)
        {
            //
            // Enumerates the children of a property. This provides support for dereferencing pointers, displaying members of an array, or fields of a class or struct.
            //

            LoggingUtils.PrintFunction();

            try
            {
                List <DEBUG_PROPERTY_INFO> childPropertyInfo = new List <DEBUG_PROPERTY_INFO> ();

                List <DebuggeeProperty> childRegisterProperties = new List <DebuggeeProperty> ();

                foreach (DebuggeeProperty child in m_children)
                {
                    bool displayProperty = false;

                    DEBUG_PROPERTY_INFO [] infoArray = new DEBUG_PROPERTY_INFO [1];

                    LoggingUtils.RequireOk(child.GetPropertyInfo(dwFields, dwRadix, dwTimeout, null, 0, infoArray));

                    if ((guidFilter == DebuggeeProperty.Filters.guidFilterRegisters) ||
                        (guidFilter == DebuggeeProperty.Filters.guidFilterAutoRegisters))
                    {
                        if ((infoArray [0].dwAttrib & enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_STORAGE_REGISTER) != 0)
                        {
                            childRegisterProperties.Add(child);
                        }
                    }
                    else if ((guidFilter == DebuggeeProperty.Filters.guidFilterArgs) ||
                             (guidFilter == DebuggeeProperty.Filters.guidFilterAllLocalsPlusArgs) ||
                             (guidFilter == DebuggeeProperty.Filters.guidFilterLocalsPlusArgs))
                    {
                        displayProperty |= ((infoArray [0].dwAttrib & enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_DATA) != 0);
                    }
                    else if ((guidFilter == DebuggeeProperty.Filters.guidFilterAllLocals) ||
                             (guidFilter == DebuggeeProperty.Filters.guidFilterAllLocalsPlusArgs) ||
                             (guidFilter == DebuggeeProperty.Filters.guidFilterLocals) ||
                             (guidFilter == DebuggeeProperty.Filters.guidFilterLocalsPlusArgs))
                    {
                        displayProperty |= ((infoArray [0].dwAttrib & enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_DATA) != 0);
                    }
                    else
                    {
                        displayProperty = true;
                    }

                    /*if ((infoArray [0].dwAttrib & dwAttribFilter) != 0)
                     * {
                     * displayProperty = false;
                     * }*/

                    if (displayProperty)
                    {
                        childPropertyInfo.Add(infoArray [0]);
                    }
                }

                if ((guidFilter == DebuggeeProperty.Filters.guidFilterRegisters) ||
                    (guidFilter == DebuggeeProperty.Filters.guidFilterAutoRegisters))
                {
                    //
                    //
                    // Registers must be specified in a collection/list as children of a 'CPU' property.
                    //
                    // Other types documented: https://msdn.microsoft.com/en-us/library/aa290860(v=vs.71).aspx
                    //

                    DebuggeeProperty registersProperty = new DebuggeeProperty(m_debugEngine, m_stackFrame, "CPU", string.Empty);

                    LoggingUtils.RequireOk(registersProperty.AddChildren(childRegisterProperties.ToArray()));

                    DEBUG_PROPERTY_INFO [] infoArray = new DEBUG_PROPERTY_INFO [1];

                    LoggingUtils.RequireOk(registersProperty.GetPropertyInfo(dwFields, dwRadix, dwTimeout, null, 0, infoArray));

                    childPropertyInfo.Add(infoArray [0]);
                }

                ppEnum = new DebuggeeProperty.Enumerator(childPropertyInfo);

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

                ppEnum = null;

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

        public DebuggeeProperty(DebuggeeProperty parent, string expression)
            : this(parent.m_debugEngine, parent.m_stackFrame, expression, string.Empty)
        {
            m_parent = parent;
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        #region IDebugStackFrame2 Members

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

        public virtual int EnumProperties(enum_DEBUGPROP_INFO_FLAGS requestedFields, uint radix, ref Guid guidFilter, uint timeout, out uint elementsReturned, out IEnumDebugPropertyInfo2 enumDebugProperty)
        {
            //
            // Creates an enumerator for properties associated with the stack frame, such as local variables.
            //

            LoggingUtils.PrintFunction();

            try
            {
                uint numEnumeratedProperties;

                IEnumDebugPropertyInfo2 enumeratedProperties;

                LoggingUtils.RequireOk(m_property.EnumChildren(requestedFields, radix, ref guidFilter, enum_DBG_ATTRIB_FLAGS.DBG_ATTRIB_ALL, string.Empty, timeout, out enumeratedProperties));

                LoggingUtils.RequireOk(enumeratedProperties.GetCount(out numEnumeratedProperties));

                elementsReturned = numEnumeratedProperties;

                enumDebugProperty = enumeratedProperties;

#if false
                //List<DEBUG_PROPERTY_INFO> filteredProperties;

                if ((guidFilter == DebuggeeProperty.Filters.guidFilterRegisters) ||
                    (guidFilter == DebuggeeProperty.Filters.guidFilterAutoRegisters))
                {
                    //
                    // Registers must be specified in a collection/list as children of a 'CPU' property.
                    //

                    DEBUG_PROPERTY_INFO [] debugProperties = new DEBUG_PROPERTY_INFO [numEnumeratedProperties];

                    LoggingUtils.RequireOk(enumeratedProperties.Next(numEnumeratedProperties, debugProperties, out numEnumeratedProperties));

                    DebuggeeProperty registersProperty = new DebuggeeProperty(m_debugEngine, this, "CPU", string.Empty);

                    for (uint i = 0; i < numEnumeratedProperties; ++i)
                    {
                        DebuggeeProperty register;

                        if (m_stackRegisters.TryGetValue(debugProperties [i].bstrName, out register))
                        {
                            registersProperty.AddChildren(new DebuggeeProperty [] { register });
                        }
                    }

                    DEBUG_PROPERTY_INFO [] infoArray = new DEBUG_PROPERTY_INFO [1];

                    LoggingUtils.RequireOk(registersProperty.GetPropertyInfo(requestedFields, radix, timeout, null, 0, infoArray));

                    elementsReturned = (uint)infoArray.Length;

                    enumDebugProperty = new DebuggeeProperty.Enumerator(infoArray);
                }

                /*DEBUG_PROPERTY_INFO [] debugProperties = new DEBUG_PROPERTY_INFO [numProperties];
                 *
                 * LoggingUtils.RequireOk (enumeratedProperties.Next (numProperties, debugProperties, out numProperties));
                 *
                 * if ((guidFilter == DebuggeeProperty.Filters.guidFilterRegisters) || (guidFilter == DebuggeeProperty.Filters.guidFilterAutoRegisters))
                 * {
                 * //
                 * // Registers must be specified in a collection/list as children of a 'CPU' property.
                 * //
                 *
                 * DebuggeeProperty registersProperty = new DebuggeeProperty (m_debugEngine, this, "CPU", string.Empty);
                 *
                 * for (uint i = 0; i < numProperties; ++i)
                 * {
                 *  DebuggeeProperty register;
                 *
                 *  if (m_stackRegisters.TryGetValue (debugProperties [i].bstrName, out register))
                 *  {
                 *    registersProperty.AddChildren (new DebuggeeProperty [] { register });
                 *  }
                 * }
                 *
                 * DEBUG_PROPERTY_INFO [] infoArray = new DEBUG_PROPERTY_INFO [1];
                 *
                 * LoggingUtils.RequireOk (registersProperty.GetPropertyInfo (requestedFields, radix, timeout, null, 0, infoArray));
                 *
                 * filteredProperties = new List<DEBUG_PROPERTY_INFO> (1);
                 *
                 * filteredProperties.Add (infoArray [0]);
                 * }
                 * else
                 * {
                 * filteredProperties = new List<DEBUG_PROPERTY_INFO> ((int)numProperties);
                 *
                 * for (uint i = 0; i < numProperties; ++i)
                 * {
                 *  //
                 *  // Determine whether this property should be filtered in/out.
                 *  //
                 *
                 *  bool displayProperty = false;
                 *
                 *  DEBUG_PROPERTY_INFO prop = debugProperties [i];
                 *
                 *  if ((guidFilter == DebuggeeProperty.Filters.guidFilterAllLocals)
                 || (guidFilter == DebuggeeProperty.Filters.guidFilterAllLocalsPlusArgs))
                 || {
                 ||   displayProperty |= true;
                 || }
                 ||
                 || if ((guidFilter == DebuggeeProperty.Filters.guidFilterArgs)
                 || (guidFilter == DebuggeeProperty.Filters.guidFilterAllLocalsPlusArgs)
                 || (guidFilter == DebuggeeProperty.Filters.guidFilterLocalsPlusArgs))
                 || {
                 ||   displayProperty |= m_stackArguments.ContainsKey (prop.bstrName);
                 || }
                 ||
                 || if ((guidFilter == DebuggeeProperty.Filters.guidFilterAllLocals)
                 || (guidFilter == DebuggeeProperty.Filters.guidFilterAllLocalsPlusArgs)
                 || (guidFilter == DebuggeeProperty.Filters.guidFilterLocals)
                 || (guidFilter == DebuggeeProperty.Filters.guidFilterLocalsPlusArgs))
                 || {
                 ||   displayProperty |= m_stackLocals.ContainsKey (prop.bstrName);
                 || }
                 ||
                 || if (displayProperty)
                 || {
                 ||   filteredProperties.Add (prop);
                 || }
                 ||}
                 ||}*/
#endif

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

                elementsReturned = 0;

                enumDebugProperty = null;

                return(Constants.E_FAIL);
            }
        }