/// <summary>
        /// Gets the Array Item for the specified indexes
        /// </summary>
        /// <param name="indexes">Which indexes to get the Array Item for.</param>
        /// <returns>The Value for the given indexes.</returns>
        public MDbgValue GetArrayItem(params int[] indexes)
        {
            if (!IsArrayType)
            {
                throw new MDbgValueException("Type is not array type");
            }

            CorDebug.CorValue      value = Dereference(CorValue);
            CorDebug.CorArrayValue av    = value.CastToArrayValue();
            Debug.Assert(av != null);
            if (av.Rank != indexes.Length)
            {
                throw new MDbgValueException("Invalid number of dimensions.");
            }

            var sb = new StringBuilder("[");

            for (int i = 0; i < indexes.Length; ++i)
            {
                if (i != 0)
                {
                    sb.Append(",");
                }
                sb.Append(indexes[i]);
            }
            sb.Append("]");

            var v = new MDbgValue(Process, sb.ToString(), av.GetElement(indexes));

            return(v);
        }
 /// <summary>
 /// Creates a new instance of the MDbgValue Object.
 /// This constructor is public so that applications can use this class to print values (CorValue).
 /// CorValue's can be returned for example by funceval(CorEval.Result).
 /// </summary>
 /// <param name="process">The Process that will own the Value.</param>
 /// <param name="value">The CorValue that this MDbgValue will start with.</param>
 public MDbgValue(MDbgProcess process, CorDebug.CorValue value)
 {
     // value can be null, but we should always know what process we are
     // looking at.
     Debug.Assert(process != null);
     Initialize(process, null, value);
 }
 private void Unbox(ref CorDebug.CorValue value)
 {
     CorDebug.CorBoxValue boxVal = value.CastToBoxValue();
     if (boxVal != null)
     {
         value = boxVal.GetObject();
     }
 }
 private CorDebug.CorValue Dereference(CorDebug.CorValue value)
 {
     while (true)
     {
         CorDebug.CorReferenceValue rv = value.CastToReferenceValue();
         if (rv == null)
         {
             break; // not a reference
         }
         if (rv.IsNull)
         {
             return(null); // reference to null
         }
         CorDebug.CorValue newValue = rv.Dereference();
         if (newValue == null)
         {
             break; // couldn't dereference the reference (eg. void*)
         }
         value = newValue;
     }
     return(value);
 }
        private string MakePtrString(CorDebug.CorValue value)
        {
            var sb = new StringBuilder();

            while (true)
            {
                CorDebug.CorReferenceValue rv = value.CastToReferenceValue();
                if (rv == null)
                {
                    break; // not a reference
                }
                if (sb.Length > 0)
                {
                    sb.Append("->");
                }
                sb.Append("0x" + rv.Value.ToString("X", CultureInfo.CurrentUICulture));

                CorDebug.CorValue newValue = null;
                try
                {
                    newValue = rv.Dereference();
                }
                catch (COMException ce)
                {
                    if (ce.ErrorCode != (int)CorDebug.HResult.CORDBG_E_BAD_REFERENCE_VALUE)
                    {
                        throw; // some other error
                    }
                }

                if (newValue == null)
                {
                    break; // couldn't dereference the reference (eg. void* or invalid ref)
                }
                value = newValue;
            }

            return(sb.ToString());
        }
        /// <summary>
        /// Gets Array Items.  This function can be called only on one dimensional arrays.
        /// </summary>
        /// <returns>An array of the values for the Array Items.</returns>
        public MDbgValue[] GetArrayItems()
        {
            if (!IsArrayType)
            {
                throw new MDbgValueException("Type is not array type");
            }

            CorDebug.CorValue value = Dereference(CorValue);

            CorDebug.CorArrayValue av = value.CastToArrayValue();
            int[] dims = av.GetDimensions();
            Debug.Assert(dims != null);

            var al = new ArrayList();

            Debug.Assert(av.Rank == 1);
            for (int i = 0; i < dims[0]; i++)
            {
                var v = new MDbgValue(Process, "[" + i + "]", av.GetElementAtPosition(i));
                al.Add(v);
            }
            return((MDbgValue[])al.ToArray(typeof(MDbgValue)));
        }
示例#7
0
文件: Value.cs 项目: pusp/o2platform
 private void Initialize(MDbgProcess process, string name, CorDebug.CorValue value)
 {
     m_process = process;
     m_name = name;
     m_corValue = value;
 }
        private MDbgValue[] InternalGetFields()
        {
            var al = new ArrayList();

            //dereference && (unbox);
            CorDebug.CorValue value = Dereference(CorValue);
            if (value == null)
            {
                throw new MDbgValueException("null value");
            }
            Unbox(ref value);
            CorDebug.CorObjectValue ov = value.CastToObjectValue();

            CorDebug.CorType cType = ov.ExactType;

            CorDebug.CorFrame cFrame = null;
            if (Process.Threads.HaveActive)
            {
                // we need a current frame to display thread local static values
                if (Process.Threads.Active.HaveCurrentFrame)
                {
                    cFrame = Process.Threads.Active.CurrentFrame.CorFrame;
                }
            }


            MDbgModule classModule;

            // initialization
            CorDebug.CorClass corClass = ov.Class;
            classModule = Process.Modules.Lookup(corClass.Module);

            // iteration through class hierarchy
            do
            {
                Type classType;
                //int parentToken;

                classType = classModule.Importer.GetType(corClass.Token);
                //classModule.Importer.GetTypeNameFromDef(classToken,out parentToken);

                foreach (MetadataFieldInfo fi in classType.GetFields())
                {
                    CorValue fieldValue = null;
                    try
                    {
                        if (fi.IsLiteral)
                        {
                            fieldValue = null;
                            // for now we just hide the constant fields.
                            continue;
                        }
                        else if (fi.IsStatic)
                        {
                            fieldValue = cType.GetStaticFieldValue(fi.MetadataToken, cFrame);
                        }
                        else // we are asuming normal field value
                             // GetFieldValueForTYpe Supersedes GetFieldValue
                             // Will replace when all issues are resolved.
                             //fieldValue = ov.GetFieldValueForType(cType, (uint)fi.Token);
                        {
                            fieldValue = ov.GetFieldValue(corClass, fi.MetadataToken);
                        }
                    }
                    catch (COMException)
                    {
                        // we won't report any problems.
                    }
                    al.Add(new MDbgValue(Process, fi.Name, fieldValue));
                }
                cType = cType.Base;
                if (cType == null)
                {
                    break;
                }
                corClass    = cType.Class;
                classModule = Process.Modules.Lookup(corClass.Module);
            } while (true);

            return((MDbgValue[])al.ToArray(typeof(MDbgValue)));
        }
 /// <summary>
 /// Creates a new instance of the MDbgValue Object.
 /// This constructor is public so that applications can use this class to print values (CorValue).
 /// CorValue's can be returned for example by funceval(CorEval.Result).
 /// </summary>
 /// <param name="process">The Process that will own the Value.</param>
 /// <param name="name">The name of the variable.</param>
 /// <param name="value">The CorValue that this MDbgValue will start with.</param>
 public MDbgValue(MDbgProcess process, string name, CorDebug.CorValue value)
 {
     Debug.Assert(process != null && name != null);
     // corValue can be null for native variables in MC++
     Initialize(process, name, value);
 }
        private string PrintObject(int indentLevel, CorDebug.CorObjectValue ov, int expandDepth, bool canDoFunceval)
        {
            Debug.Assert(expandDepth >= 0);

            // Print generics-aware type.
            string name = InternalUtil.PrintCorType(m_process, ov.ExactType);

            var txt = new StringBuilder();

            txt.Append(name);

            if (expandDepth > 0)
            {
                // we gather the field info of the class before we do
                // funceval since funceval requires running the debugger process
                // and this in turn can cause GC and invalidate our references.
                var expandedDescription = new StringBuilder();
                if (IsComplexType)
                {
                    foreach (MDbgValue v in GetFields())
                    {
                        expandedDescription.Append("\n").Append(IndentedString(indentLevel + 1, v.Name)).
                        Append("=").Append(IndentedBlock(indentLevel + 2,
                                                         v.GetStringValue(expandDepth - 1, false)));
                    }
                }

                if (ov.IsValueClass && canDoFunceval)
                // we could display even values for real Objects, but we will just show
                // "description" for valueclasses.
                {
                    CorDebug.CorClass cls      = ov.ExactType.Class;
                    CorMetadataImport importer = m_process.Modules.Lookup(cls.Module).Importer;
                    var mdType = importer.GetType(cls.Token) as MetadataType;

                    if (mdType.ReallyIsEnum)
                    {
                        txt.AppendFormat(" <{0}>", InternalGetEnumString(ov, mdType));
                    }
                    else if (m_process.IsRunning)
                    {
                        txt.Append(" <N/A during run>");
                    }
                    else
                    {
                        MDbgThread activeThread = m_process.Threads.Active;

                        CorDebug.CorValue     thisValue;
                        CorDebug.CorHeapValue hv = ov.CastToHeapValue();
                        if (hv != null)
                        {
                            // we need to pass reference value.
                            CorDebug.CorHandleValue handle = hv.CreateHandle(CorDebugHandleType.HANDLE_WEAK_TRACK_RESURRECTION);
                            thisValue = handle;
                        }
                        else
                        {
                            thisValue = ov;
                        }

                        try
                        {
                            CorDebug.CorEval eval = m_process.Threads.Active.CorThread.CreateEval();
                            m_process.CorProcess.SetAllThreadsDebugState(CorDebugThreadState.THREAD_SUSPEND,
                                                                         activeThread.CorThread);

                            MDbgFunction toStringFunc =
                                m_process.ResolveFunctionName(null, "System.Object", "ToString"
                                                              , thisValue.ExactType.Class.Module.Assembly.AppDomain);
                            Debug.Assert(toStringFunc != null);
                            // we should be always able to resolve ToString function.

                            eval.CallFunction(toStringFunc.CorFunction, new[] { thisValue });
                            m_process.Go();
                            do
                            {
                                m_process.StopEvent.WaitOne();
                                if (m_process.StopReason is EvalCompleteStopReason)
                                {
                                    CorDebug.CorValue cv = eval.Result;
                                    Debug.Assert(cv != null);
                                    var    mv      = new MDbgValue(m_process, cv);
                                    string valName = mv.GetStringValue(0);

                                    // just purely for esthetical reasons we 'discard' "
                                    if (valName.StartsWith("\"") && valName.EndsWith("\""))
                                    {
                                        valName = valName.Substring(1, valName.Length - 2);
                                    }

                                    txt.Append(" <").Append(valName).Append(">");
                                    break;
                                }
                                if ((m_process.StopReason is ProcessExitedStopReason) ||
                                    (m_process.StopReason is EvalExceptionStopReason))
                                {
                                    txt.Append(" <N/A cannot evaluate>");
                                    break;
                                }
                                // hitting bp or whatever should not matter -- we need to ignore it
                                m_process.Go();
                            } while (true);
                        }
                        catch (COMException e)
                        {
                            // Ignore canot copy a VC class error - Can't copy a VC with object refs in it.
                            if (e.ErrorCode != (int)CorDebug.HResult.CORDBG_E_OBJECT_IS_NOT_COPYABLE_VALUE_CLASS)
                            {
                                throw;
                            }
                        }
                        finally
                        {
                            // we need to resume all the threads that we have suspended no matter what.
                            m_process.CorProcess.SetAllThreadsDebugState(CorDebugThreadState.THREAD_RUN,
                                                                         activeThread.CorThread);
                        }
                    }
                }
                txt.Append(expandedDescription.ToString());
            }
            return(txt.ToString());
        }
        //////////////////////////////////////////////////////////////////////////////////
        //
        // Implementation Part
        //
        //////////////////////////////////////////////////////////////////////////////////

        private string InternalGetValue(int indentLevel, int expandDepth, bool canDoFunceval)
        {
            Debug.Assert(expandDepth >= 0);

            CorDebug.CorValue value = CorValue;
            if (value == null)
            {
                return("<N/A>");
            }

            // Record the memory addresses if displaying them is enabled
            string prefix = String.Empty;

            if (m_process.m_engine.Options.ShowAddresses)
            {
                string ptrStr = MakePtrString(value);
                if (!String.IsNullOrEmpty(ptrStr))
                {
                    prefix = "(" + ptrStr + ") ";
                }
            }

            try
            {
                value = Dereference(value);
            }
            catch (COMException ce)
            {
                if (ce.ErrorCode == (int)CorDebug.HResult.CORDBG_E_BAD_REFERENCE_VALUE)
                {
                    return(prefix + "<invalid reference value>");
                }
                throw;
            }

            if (value == null)
            {
                return(prefix + "<null>");
            }

            Unbox(ref value);

            switch (value.Type)
            {
            case CorElementType.ELEMENT_TYPE_BOOLEAN:
            case CorElementType.ELEMENT_TYPE_I1:
            case CorElementType.ELEMENT_TYPE_U1:
            case CorElementType.ELEMENT_TYPE_I2:
            case CorElementType.ELEMENT_TYPE_U2:
            case CorElementType.ELEMENT_TYPE_I4:
            case CorElementType.ELEMENT_TYPE_U4:
            case CorElementType.ELEMENT_TYPE_I:
            case CorElementType.ELEMENT_TYPE_U:
            case CorElementType.ELEMENT_TYPE_I8:
            case CorElementType.ELEMENT_TYPE_U8:
            case CorElementType.ELEMENT_TYPE_R4:
            case CorElementType.ELEMENT_TYPE_R8:
            case CorElementType.ELEMENT_TYPE_CHAR:
            {
                object v = value.CastToGenericValue().GetValue();
                string result;

                var vFormattable = v as IFormattable;
                if (vFormattable != null)
                {
                    result = vFormattable.ToString(null, CultureInfo.CurrentUICulture);
                }
                else
                {
                    result = v.ToString();
                }

                // let's put quotes around char values
                if (value.Type == CorElementType.ELEMENT_TYPE_CHAR)
                {
                    result = "'" + result + "'";
                }

                return(prefix + result);
            }

            case CorElementType.ELEMENT_TYPE_CLASS:
            case CorElementType.ELEMENT_TYPE_VALUETYPE:
                CorDebug.CorObjectValue ov = value.CastToObjectValue();
                return(prefix + PrintObject(indentLevel, ov, expandDepth, canDoFunceval));

            case CorElementType.ELEMENT_TYPE_STRING:
                CorDebug.CorStringValue sv = value.CastToStringValue();
                return(prefix + '"' + sv.String + '"');

            case CorElementType.ELEMENT_TYPE_SZARRAY:
            case CorElementType.ELEMENT_TYPE_ARRAY:
                CorDebug.CorArrayValue av = value.CastToArrayValue();
                return(prefix + PrintArray(indentLevel, av, expandDepth, canDoFunceval));

            case CorElementType.ELEMENT_TYPE_PTR:
                return(prefix + "<non-null pointer>");

            case CorElementType.ELEMENT_TYPE_BYREF:
            case CorElementType.ELEMENT_TYPE_TYPEDBYREF:
            case CorElementType.ELEMENT_TYPE_OBJECT:
            default:
                return(prefix + "<printing value of type: " + value.Type + " not implemented>");
            }
        }
 private void Initialize(MDbgProcess process, string name, CorDebug.CorValue value)
 {
     m_process  = process;
     m_name     = name;
     m_corValue = value;
 }