public static void UnwrapGCHandleCmd(string arguments) { ArgParser ap = new ArgParser(arguments); if (ap.Count != 1) { WriteError("Wrong arguments, should be name or address of a \"System.Runtime.InteropServices.GCHandle\" object."); return; } long handleAdd = 0; // First try to resolve the argument as a variable in the current frame MDbgValue var = Debugger.Processes.Active.ResolveVariable( ap.AsString(0), Debugger.Processes.Active.Threads.Active.CurrentFrame); if (var != null) { if (var.TypeName != "System.Runtime.InteropServices.GCHandle") { WriteError("Variable is not of type \"System.Runtime.InteropServices.GCHandle\"."); return; } foreach (MDbgValue field in var.GetFields()) { if (field.Name == "m_handle") { handleAdd = Int64.Parse(field.GetStringValue(0)); break; } } } else { // Trying to resolve as a raw address now try { handleAdd = ap.GetArgument(0).AsAddress; } catch (System.FormatException) { WriteError("Couldn't recognize the argument as a variable name or address"); return; } } IntPtr add = new IntPtr(handleAdd); CorReferenceValue result; try { result = Debugger.Processes.Active.CorProcess.GetReferenceValueFromGCHandle(add); } catch (System.Runtime.InteropServices.COMException e) { if (e.ErrorCode == (int)HResult.CORDBG_E_BAD_REFERENCE_VALUE) { WriteError("Invalid handle address."); return; } else { throw; } } CorValue v = result.Dereference(); MDbgValue mv = new MDbgValue(Debugger.Processes.Active, v); if (mv.IsComplexType) { WriteOutput(string.Format("GCHandle to <{0}>", InternalUtil.PrintCorType(Debugger.Processes.Active, v.ExactType))); // now print fields as well foreach (MDbgValue f in mv.GetFields()) CommandBase.WriteOutput(" " + f.Name + "=" + f.GetStringValue(0)); } else { WriteOutput(string.Format("GCHandle to {0}", mv.GetStringValue(0))); } }
private LocalVariableInformation GetLocalVariableInformation(MDbgValue value, VariableType variableType, int depth) { // Some MDbgValues don't have an associated CorValue. This occurs when there is no variable declaration in IL. if (value == null || value.CorValue == null) return null; if (createdLocals.ContainsKey(value.CorValue.Address)) return createdLocals[value.CorValue.Address]; var fields = new List<LocalVariableInformation>(); if (value.IsComplexType && value.IsNull == false && depth < 10) { MDbgValue[] fieldValues = value.GetFields(); foreach (var fieldValue in fieldValues) { fields.Add(GetLocalVariableInformation(fieldValue, VariableType.Field, depth + 1)); } } var information = new LocalVariableInformation { TypeName = value.TypeName, Name = value.Name, StringValue = value.GetStringValue(false), TypeOfVariable = variableType, IsPrimitive = !value.IsComplexType, Fields = fields }; createdLocals[value.CorValue.Address] = information; return information; }
//----------------------------------------------------------------------------- // Recursive helper to populate tree view. // val - value to print // c - node collection to add to. // iDepth - track how far we are to avoid infinite recursion. //----------------------------------------------------------------------------- void PrintInternal(MDbgValue val, TreeNodeCollection c, int iDepth) { if (iDepth > 10) { return; } if (val.IsArrayType) { TreeNode n = new TreeNode(val.TypeName + " array:"); foreach (MDbgValue vField in val.GetArrayItems()) { PrintInternal(vField, n.Nodes, iDepth + 1); } c.Add(n); } else if (val.IsComplexType) { // This will include both instance and static fields // It will also include all base class fields. TreeNode n = new TreeNode(val.TypeName + " fields:"); foreach (MDbgValue vField in val.GetFields()) { PrintInternal(vField, n.Nodes, iDepth + 1); } c.Add(n); } else { // This is a ctach-call for primitives. string st = val.GetStringValue(false); c.Add(val.Name + "=" + st + " (type='" + val.TypeName + "')"); } }