Browse Source

Complete rewrite of variable subsystem

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2185 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 19 years ago
parent
commit
4109904d24
  1. 2
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/CallStackPad.cs
  2. 32
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/LocalVarPad.cs
  3. 37
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/TreeListViewDebuggerItem.cs
  4. 8
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DebuggerIcons.cs
  5. 101
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DynamicTreeDebuggerRow.cs
  6. 16
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs
  7. 18
      src/AddIns/Misc/Debugger/Debugger.BooInterpreter/Project/Src/DebugeeInterpreterContext.cs
  8. 62
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj
  9. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Exceptions.cs
  10. 4
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/MTA2STA.cs
  11. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallbackProxy.cs
  12. 1
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/NDebugger.cs
  13. 23
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/NamespaceDoc.cs
  14. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Util.cs
  15. 5
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop enums/ClassFieldAttribute.cs
  16. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop enums/CorCallingConvention.cs
  17. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop enums/CorElementType.cs
  18. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop enums/CorMethodAttr.cs
  19. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop enums/CorTokenType.cs
  20. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop/CorDebug/ICorDebugClass2.cs
  21. 6
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Modules/Module.cs
  22. 15
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Exception.cs
  23. 119
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs
  24. 18
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Process.cs
  25. 14
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Thread.cs
  26. 29
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ArrayElement.cs
  27. 166
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ArrayValue.cs
  28. 57
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/CallFunctionEval.cs
  29. 230
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/Eval.cs
  30. 5
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/EvalEventArgs.cs
  31. 31
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/NewObjectEval.cs
  32. 30
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/NewStringEval.cs
  33. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/Process-Evals.cs
  34. 31
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/MethodArgument.cs
  35. 43
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/NullValue.cs
  36. 50
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ObjectMember.cs
  37. 101
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ObjectValue.cs
  38. 232
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ObjectValueClass.cs
  39. 61
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PrimitiveValue.cs
  40. 296
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/SignatureStream.cs
  41. 32
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/BindingFlags.cs
  42. 102
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/DebugType-Helpers.cs
  43. 340
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/DebugType.cs
  44. 109
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/FieldInfo.cs
  45. 64
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/MemberInfo.cs
  46. 126
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/MethodInfo.cs
  47. 120
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/PropertyInfo.cs
  48. 38
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/UnavailableValue.cs
  49. 446
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Value.cs
  50. 93
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ValueProxy.cs
  51. 51
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/NamedValue.cs
  52. 71
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/NamedValueCollection.cs
  53. 131
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value-Array.cs
  54. 72
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value-Common.cs
  55. 124
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value-Helpers.cs
  56. 130
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value-Object.cs
  57. 76
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value-Primitive.cs
  58. 217
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value.cs
  59. 5
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/ValueEventArgs.cs
  60. 91
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variable.cs
  61. 115
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/VariableCollection.cs
  62. 27
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/VariableEventArgs.cs
  63. 56
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variables/ArrayElement.cs
  64. 34
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variables/LocalVariable.cs
  65. 47
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variables/MemberVariable.cs
  66. 50
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variables/MethodArgument.cs
  67. 10
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variables/Variable.cs
  68. 107
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variables/VariableCollection.cs
  69. 27
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variables/VariableEventArgs.cs
  70. 24
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/Autogenerated/ICorDebugClass2.cs
  71. 35
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/ICorDebugArrayValue.cs
  72. 6
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/FieldProps.cs
  73. 24
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/MetaData.cs
  74. 7
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/MethodProps.cs
  75. 6
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/ParamProps.cs
  76. 6
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/TypeDefProps.cs
  77. 6
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/TypeRefProps.cs
  78. 4
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/NativeMethods.cs
  79. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/ResourceManager.cs

2
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/CallStackPad.cs

@ -117,7 +117,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -117,7 +117,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
}
if (showArgumentValues) {
try {
argValue = f.GetArgumentVariable(i).ValueProxy.AsString;
argValue = f.GetArgument(i).AsString;
} catch { }
}
if (parameterName != null && argValue != null) {

32
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/LocalVarPad.cs

@ -97,24 +97,24 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -97,24 +97,24 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
localVarList.EndUpdate();
}
delegate void AddVariableMethod(Variable variable);
//delegate void AddVariableMethod(NamedValue val);
public static void AddVariableCollectionToTree(VariableCollection varCollection, TreeListViewItemCollection tree)
public static void AddVariableCollectionToTree(NamedValueCollection collection, TreeListViewItemCollection tree)
{
foreach(VariableCollection sub in varCollection.SubCollections) {
VariableCollection subCollection = sub;
TreeListViewItem subMenu = new TreeListViewItem("<" + subCollection.Name + ">", 0);
subMenu.SubItems.Add(subCollection.Value);
tree.Add(subMenu);
TreeListViewItem.TreeListViewItemHanlder populate = null;
populate = delegate {
AddVariableCollectionToTree(subCollection, subMenu.Items);
subMenu.AfterExpand -= populate;
};
subMenu.AfterExpand += populate;
}
foreach(Variable variable in varCollection.Items) {
tree.Add(new TreeListViewDebuggerItem(variable));
// foreach(VariableCollection sub in varCollection.SubCollections) {
// VariableCollection subCollection = sub;
// TreeListViewItem subMenu = new TreeListViewItem("<" + subCollection.Name + ">", 0);
// subMenu.SubItems.Add(subCollection.Value);
// tree.Add(subMenu);
// TreeListViewItem.TreeListViewItemHanlder populate = null;
// populate = delegate {
// AddVariableCollectionToTree(subCollection, subMenu.Items);
// subMenu.AfterExpand -= populate;
// };
// subMenu.AfterExpand += populate;
// }
foreach(NamedValue val in collection) {
tree.Add(new TreeListViewDebuggerItem(val));
}
}

37
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/TreeListViewDebuggerItem.cs

@ -15,13 +15,13 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -15,13 +15,13 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
{
public class TreeListViewDebuggerItem: TreeListViewItem
{
Variable variable;
NamedValue val;
bool populated = false;
bool dirty = true;
public Variable Variable {
public NamedValue Value {
get {
return variable;
return val;
}
}
@ -51,12 +51,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -51,12 +51,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
}
}
public TreeListViewDebuggerItem(Variable variable)
public TreeListViewDebuggerItem(NamedValue val)
{
this.variable = variable;
this.val = val;
variable.Changed += delegate { dirty = true; Update(); };
variable.Expired += delegate { this.Remove(); };
val.Changed += delegate { dirty = true; Update(); };
val.Expired += delegate { this.Remove(); };
SubItems.Add("");
SubItems.Add("");
@ -71,18 +71,18 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -71,18 +71,18 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
if (this.TreeListView != null) {
((DebuggerTreeListView)this.TreeListView).DelayRefresh();
Highlight = (Variable.ValueProxy.AsString != SubItems[1].Text);
Highlight = (val.AsString != SubItems[1].Text);
}
this.SubItems[0].Text = Variable.Name;
this.SubItems[1].Text = Variable.ValueProxy.AsString;
this.SubItems[2].Text = Variable.ValueProxy.Type;
this.SubItems[0].Text = val.Name;
this.SubItems[1].Text = val.AsString;
this.SubItems[2].Text = val.IsNull ? String.Empty : val.Type.Name;
this.ImageIndex = DebuggerIcons.GetImageListIndex(variable);
this.ImageIndex = DebuggerIcons.GetImageListIndex(val);
if (!IsExpanded) {
// Show plus sign
if (variable.ValueProxy.MayHaveSubVariables && Items.Count == 0) {
if ((val.IsObject || val.IsArray) && Items.Count == 0) {
TreeListViewItem dummy = new TreeListViewItem();
this.AfterExpand += delegate { dummy.Remove(); };
Items.Add(dummy);
@ -96,9 +96,14 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -96,9 +96,14 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
{
if (!populated) {
Items.Clear();
// Do not sort names of array items
this.Items.SortOrder = variable.ValueProxy is ArrayValue ? SortOrder.None : SortOrder.Ascending;
LocalVarPad.AddVariableCollectionToTree(variable.ValueProxy.SubVariables, this.Items);
if (val.IsArray) {
// Do not sort names of array items
this.Items.SortOrder = SortOrder.None;
LocalVarPad.AddVariableCollectionToTree(val.GetArrayElements(), this.Items);
} else if (val.IsObject) {
this.Items.SortOrder = SortOrder.Ascending;
LocalVarPad.AddVariableCollectionToTree(val.GetMembers(), this.Items);
}
populated = true;
}
}

8
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DebuggerIcons.cs

@ -34,14 +34,14 @@ namespace Debugger @@ -34,14 +34,14 @@ namespace Debugger
imageList.Images.Add(IconService.GetBitmap("Icons.16x16.Property"));
}
public static Image GetImage(Variable variable)
public static Image GetImage(Value val)
{
return imageList.Images[GetImageListIndex(variable)];
return imageList.Images[GetImageListIndex(val)];
}
public static int GetImageListIndex(Variable variable)
public static int GetImageListIndex(Value val)
{
if (variable.ValueProxy is ObjectValue) {
if (val.IsObject) {
return 0; // Class
} else {
return 1; // Field

101
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DynamicTreeDebuggerRow.cs

@ -25,17 +25,17 @@ namespace ICSharpCode.SharpDevelop.Services @@ -25,17 +25,17 @@ namespace ICSharpCode.SharpDevelop.Services
// 2 = text
// 3 = value
Variable variable;
NamedValue val;
Image image;
bool populated = false;
bool dirty = true;
public Variable Variable {
public NamedValue Value {
get {
return variable;
return val;
}
set {
variable = value;
val = value;
}
}
@ -52,18 +52,18 @@ namespace ICSharpCode.SharpDevelop.Services @@ -52,18 +52,18 @@ namespace ICSharpCode.SharpDevelop.Services
{
}
public DynamicTreeDebuggerRow(Variable variable)
public DynamicTreeDebuggerRow(NamedValue val)
{
if (variable == null) throw new ArgumentNullException("variable");
if (val == null) throw new ArgumentNullException("val");
this.variable = variable;
this.val = val;
this.Shown += delegate {
this.variable.Changed += Update;
this.val.Changed += Update;
dirty = true;
DoInPausedState( delegate { Update(); } );
};
this.Hidden += delegate {
this.variable.Changed -= Update;
this.val.Changed -= Update;
};
DebuggerGridControl.AddColumns(this.ChildColumns);
@ -85,25 +85,22 @@ namespace ICSharpCode.SharpDevelop.Services @@ -85,25 +85,22 @@ namespace ICSharpCode.SharpDevelop.Services
{
if (!dirty) return;
image = DebuggerIcons.GetImage(variable);
image = DebuggerIcons.GetImage(val);
this[1].Text = ""; // Icon
this[2].Text = variable.Name;
if (ShowValuesInHexadecimal && variable.ValueProxy is PrimitiveValue && variable.ValueProxy.TheValue.IsInteger) {
this[3].Text = String.Format("0x{0:X}", (variable.ValueProxy as PrimitiveValue).Primitive);
this[2].Text = val.Name;
if (ShowValuesInHexadecimal && val.IsPrimitive && val.IsInteger) {
this[3].Text = String.Format("0x{0:X}", val.PrimitiveValue);
} else {
this[3].Text = variable.ValueProxy.AsString;
this[3].Text = val.AsString;
}
this[3].AllowLabelEdit = variable.ValueProxy is PrimitiveValue &&
variable.ValueProxy.ManagedType != typeof(string) &&
!ShowValuesInHexadecimal;
ObjectValue objValue = variable.ValueProxy as ObjectValue;
if (objValue != null) {
objValue.ToStringText.Changed -= Update;
objValue.ToStringText.Changed += Update;
this[3].Text = objValue.ToStringText.ValueProxy.AsString;
this[3].AllowLabelEdit = val.IsInteger && !ShowValuesInHexadecimal;
if (val.IsObject) {
val.ObjectToString.Changed -= Update;
val.ObjectToString.Changed += Update;
this[3].Text = val.ObjectToString.AsString;
}
this.ShowPlus = variable.ValueProxy.MayHaveSubVariables;
this.ShowPlus = val.IsObject || val.IsArray;
this.ShowMinusWhileExpanded = true;
dirty = false;
@ -118,13 +115,12 @@ namespace ICSharpCode.SharpDevelop.Services @@ -118,13 +115,12 @@ namespace ICSharpCode.SharpDevelop.Services
void OnLabelEdited(object sender, DynamicListEventArgs e)
{
PrimitiveValue val = (PrimitiveValue)variable.ValueProxy;
string newValue = ((DynamicListItem)sender).Text;
try {
val.Primitive = newValue;
val.PrimitiveValue = newValue;
} catch (NotSupportedException) {
string format = ResourceService.GetString("MainWindow.Windows.Debug.LocalVariables.CannotSetValue.BadFormat");
string msg = String.Format(format, newValue, val.ManagedType.ToString());
string msg = String.Format(format, newValue, val.Type.ManagedType.ToString());
MessageService.ShowMessage(msg ,"${res:MainWindow.Windows.Debug.LocalVariables.CannotSetValue.Title}");
} catch (COMException) {
// COMException (0x80131330): Cannot perfrom SetValue on non-leaf frames.
@ -177,48 +173,49 @@ namespace ICSharpCode.SharpDevelop.Services @@ -177,48 +173,49 @@ namespace ICSharpCode.SharpDevelop.Services
void DoInPausedState(MethodInvoker action)
{
if (Variable.Process.IsPaused) {
if (val.Process.IsPaused) {
action();
} else {
EventHandler<ProcessEventArgs> onDebuggingPaused = null;
onDebuggingPaused = delegate {
action();
Variable.Process.DebuggingPaused -= onDebuggingPaused;
val.Process.DebuggingPaused -= onDebuggingPaused;
};
Variable.Process.DebuggingPaused += onDebuggingPaused;
val.Process.DebuggingPaused += onDebuggingPaused;
}
}
void Populate()
{
Fill(this, Variable.ValueProxy.SubVariables);
if (val.IsArray) Fill(this, val.GetArrayElements());
if (val.IsObject) Fill(this, val.GetMembers());
populated = true;
}
static void Fill(DynamicTreeRow row, VariableCollection collection)
static void Fill(DynamicTreeRow row, NamedValueCollection collection)
{
row.ChildRows.Clear();
foreach(VariableCollection sub in collection.SubCollections) {
VariableCollection subCollection = sub;
DynamicTreeRow subMenu = new DynamicTreeRow();
DebuggerGridControl.AddColumns(subMenu.ChildColumns);
subMenu[2].Text = subCollection.Name;
subMenu[3].Text = subCollection.Value;
subMenu.ShowMinusWhileExpanded = true;
subMenu.ShowPlus = !subCollection.IsEmpty;
EventHandler<DynamicListEventArgs> populate = null;
populate = delegate {
Fill(subMenu, subCollection);
subMenu.Expanding -= populate;
};
subMenu.Expanding += populate;
row.ChildRows.Add(subMenu);
}
foreach(Variable variable in collection.Items) {
row.ChildRows.Add(new DynamicTreeDebuggerRow(variable));
// foreach(VariableCollection sub in collection.SubCollections) {
// VariableCollection subCollection = sub;
//
// DynamicTreeRow subMenu = new DynamicTreeRow();
// DebuggerGridControl.AddColumns(subMenu.ChildColumns);
// subMenu[2].Text = subCollection.Name;
// subMenu[3].Text = subCollection.Value;
// subMenu.ShowMinusWhileExpanded = true;
// subMenu.ShowPlus = !subCollection.IsEmpty;
//
// EventHandler<DynamicListEventArgs> populate = null;
// populate = delegate {
// Fill(subMenu, subCollection);
// subMenu.Expanding -= populate;
// };
// subMenu.Expanding += populate;
//
// row.ChildRows.Add(subMenu);
// }
foreach(NamedValue val in collection) {
row.ChildRows.Add(new DynamicTreeDebuggerRow(val));
}
}
}

16
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs

@ -211,11 +211,11 @@ namespace ICSharpCode.SharpDevelop.Services @@ -211,11 +211,11 @@ namespace ICSharpCode.SharpDevelop.Services
/// Gets variable of given name.
/// Returns null if unsuccessful.
/// </summary>
public Variable GetVariableFromName(string variableName)
public NamedValue GetVariableFromName(string variableName)
{
if (debuggedProcess == null || debuggedProcess.IsRunning) return null;
VariableCollection collection = debuggedProcess.LocalVariables;
NamedValueCollection collection = debuggedProcess.LocalVariables;
if (collection == null) return null;
@ -233,12 +233,12 @@ namespace ICSharpCode.SharpDevelop.Services @@ -233,12 +233,12 @@ namespace ICSharpCode.SharpDevelop.Services
/// </summary>
public string GetValueAsString(string variableName)
{
Variable variable = GetVariableFromName(variableName);
NamedValue val = GetVariableFromName(variableName);
if (variable == null) {
if (val == null) {
return null;
} else {
return variable.ValueProxy.AsString;
return val.AsString;
}
}
@ -248,12 +248,12 @@ namespace ICSharpCode.SharpDevelop.Services @@ -248,12 +248,12 @@ namespace ICSharpCode.SharpDevelop.Services
/// </summary>
public DebuggerGridControl GetTooltipControl(string variableName)
{
Variable variable = GetVariableFromName(variableName.Trim());
NamedValue val = GetVariableFromName(variableName.Trim());
if (variable == null) {
if (val == null) {
return null;
} else {
return new DebuggerGridControl(new DynamicTreeDebuggerRow(variable));
return new DebuggerGridControl(new DynamicTreeDebuggerRow(val));
}
}

18
src/AddIns/Misc/Debugger/Debugger.BooInterpreter/Project/Src/DebugeeInterpreterContext.cs

@ -67,8 +67,8 @@ namespace Debugger @@ -67,8 +67,8 @@ namespace Debugger
// Debugger.BooInterpreter.dll
assembly = LoadAssembly(typeof(DebugeeInteractiveInterpreter).Assembly.Location);
Value interpreterType = Eval.NewString(process, typeof(DebugeeInteractiveInterpreter).FullName);
interpreter = Eval.CallFunction(process, typeof(Assembly), "CreateInstance", assembly, new Value[] {interpreterType});
interpreter_localVariable = interpreter.ValueProxy.SubVariables["localVariable"].Value;
interpreter = Eval.InvokeMethod(process, typeof(Assembly), "CreateInstance", assembly, new Value[] {interpreterType});
interpreter_localVariable = interpreter.GetMember("localVariable");
RunCommand(
"import System\n" +
"import System.IO\n" +
@ -82,7 +82,7 @@ namespace Debugger @@ -82,7 +82,7 @@ namespace Debugger
Value LoadAssembly(string path)
{
Value assemblyPath = Eval.NewString(process, path);
Value assembly = Eval.CallFunction(process, typeof(Assembly), "LoadFrom", null, new Value[] {assemblyPath});
Value assembly = Eval.InvokeMethod(process, typeof(Assembly), "LoadFrom", null, new Value[] {assemblyPath});
return assembly;
}
@ -90,7 +90,7 @@ namespace Debugger @@ -90,7 +90,7 @@ namespace Debugger
{
if (CanLoadInterpreter) {
Value cmd = Eval.NewString(process, code);
Eval.CallFunction(process, typeof(InteractiveInterpreter), "LoopEval", interpreter, new Value[] {cmd});
Eval.InvokeMethod(process, typeof(InteractiveInterpreter), "LoopEval", interpreter, new Value[] {cmd});
}
}
@ -103,7 +103,7 @@ namespace Debugger @@ -103,7 +103,7 @@ namespace Debugger
{
if (CanLoadInterpreter) {
Value cmd = Eval.NewString(process, code);
Eval.CallFunction(process, typeof(AbstractInterpreter), "SuggestCodeCompletion", interpreter, new Value[] {cmd});
Eval.InvokeMethod(process, typeof(AbstractInterpreter), "SuggestCodeCompletion", interpreter, new Value[] {cmd});
return null;
} else {
return null;
@ -129,7 +129,7 @@ namespace Debugger @@ -129,7 +129,7 @@ namespace Debugger
void BeforeGetValue(string name)
{
Variable localVar;
NamedValue localVar;
try {
localVar = process.LocalVariables[name];
} catch (DebuggerException) {
@ -140,7 +140,7 @@ namespace Debugger @@ -140,7 +140,7 @@ namespace Debugger
Stepper stepOut = new Stepper(process.SelectedThread.LastFunction, "Boo interperter");
stepOut.StepComplete += delegate {
process.Debugger.MTA2STA.AsyncCall(delegate {
if (!interpreter_localVariable.SetValue(localVar.Value)) {
if (!interpreter_localVariable.SetValue(localVar)) {
PrintLine("Getting of local variable " + name + " failed");
}
process.Continue();
@ -151,14 +151,14 @@ namespace Debugger @@ -151,14 +151,14 @@ namespace Debugger
void BeforeSetValue(string name)
{
Variable localVar;
NamedValue localVar;
try {
localVar = process.LocalVariables[name];
} catch (DebuggerException) {
return;
}
PrintLine("Setting local variable " + name);
localVar.Value.SetValue(interpreter_localVariable);
localVar.SetValue(interpreter_localVariable);
}
}
}

62
src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj

@ -18,21 +18,19 @@ @@ -18,21 +18,19 @@
<FileAlignment>4096</FileAlignment>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<OutputPath>..\..\..\..\..\..\AddIns\AddIns\Misc\Debugger\</OutputPath>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>Full</DebugType>
<OutputPath>..\..\..\..\..\..\AddIns\AddIns\Misc\Debugger\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<Optimize>False</Optimize>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>PdbOnly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\..\..\..\..\AddIns\AddIns\Misc\Debugger\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<NoWarn>108</NoWarn>
<DebugSymbols>false</DebugSymbols>
</PropertyGroup>
@ -171,18 +169,6 @@ @@ -171,18 +169,6 @@
<Compile Include="Src\Interop\CorDebug\tagSTATSTG.cs" />
<Compile Include="Src\Interop\MetaData\IMetaDataImport.cs" />
<Compile Include="Src\Interop\MetaData\COR_FIELD_OFFSET.cs" />
<Compile Include="Src\Variables\Evals\Eval.cs" />
<Compile Include="Src\Variables\Evals\EvalEventArgs.cs" />
<Compile Include="Src\Variables\Evals\Process-Evals.cs" />
<Compile Include="Src\Variables\ArrayValue.cs" />
<Compile Include="Src\Variables\NullValue.cs" />
<Compile Include="Src\Variables\ObjectValueClass.cs" />
<Compile Include="Src\Variables\PrimitiveValue.cs" />
<Compile Include="Src\Variables\SignatureStream.cs" />
<Compile Include="Src\Variables\UnavailableValue.cs" />
<Compile Include="Src\Variables\Value.cs" />
<Compile Include="Src\Variables\ValueEventArgs.cs" />
<Compile Include="Src\Variables\VariableCollection.cs" />
<Compile Include="Src\Threads\Stepper.cs" />
<Compile Include="Src\Threads\StepperEventArgs.cs" />
<Compile Include="Src\Interop\CorSym\_FILETIME.cs" />
@ -363,22 +349,39 @@ @@ -363,22 +349,39 @@
<Compile Include="Src\Threads\FrameID.cs" />
<Compile Include="Src\Wrappers\CorDebug\ICorDebugChain.cs" />
<Compile Include="Src\Wrappers\CorDebug\ICorDebugFrame.cs" />
<Compile Include="Src\Variables\VariableEventArgs.cs" />
<Compile Include="Src\Debugger\IExpirable.cs" />
<Compile Include="Src\Variables\Evals\CallFunctionEval.cs" />
<Compile Include="Src\Variables\Evals\NewStringEval.cs" />
<Compile Include="Src\Variables\ObjectValue.cs" />
<Compile Include="Src\Debugger\Util.cs" />
<Compile Include="Src\Variables\Evals\NewObjectEval.cs" />
<Compile Include="Src\Debugger\IMutable.cs" />
<Compile Include="Src\Debugger\ExceptionEventArgs.cs" />
<Compile Include="Src\Debugger\Internal\ManagedCallbackSwitch.cs" />
<Compile Include="Src\Variables\ObjectMember.cs" />
<Compile Include="Src\Variables\MethodArgument.cs" />
<Compile Include="Src\Variables\LocalVariable.cs" />
<Compile Include="Src\Variables\ArrayElement.cs" />
<Compile Include="Src\Variables\ValueProxy.cs" />
<Compile Include="Src\Variables\Variable.cs" />
<Compile Include="Src\Wrappers\CorDebug\ICorDebugArrayValue.cs" />
<Compile Include="Src\Variables\Evals\Eval.cs" />
<Compile Include="Src\Variables\Evals\EvalEventArgs.cs" />
<Compile Include="Src\Variables\Evals\Process-Evals.cs" />
<Compile Include="Src\Variables\Types\BindingFlags.cs" />
<Compile Include="Src\Variables\Types\DebugType.cs" />
<Compile Include="Src\Variables\Types\FieldInfo.cs" />
<Compile Include="Src\Variables\Values\Value.cs" />
<Compile Include="Src\Variables\Values\Value-Array.cs" />
<Compile Include="Src\Variables\Values\Value-Common.cs" />
<Compile Include="Src\Variables\Values\ValueEventArgs.cs" />
<Compile Include="Src\Variables\Values\Value-Object.cs" />
<Compile Include="Src\Variables\Values\Value-Primitive.cs" />
<Compile Include="Src\Variables\Variables\ArrayElement.cs" />
<Compile Include="Src\Variables\Variables\LocalVariable.cs" />
<Compile Include="Src\Variables\Variables\MethodArgument.cs" />
<Compile Include="Src\Variables\Variables\Variable.cs" />
<Compile Include="Src\Variables\Variables\VariableCollection.cs" />
<Compile Include="Src\Variables\Variables\VariableEventArgs.cs" />
<Compile Include="Src\Variables\Types\MethodInfo.cs" />
<Compile Include="Src\Variables\Types\MemberInfo.cs" />
<Compile Include="Src\Variables\Types\PropertyInfo.cs" />
<Compile Include="Src\Variables\Variables\MemberVariable.cs" />
<Compile Include="Src\Variables\Values\Value-Helpers.cs" />
<Compile Include="Src\Variables\Types\DebugType-Helpers.cs" />
<Compile Include="Src\Debugger\NamespaceDoc.cs" />
<Compile Include="Src\Variables\Values\NamedValue.cs" />
<Compile Include="Src\Variables\Values\NamedValueCollection.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="README.TXT" />
@ -391,6 +394,11 @@ @@ -391,6 +394,11 @@
<Folder Include="Src\Wrappers\MetaData" />
<Folder Include="docs" />
<Content Include="docs\Stepping.txt" />
<Folder Include="Src\Variables" />
<Folder Include="Src\Variables\Evals" />
<Folder Include="Src\Variables\Types" />
<Folder Include="Src\Variables\Values" />
<Folder Include="Src\Variables\Variables" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
</Project>

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Exceptions.cs

@ -15,6 +15,4 @@ namespace Debugger @@ -15,6 +15,4 @@ namespace Debugger
public DebuggerException(string message): base(message) {}
public DebuggerException(string message, System.Exception inner): base(message, inner) {}
}
public class BadSignatureException: DebuggerException {}
}

4
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/MTA2STA.cs

@ -12,7 +12,7 @@ using System.Runtime.InteropServices; @@ -12,7 +12,7 @@ using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
namespace Debugger
namespace Debugger.Interop
{
public delegate T MethodInvokerWithReturnValue<T>();
@ -204,7 +204,7 @@ namespace Debugger @@ -204,7 +204,7 @@ namespace Debugger
/// <returns>Return value of the called function</returns>
public static object InvokeMethod(object targetObject, string functionName, object[] functionParameters)
{
MethodInfo method;
System.Reflection.MethodInfo method;
if (targetObject is Type) {
method = ((Type)targetObject).GetMethod(functionName);
} else {

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallbackProxy.cs

@ -7,6 +7,8 @@ @@ -7,6 +7,8 @@
using System;
using System.Windows.Forms;
using Debugger.Interop;
using Debugger.Wrappers.CorDebug;
// Regular expresion:

1
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/NDebugger.cs

@ -9,6 +9,7 @@ using System; @@ -9,6 +9,7 @@ using System;
using System.Text;
using System.Threading;
using Debugger.Interop;
using Debugger.Wrappers.CorDebug;
namespace Debugger

23
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/NamespaceDoc.cs

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision: 1965 $</version>
// </file>
using System;
using System.Text;
using System.Threading;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
/// <summary>
/// <para> This library provides features for debugging managed applications. </para>
/// </summary>
class NamespaceDoc
{
}
}

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Util.cs

@ -10,7 +10,7 @@ using System.Collections.Generic; @@ -10,7 +10,7 @@ using System.Collections.Generic;
namespace Debugger
{
public static class Util
static class Util
{
public static List<T> MergeLists<T>(T a, IEnumerable<T> b)
{

5
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop enums/ClassFieldAttribute.cs

@ -5,9 +5,10 @@ @@ -5,9 +5,10 @@
// <version>$Revision$</version>
// </file>
namespace Debugger
namespace Debugger.Wrappers.MetaData
{
[System.Flags()] enum ClassFieldAttribute: uint
[System.Flags()]
enum ClassFieldAttribute: uint
{
// member access mask - Use this mask to retrieve accessibility information.
fdFieldAccessMask = 0x0007,

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop enums/CorCallingConvention.cs

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
// <version>$Revision$</version>
// </file>
namespace Debugger
namespace Debugger.Wrappers.MetaData
{
enum CorCallingConvention: uint
{

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop enums/CorElementType.cs

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
// <version>$Revision$</version>
// </file>
namespace Debugger
namespace Debugger.Wrappers.CorDebug
{
enum CorElementType: uint
{

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop enums/CorMethodAttr.cs

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
// <version>$Revision$</version>
// </file>
namespace Debugger
namespace Debugger.Wrappers.MetaData
{
enum CorMethodAttr: uint
{

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop enums/CorTokenType.cs

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
// <version>$Revision$</version>
// </file>
namespace Debugger
namespace Debugger.Wrappers.MetaData
{
enum CorTokenType: uint
{

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Interop/CorDebug/ICorDebugClass2.cs

@ -17,7 +17,7 @@ namespace Debugger.Interop.CorDebug @@ -17,7 +17,7 @@ namespace Debugger.Interop.CorDebug
public interface ICorDebugClass2
{
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
void GetParameterizedType([In] uint elementType, [In] uint nTypeArgs, [In, MarshalAs(UnmanagedType.Interface)] ref ICorDebugType ppTypeArgs, [MarshalAs(UnmanagedType.Interface)] out ICorDebugType ppType);
void GetParameterizedType([In] uint elementType, [In] uint nTypeArgs, [In, MarshalAs(UnmanagedType.LPArray)] ICorDebugType[] ppTypeArgs, [MarshalAs(UnmanagedType.Interface)] out ICorDebugType ppType);
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
void SetJMCStatus([In] int bIsJustMyCode);
}

6
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Modules/Module.cs

@ -116,12 +116,6 @@ namespace Debugger @@ -116,12 +116,6 @@ namespace Debugger
}
}
internal ICorDebugFunction GetMethod(string type, string name, int paramCount)
{
uint token = MetaData.GetMethod(type, name, paramCount).Token;
return corModule.GetFunctionFromToken(token);
}
internal Module(Process process, ICorDebugModule pModule)
{
this.process = process;

15
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Exception.cs

@ -15,8 +15,6 @@ namespace Debugger @@ -15,8 +15,6 @@ namespace Debugger
Process process;
Thread thread;
ICorDebugValue corValue;
ValueProxy runtimeValue;
ObjectValueClass runtimeValueException;
ExceptionType exceptionType;
SourcecodeSegment location;
DateTime creationTime;
@ -37,12 +35,11 @@ namespace Debugger @@ -37,12 +35,11 @@ namespace Debugger
this.thread = thread;
corValue = thread.CorThread.CurrentException;
exceptionType = thread.CurrentExceptionType;
runtimeValue = new Value(process,
new IExpirable[] {process.PauseSession},
new IMutable[] {},
delegate { return corValue; } ).ValueProxy;
runtimeValueException = ((ObjectValue)runtimeValue).GetClass("System.Exception");
message = runtimeValueException.SubVariables["_message"].ValueProxy.AsString;
Value runtimeValue = new Value(process,
new IExpirable[] {process.PauseSession},
new IMutable[] {},
delegate { return corValue; } );
message = runtimeValue.GetMember("_message").AsString;
if (thread.LastFunctionWithLoadedSymbols != null) {
location = thread.LastFunctionWithLoadedSymbols.NextStatement;
@ -65,7 +62,7 @@ namespace Debugger @@ -65,7 +62,7 @@ namespace Debugger
callstackItems++;
}
type = runtimeValue.Type;
type = runtimeValue.Type.Name;
}
public string Type {

119
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs

@ -15,6 +15,10 @@ using Debugger.Wrappers.MetaData; @@ -15,6 +15,10 @@ using Debugger.Wrappers.MetaData;
namespace Debugger
{
/// <summary>
/// A function (or also a method or frame) which is being executed on
/// some thread. Use to obtain arguments or local variables.
/// </summary>
public class Function: RemotingObjectBase, IExpirable
{
Process process;
@ -32,68 +36,74 @@ namespace Debugger @@ -32,68 +36,74 @@ namespace Debugger
MethodProps methodProps;
/// <summary> The process in which this function is executed </summary>
public Process Process {
get {
return process;
}
}
/// <summary> The name of the function (eg "ToString") </summary>
public string Name {
get {
return methodProps.Name;
}
}
/// <summary> Metadata token of the function </summary>
public uint Token {
get {
return methodProps.Token;
}
}
/// <summary> A module in which the function is defined </summary>
public Module Module {
get {
return module;
}
}
/// <summary> A thread in which the function is executed </summary>
public Thread Thread {
get {
return thread;
}
}
/// <summary> True if the function is static </summary>
public bool IsStatic {
get {
return methodProps.IsStatic;
}
}
/// <summary> True if the function has symbols defined.
/// (That is has accesss to the .pdb file) </summary>
public bool HasSymbols {
get {
return GetSegmentForOffet(0) != null;
}
}
internal ICorDebugClass ContaingClass {
/// <summary> The class that defines this function </summary>
internal ICorDebugClass ContaingClass { // TODO: Use DebugType
get {
return corFunction.Class;
}
}
/// <summary>
/// True if function stepped out and is not longer valid.
/// </summary>
/// <summary> True if function stepped out and is not longer valid. </summary>
public bool HasExpired {
get {
return steppedOut || Module.Unloaded;
}
}
/// <summary>
/// Occurs when function expires and is no longer usable
/// </summary>
/// <summary> Occurs when function expires and is no longer usable </summary>
public event EventHandler Expired;
/// <summary> Is called when function expires and is no longer usable </summary>
internal protected virtual void OnExpired(EventArgs e)
{
if (!steppedOut) {
@ -124,6 +134,7 @@ namespace Debugger @@ -124,6 +134,7 @@ namespace Debugger
process.TraceMessage("Function " + this.ToString() + " created");
}
/// <summary> Returns diagnostic description of the frame </summary>
public override string ToString()
{
return methodProps.Name + "(" + frameID.ToString() + ")";
@ -174,16 +185,19 @@ namespace Debugger @@ -174,16 +185,19 @@ namespace Debugger
}
}
/// <summary> Step into next instruction </summary>
public void StepInto()
{
Step(true);
}
/// <summary> Step over next instruction </summary>
public void StepOver()
{
Step(false);
}
/// <summary> Step out of the function </summary>
public void StepOut()
{
new Stepper(this, "Function step out").StepOut();
@ -313,11 +327,19 @@ namespace Debugger @@ -313,11 +327,19 @@ namespace Debugger
return null;
}
/// <summary>
/// Determine whether the instrustion pointer can be set to given location
/// </summary>
/// <returns> Best possible location. Null is not possible. </returns>
public SourcecodeSegment CanSetIP(string filename, int line, int column)
{
return SetIP(true, filename, line, column);
}
/// <summary>
/// Set the instrustion pointer to given location
/// </summary>
/// <returns> Best possible location. Null is not possible. </returns>
public SourcecodeSegment SetIP(string filename, int line, int column)
{
return SetIP(false, filename, line, column);
@ -353,31 +375,40 @@ namespace Debugger @@ -353,31 +375,40 @@ namespace Debugger
}
}
public VariableCollection Variables {
/// <summary>
/// Gets all variables in the lexical scope of the function.
/// That is, arguments, local variables and varables of the containing class.
/// </summary>
public NamedValueCollection Variables {
get {
return new VariableCollection(GetVariables());
return new NamedValueCollection(GetVariables());
}
}
IEnumerable<Variable> GetVariables()
IEnumerable<NamedValue> GetVariables()
{
if (!IsStatic) {
yield return new Variable("this", ThisValue);
yield return ThisValue;
}
foreach(Variable var in ArgumentVariables) {
yield return var;
foreach(NamedValue namedValue in Arguments) {
yield return namedValue;
}
foreach(Variable var in LocalVariables) {
yield return var;
foreach(NamedValue namedValue in LocalVariables) {
yield return namedValue;
}
foreach(Variable var in ContaingClassVariables) {
yield return var;
foreach(NamedValue namedValue in ContaingClassVariables) {
yield return namedValue;
}
}
public Value ThisValue {
/// <summary>
/// Gets the instance of the class asociated with the current frame.
/// That is, 'this' in C#.
/// </summary>
public NamedValue ThisValue {
get {
return new Value(
return new NamedValue(
"this",
process,
new IExpirable[] {this},
new IMutable[] {},
@ -400,17 +431,22 @@ namespace Debugger @@ -400,17 +431,22 @@ namespace Debugger
}
}
public IEnumerable<Variable> ContaingClassVariables {
/// <summary>
/// Gets all accessible members of the class that defines this function.
/// </summary>
public NamedValueCollection ContaingClassVariables {
get {
// TODO: Should work for static
if (!IsStatic) {
foreach(Variable var in ThisValue.ValueProxy.SubVariables) {
yield return var;
}
return ThisValue.GetMembers();
} else {
return NamedValueCollection.Empty;
}
}
}
/// <summary> Gets the name of given parameter </summary>
/// <param name="index"> Zero-based index </param>
public string GetParameterName(int index)
{
// index = 0 is return parameter
@ -421,6 +457,7 @@ namespace Debugger @@ -421,6 +457,7 @@ namespace Debugger
}
}
/// <summary> Total number of arguments (excluding implicit 'this' argument) </summary>
public int ArgumentCount {
get {
ICorDebugValueEnum argumentEnum = CorILFrame.EnumerateArguments();
@ -432,17 +469,17 @@ namespace Debugger @@ -432,17 +469,17 @@ namespace Debugger
}
}
public MethodArgument GetArgumentVariable(int index)
/// <summary> Gets argument with a given index </summary>
/// <param name="index"> Zero-based index </param>
public MethodArgument GetArgument(int index)
{
return new MethodArgument(
GetParameterName(index),
index,
new Value(
process,
new IExpirable[] {this},
new IMutable[] {process.DebugeeState},
delegate { return GetArgumentCorValue(index); }
)
process,
new IExpirable[] {this},
new IMutable[] {process.DebugeeState},
delegate { return GetArgumentCorValue(index); }
);
}
@ -459,14 +496,22 @@ namespace Debugger @@ -459,14 +496,22 @@ namespace Debugger
}
}
public IEnumerable<MethodArgument> ArgumentVariables {
/// <summary> Gets all arguments of the function. </summary>
public NamedValueCollection Arguments {
get {
return new NamedValueCollection(ArgumentsEnum);
}
}
IEnumerable<NamedValue> ArgumentsEnum {
get {
for (int i = 0; i < ArgumentCount; i++) {
yield return GetArgumentVariable(i);
yield return GetArgument(i);
}
}
}
/// <summary> Gets all local variables of the function. </summary>
public IEnumerable<LocalVariable> LocalVariables {
get {
if (symMethod != null) { // TODO: Is this needed?
@ -496,12 +541,10 @@ namespace Debugger @@ -496,12 +541,10 @@ namespace Debugger
{
return new LocalVariable(
symVar.Name,
new Value(
process,
new IExpirable[] {this},
new IMutable[] {process.DebugeeState},
delegate { return GetCorValueOfLocalVariable(symVar); }
)
process,
new IExpirable[] {this},
new IMutable[] {process.DebugeeState},
delegate { return GetCorValueOfLocalVariable(symVar); }
);
}

18
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Process.cs

@ -6,6 +6,8 @@ @@ -6,6 +6,8 @@
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
namespace Debugger
@ -20,6 +22,8 @@ namespace Debugger @@ -20,6 +22,8 @@ namespace Debugger
Thread selectedThread;
PauseSession pauseSession;
Dictionary<object, DebugType> debugTypeCache = new Dictionary<object, DebugType>();
bool hasExpired = false;
public event EventHandler Expired;
@ -239,14 +243,24 @@ namespace Debugger @@ -239,14 +243,24 @@ namespace Debugger
}
}
public VariableCollection LocalVariables {
public NamedValueCollection LocalVariables {
get {
if (SelectedFunction == null || IsRunning) {
return VariableCollection.Empty;
return NamedValueCollection.Empty;
} else {
return SelectedFunction.Variables;
}
}
}
internal DebugType GetDebugType(ICorDebugType corType)
{
DebugType type;
if (!debugTypeCache.TryGetValue(corType.WrappedObject, out type)) {
type = new DebugType(this, corType);
debugTypeCache.Add(corType.WrappedObject, type);
}
return type;
}
}
}

14
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Thread.cs

@ -149,9 +149,9 @@ namespace Debugger @@ -149,9 +149,9 @@ namespace Debugger
if (!HasBeenLoaded) return lastPriority;
if (process.IsRunning) return lastPriority;
ValueProxy runTimeValue = RuntimeValue.ValueProxy;
if (runTimeValue is NullValue) return ThreadPriority.Normal;
lastPriority = (ThreadPriority)(int)(runTimeValue["m_Priority"].ValueProxy as PrimitiveValue).Primitive;
Value runTimeValue = RuntimeValue;
if (runTimeValue.IsNull) return ThreadPriority.Normal;
lastPriority = (ThreadPriority)(int)runTimeValue.GetMember("m_Priority").PrimitiveValue;
return lastPriority;
}
}
@ -174,10 +174,10 @@ namespace Debugger @@ -174,10 +174,10 @@ namespace Debugger
get {
if (!HasBeenLoaded) return lastName;
if (process.IsRunning) return lastName;
ValueProxy runtimeVar = RuntimeValue.ValueProxy;
if (runtimeVar is NullValue) return lastName;
ValueProxy runtimeName = runtimeVar["m_Name"].ValueProxy;
if (runtimeName is NullValue) return string.Empty;
Value runtimeValue = RuntimeValue;
if (runtimeValue.IsNull) return lastName;
Value runtimeName = runtimeValue.GetMember("m_Name");
if (runtimeName.IsNull) return string.Empty;
lastName = runtimeName.AsString.ToString();
return lastName;
}

29
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ArrayElement.cs

@ -1,29 +0,0 @@ @@ -1,29 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
public class ArrayElement: Variable
{
uint[] indicies;
public uint[] Indicies {
get { return indicies; }
}
public ArrayElement(string name, uint[] indicies, Value @value)
:base (name, @value)
{
this.indicies = indicies;
}
}
}

166
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ArrayValue.cs

@ -1,166 +0,0 @@ @@ -1,166 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
//TODO: Support for lower bound
namespace Debugger
{
public class ArrayValue: ValueProxy
{
uint[] dimensions;
uint lenght;
CorElementType corElementType;
readonly uint rank;
protected ICorDebugArrayValue CorArrayValue {
get {
return TheValue.CorValue.CastTo<ICorDebugArrayValue>();
}
}
public uint Lenght {
get {
return lenght;
}
}
public string ElementsType {
get {
return Value.CorTypeToString(corElementType);
}
}
public uint Rank {
get {
return rank;
}
}
public override string AsString {
get {
string txt = "{" + ElementsType + "[";
for (int i = 0; i < rank; i++) {
txt += dimensions[i].ToString() + ",";
}
txt = txt.TrimEnd(new char[] {','}) + "]}";
return txt;
}
}
internal unsafe ArrayValue(Value @value):base(@value)
{
corElementType = (CorElementType)CorArrayValue.ElementType;
rank = CorArrayValue.Rank;
lenght = CorArrayValue.Count;
dimensions = new uint[rank];
fixed (void* pDimensions = dimensions) {
CorArrayValue.GetDimensions(rank, new IntPtr(pDimensions));
}
}
bool IsCorValueCompatible {
get {
ArrayValue freshValue = TheValue.ValueProxy as ArrayValue;
return freshValue != null &&
freshValue.ElementsType == this.ElementsType &&
freshValue.Lenght == this.Lenght &&
freshValue.Rank == this.Rank;
}
}
public Variable this[uint index] {
get {
return this[new uint[] {index}];
}
}
public Variable this[uint index1, uint index2] {
get {
return this[new uint[] {index1, index2}];
}
}
public Variable this[uint index1, uint index2, uint index3] {
get {
return this[new uint[] {index1, index2, index3}];
}
}
public Variable this[uint[] indices] {
get {
return GetItem(indices);
}
}
Variable GetItem(uint[] itemIndices)
{
uint[] indices = (uint[])itemIndices.Clone();
if (indices.Length != rank) throw new DebuggerException("Given indicies does not match array size.");
string elementName = "[";
for (int i = 0; i < indices.Length; i++)
elementName += indices[i].ToString() + ",";
elementName = elementName.TrimEnd(new char[] {','}) + "]";
return new ArrayElement(
elementName,
indices,
new Value(
TheValue.Process,
new IExpirable[] {this.TheValue},
new IMutable[] {this.TheValue},
delegate { return GetCorValueOfItem(indices); }
)
);
}
unsafe ICorDebugValue GetCorValueOfItem(uint[] indices)
{
if (!IsCorValueCompatible) throw new CannotGetValueException("Value is not the same array");
fixed (void* pIndices = indices) {
return CorArrayValue.GetElement(rank, new IntPtr(pIndices));
}
}
protected override bool GetMayHaveSubVariables()
{
return true;
}
protected override VariableCollection GetSubVariables()
{
return new VariableCollection(GetSubVariablesEnum());
}
IEnumerable<Variable> GetSubVariablesEnum()
{
uint[] indices = new uint[rank];
while(true) { // Go thought all combinations
for (uint i = rank - 1; i >= 1; i--)
if (indices[i] >= dimensions[i]) {
indices[i] = 0;
indices[i-1]++;
}
if (indices[0] >= dimensions[0]) break; // We are done
yield return GetItem(indices);
indices[rank - 1]++;
}
}
}
}

57
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/CallFunctionEval.cs

@ -1,57 +0,0 @@ @@ -1,57 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
class CallFunctionEval: Eval
{
ICorDebugFunction corFunction;
Value thisValue;
Value[] args;
public CallFunctionEval(Process process,
IExpirable[] expireDependencies,
IMutable[] mutateDependencies,
ICorDebugFunction corFunction,
Value thisValue,
Value[] args)
:base(process, expireDependencies, mutateDependencies)
{
this.corFunction = corFunction;
this.thisValue = thisValue;
this.args = args;
}
protected override void StartEvaluation()
{
List<ICorDebugValue> corArgs = new List<ICorDebugValue>();
try {
if (thisValue != null) {
ValueProxy val = thisValue.ValueProxy;
if (!(val is ObjectValue)) {
throw new EvalSetupException("Can not evaluate on a value which is not an object");
}
if (!((ObjectValue)val).IsInClassHierarchy(corFunction.Class)) {
throw new EvalSetupException("Can not evaluate because the object does not contain specified function");
}
corArgs.Add(thisValue.SoftReference);
}
foreach(Value arg in args) {
corArgs.Add(arg.SoftReference);
}
} catch (CannotGetValueException e) {
throw new EvalSetupException(e.Message);
}
corEval.CallFunction(corFunction, (uint)corArgs.Count, corArgs.ToArray());
}
}
}

230
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/Eval.cs

@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
// </file>
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Debugger.Wrappers.CorDebug;
@ -16,143 +17,198 @@ namespace Debugger @@ -16,143 +17,198 @@ namespace Debugger
/// <summary>
/// This class holds information about function evaluation.
/// </summary>
public abstract partial class Eval: Value
public class Eval: RemotingObjectBase
{
protected class EvalSetupException: System.Exception
delegate void EvaluationInvoker(ICorDebugEval corEval);
class EvalSetupException: System.Exception
{
public EvalSetupException(string msg):base(msg)
{
}
}
protected ICorDebugEval corEval;
EvalState currentState = EvalState.WaitingForRequest;
string currentErrorMsg;
Process process;
Value val;
string description;
EvaluationInvoker evaluationInvoker;
EvalState state = EvalState.WaitingForRequest;
ICorDebugEval corEval;
string errorMsg;
ICorDebugValue result;
public Process Process {
get {
return process;
}
}
public Value Result {
get {
return val;
}
}
string description = String.Empty;
public string Description {
get {
return description;
}
}
public EvalState State {
get {
return currentState;
return state;
}
}
public bool Evaluated {
get {
return currentState == EvalState.EvaluatedSuccessfully ||
currentState == EvalState.EvaluatedException ||
currentState == EvalState.EvaluatedNoResult ||
currentState == EvalState.EvaluatedError;
return state == EvalState.EvaluatedSuccessfully ||
state == EvalState.EvaluatedException ||
state == EvalState.EvaluatedNoResult ||
state == EvalState.EvaluatedError;
}
}
internal ICorDebugEval CorEval {
get {
return corEval;
Eval(Process process,
string description,
IExpirable[] expireDependencies,
IMutable[] mutateDependencies,
EvaluationInvoker evaluationInvoker)
{
this.process = process;
this.description = description;
this.val = new Value(process,
expireDependencies,
mutateDependencies,
delegate { return GetCorValue(); });
this.val.Changed += delegate { SetState(EvalState.WaitingForRequest, null, null); };
this.evaluationInvoker = evaluationInvoker;
}
internal bool IsCorEval(ICorDebugEval corEval)
{
return this.corEval == corEval;
}
public ICorDebugValue GetCorValue()
{
switch(this.State) {
case EvalState.WaitingForRequest: RequestEvaluation(); goto case EvalState.EvaluationScheduled;
case EvalState.EvaluationScheduled: throw new CannotGetValueException("Evaluation pending");
case EvalState.Evaluating: throw new CannotGetValueException("Evaluating...");
case EvalState.EvaluatedSuccessfully: return result;
case EvalState.EvaluatedException: return result;
case EvalState.EvaluatedNoResult: throw new CannotGetValueException("No return value");
case EvalState.EvaluatedError: throw new CannotGetValueException(errorMsg);
default: throw new DebuggerException("Unknown state");
}
}
public string Description {
get { return description; }
set { description = value; }
void SetState(EvalState state, string errorMsg, ICorDebugValue result)
{
this.state = state;
this.errorMsg = errorMsg;
this.result = result;
}
protected Eval(Process process,
IExpirable[] expireDependencies,
IMutable[] mutateDependencies)
:base(process, expireDependencies, mutateDependencies, null)
void ChangeState(EvalState state, string errorMsg, ICorDebugValue result)
{
SetState(state, errorMsg, result);
this.Result.NotifyChange();
}
protected override void ClearCurrentValue()
/// <summary> Synchronously calls a function and returns its return value </summary>
public static Value InvokeMethod(Process process, System.Type type, string name, Value thisValue, Value[] args)
{
currentState = EvalState.WaitingForRequest;
currentErrorMsg = null;
base.ClearCurrentValue();
return InvokeMethod(MethodInfo.GetFromName(process, type, name, args.Length), thisValue, args);
}
public void SetState(EvalState currentState, string currentErrorMsg, ICorDebugValue currentCorValue)
/// <summary> Synchronously calls a function and returns its return value </summary>
public static Value InvokeMethod(MethodInfo method, Value thisValue, Value[] args)
{
ClearCurrentValue();
this.currentState = currentState;
this.currentErrorMsg = currentErrorMsg;
this.currentCorValue = currentCorValue;
this.currentCorValuePauseSession = process.PauseSession;
OnChanged(new EvalEventArgs(this));
return AsyncInvokeMethod(method, thisValue, args).EvaluateNow();
}
/// <summary>
/// Synchronously calls a function and returns its return value
/// </summary>
public static Value CallFunction(Process process, Type type, string functionName, Value thisValue, Value[] args)
public static Eval AsyncInvokeMethod(MethodInfo method, Value thisValue, Value[] args)
{
string moduleName = System.IO.Path.GetFileName(type.Assembly.Location);
Module module = process.GetModule(moduleName);
string containgType = type.FullName;
ICorDebugFunction corFunction = module.GetMethod(containgType, functionName, args.Length);
Eval eval = new CallFunctionEval(
process,
new IExpirable[] {},
// string moduleName = System.IO.Path.GetFileName(type.Assembly.Location);
// Module module = process.GetModule(moduleName);
// string containgType = type.FullName;
// ICorDebugFunction corFunction = module.GetMethod(containgType, functionName, args.Length);
return new Eval(
method.Process,
"Function call: " + method.DeclaringType.Name + "." + method.Name,
new IExpirable[] {}, // TODO
new IMutable[] {},
corFunction,
thisValue,
args
delegate(ICorDebugEval corEval) { StartMethodInvoke(corEval, method, thisValue, args); }
);
eval.Description = "Function call: " + containgType + "." + functionName;
return eval.EvaluateNow();
}
/// <summary>
/// Synchronously creates a new string
/// </summary>
static void StartMethodInvoke(ICorDebugEval corEval, MethodInfo method, Value thisValue, Value[] args)
{
List<ICorDebugValue> corArgs = new List<ICorDebugValue>();
args = args ?? new Value[0];
try {
if (thisValue != null) {
if (!(thisValue.IsObject)) {
throw new EvalSetupException("Can not evaluate on a value which is not an object");
}
if (!method.DeclaringType.IsInstanceOfType(thisValue)) {
throw new EvalSetupException("Can not evaluate because the object is not of proper type");
}
corArgs.Add(thisValue.SoftReference);
}
foreach(Value arg in args) {
corArgs.Add(arg.SoftReference);
}
} catch (CannotGetValueException e) {
throw new EvalSetupException(e.Message);
}
corEval.CallFunction(method.CorFunction, (uint)corArgs.Count, corArgs.ToArray());
}
public static Value NewString(Process process, string textToCreate)
{
Eval eval = new NewStringEval(
return AsyncNewString(process, textToCreate).EvaluateNow();
}
public static Eval AsyncNewString(Process process, string textToCreate)
{
return new Eval(
process,
"New string: " + textToCreate,
new IExpirable[] {},
new IMutable[] {},
textToCreate
delegate(ICorDebugEval corEval) { corEval.NewString(textToCreate); }
);
eval.Description = "New string: " + textToCreate;
return eval.EvaluateNow();
}
/// <summary>
/// Synchronously creates a new object
/// </summary>
public static Value NewObject(Process process, ICorDebugClass classToCreate)
{
Eval eval = new NewObjectEval(
return AsyncNewObject(process, classToCreate).EvaluateNow();
}
public static Eval AsyncNewObject(Process process, ICorDebugClass classToCreate)
{
return new Eval(
process,
"New object: " + classToCreate.Token,
new IExpirable[] {},
new IMutable[] {},
classToCreate
delegate(ICorDebugEval corEval) { corEval.NewObjectNoConstructor(classToCreate); }
);
eval.Description = "New object: " + classToCreate.Token;
return eval.EvaluateNow();
}
protected override ICorDebugValue RawCorValue {
get {
switch(this.State) {
case EvalState.WaitingForRequest: ScheduleEvaluation(); goto case EvalState.EvaluationScheduled;
case EvalState.EvaluationScheduled: throw new CannotGetValueException("Evaluation pending");
case EvalState.Evaluating: throw new CannotGetValueException("Evaluating...");
case EvalState.EvaluatedSuccessfully: return currentCorValue;
case EvalState.EvaluatedException: return currentCorValue;
case EvalState.EvaluatedNoResult: throw new CannotGetValueException("No return value");
case EvalState.EvaluatedError: throw new CannotGetValueException(currentErrorMsg);
default: throw new DebuggerException("Unknown state");
}
}
}
public void ScheduleEvaluation()
public void RequestEvaluation()
{
if (Evaluated || State == EvalState.WaitingForRequest) {
process.ScheduleEval(this);
process.Debugger.MTA2STA.AsyncCall(delegate { process.StartEvaluation(); });
SetState(EvalState.EvaluationScheduled, null, null);
ChangeState(EvalState.EvaluationScheduled, null, null);
}
}
@ -173,7 +229,7 @@ namespace Debugger @@ -173,7 +229,7 @@ namespace Debugger
corEval = targetThread.CorThread.CreateEval();
try {
StartEvaluation();
evaluationInvoker(corEval);
} catch (COMException e) {
if ((uint)e.ErrorCode == 0x80131C26) {
throw new EvalSetupException("Can not evaluate in optimized code");
@ -187,24 +243,22 @@ namespace Debugger @@ -187,24 +243,22 @@ namespace Debugger
}
}
SetState(EvalState.Evaluating, null, null);
ChangeState(EvalState.Evaluating, null, null);
return true;
} catch (EvalSetupException e) {
SetState(EvalState.EvaluatedError, e.Message, null);
ChangeState(EvalState.EvaluatedError, e.Message, null);
return false;
}
}
protected abstract void StartEvaluation();
public Value EvaluateNow()
{
while (State == EvalState.WaitingForRequest) {
ScheduleEvaluation();
RequestEvaluation();
process.WaitForPause();
process.WaitForPause();
}
return this;
return this.Result;
}
internal void NotifyEvaluationComplete(bool successful)
@ -212,12 +266,12 @@ namespace Debugger @@ -212,12 +266,12 @@ namespace Debugger
// Eval result should be ICorDebugHandleValue so it should survive Continue()
if (corEval.Result == null) {
SetState(EvalState.EvaluatedNoResult, null, null);
ChangeState(EvalState.EvaluatedNoResult, null, null);
} else {
if (successful) {
SetState(EvalState.EvaluatedSuccessfully, null, corEval.Result);
ChangeState(EvalState.EvaluatedSuccessfully, null, corEval.Result);
} else {
SetState(EvalState.EvaluatedException, null, corEval.Result);
ChangeState(EvalState.EvaluatedException, null, corEval.Result);
}
}
}

5
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/EvalEventArgs.cs

@ -9,17 +9,22 @@ using System; @@ -9,17 +9,22 @@ using System;
namespace Debugger
{
/// <summary>
/// Provides data related to evalution events
/// </summary>
[Serializable]
public class EvalEventArgs : ProcessEventArgs
{
Eval eval;
/// <summary> The evaluation that caused the event </summary>
public Eval Eval {
get {
return eval;
}
}
/// <summary> Initializes a new instance of the class </summary>
public EvalEventArgs(Eval eval): base(eval.Process)
{
this.eval = eval;

31
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/NewObjectEval.cs

@ -1,31 +0,0 @@ @@ -1,31 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
class NewObjectEval: Eval
{
ICorDebugClass classToCreate;
public NewObjectEval(Process process,
IExpirable[] expireDependencies,
IMutable[] mutateDependencies,
ICorDebugClass classToCreate)
:base(process, expireDependencies, mutateDependencies)
{
this.classToCreate = classToCreate;
}
protected override void StartEvaluation()
{
corEval.NewObjectNoConstructor(classToCreate);
}
}
}

30
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/NewStringEval.cs

@ -1,30 +0,0 @@ @@ -1,30 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
namespace Debugger
{
class NewStringEval: Eval
{
string textToCreate;
public NewStringEval(Process process,
IExpirable[] expireDependencies,
IMutable[] mutateDependencies,
string textToCreate)
:base(process, expireDependencies, mutateDependencies)
{
this.textToCreate = textToCreate;
}
protected override void StartEvaluation()
{
corEval.NewString(textToCreate);
}
}
}

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/Process-Evals.cs

@ -25,7 +25,7 @@ namespace Debugger @@ -25,7 +25,7 @@ namespace Debugger
internal Eval GetEval(ICorDebugEval corEval)
{
return activeEvals.Find(delegate (Eval eval) {return eval.CorEval == corEval;});
return activeEvals.Find(delegate (Eval eval) {return eval.IsCorEval(corEval);});
}
/// <summary>

31
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/MethodArgument.cs

@ -1,31 +0,0 @@ @@ -1,31 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
public class MethodArgument: Variable
{
int index;
public int Index {
get {
return index;
}
}
public MethodArgument(string name, int index, Value @value)
:base (name, @value)
{
this.index = index;
}
}
}

43
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/NullValue.cs

@ -1,43 +0,0 @@ @@ -1,43 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
namespace Debugger
{
public class NullValue: ValueProxy
{
public override string AsString {
get {
return "<null reference>";
}
}
public override string Type {
get {
switch (TheValue.CorType) {
case CorElementType.SZARRAY:
case CorElementType.ARRAY: return typeof(System.Array).ToString();
case CorElementType.OBJECT: return typeof(System.Object).ToString();
case CorElementType.STRING: return typeof(System.String).ToString();
case CorElementType.CLASS: return "<class>";
default: return string.Empty;
}
}
}
internal unsafe NullValue(Value @value):base(@value)
{
}
protected override bool GetMayHaveSubVariables()
{
return false;
}
}
}

50
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ObjectMember.cs

@ -1,50 +0,0 @@ @@ -1,50 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
/// <summary>
/// Provides information about a member of a given object.
/// In particular, it allows to access the value.
/// </summary>
public class ObjectMember: Variable
{
[Flags]
public enum Flags { Default = Public, None = 0, Public = 1, Static = 2, PublicStatic = Public | Static};
Flags memberFlags;
public Flags MemberFlags {
get {
return memberFlags;
}
}
public bool IsStatic {
get {
return (memberFlags & Flags.Static) != 0;
}
}
public bool IsPublic {
get {
return (memberFlags & Flags.Public) != 0;
}
}
public ObjectMember(string name, Flags flags, Value @value)
:base (name, @value)
{
this.memberFlags = flags;
}
}
}

101
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ObjectValue.cs

@ -1,101 +0,0 @@ @@ -1,101 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
public class ObjectValue: ValueProxy
{
ObjectValueClass topClass;
Value toStringText;
public override string AsString {
get {
return "{" + Type + "}";
}
}
public Value ToStringText {
get {
return toStringText;
}
}
public override string Type {
get {
return topClass.Type;
}
}
public ObjectValueClass TopClass {
get {
return topClass;
}
}
public IEnumerable<ObjectValueClass> Classes {
get {
ObjectValueClass currentClass = topClass;
do {
yield return currentClass;
currentClass = currentClass.BaseClass;
} while (currentClass != null);
}
}
public ObjectValueClass GetClass(string type)
{
foreach(ObjectValueClass cls in Classes) {
if (cls.Type == type) return cls;
}
return null;
}
internal bool IsInClassHierarchy(ICorDebugClass corClass)
{
foreach(ObjectValueClass cls in Classes) {
if (cls.CorClass == corClass) return true;
}
return false;
}
internal ObjectValue(Value @value):base(@value)
{
topClass = new ObjectValueClass(this, TheValue.CorValue.As<ICorDebugObjectValue>().Class);
Module module = GetClass("System.Object").Module;
ICorDebugFunction corFunction = module.GetMethod("System.Object", "ToString", 0);
toStringText = new CallFunctionEval(TheValue.Process,
new IExpirable[] {this.TheValue},
new IMutable[] {this.TheValue},
corFunction,
TheValue,
new Value[] {});
}
internal bool IsCorValueCompatible {
get {
ObjectValue freshValue = TheValue.ValueProxy as ObjectValue;
return freshValue != null &&
topClass.Module == freshValue.TopClass.Module &&
topClass.ClassToken == freshValue.TopClass.ClassToken;
}
}
protected override bool GetMayHaveSubVariables()
{
return true;
}
protected override VariableCollection GetSubVariables()
{
return topClass.SubVariables;
}
}
}

232
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ObjectValueClass.cs

@ -1,232 +0,0 @@ @@ -1,232 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
using Debugger.Wrappers.MetaData;
namespace Debugger
{
public class ObjectValueClass: RemotingObjectBase
{
Process process;
ObjectValue objectValue;
Module module;
ICorDebugClass corClass;
TypeDefProps classProps;
ICorDebugObjectValue CorObjectValue {
get {
return objectValue.TheValue.CorValue.As<ICorDebugObjectValue>();
}
}
bool IsCorValueCompatible {
get {
return objectValue.IsCorValueCompatible;
}
}
public Module Module {
get {
return module;
}
}
public string Type {
get{
return classProps.Name;
}
}
internal ICorDebugClass CorClass {
get {
return corClass;
}
}
public uint ClassToken {
get {
return classProps.Token;
}
}
public ObjectValueClass(ObjectValue objectValue, ICorDebugClass corClass)
{
this.process = objectValue.TheValue.Process;
this.objectValue = objectValue;
this.module = process.GetModule(corClass.Module);
this.corClass = corClass;
this.classProps = Module.MetaData.GetTypeDefProps(corClass.Token);
}
public VariableCollection SubVariables {
get {
return new VariableCollection("Base class",
"{" + Type + "}",
SubCollections,
GetSubVariables(ObjectMember.Flags.Public, ObjectMember.Flags.PublicStatic));
}
}
IEnumerable<VariableCollection> SubCollections {
get {
ObjectValueClass baseClass = BaseClass;
VariableCollection privateStatic = new VariableCollection("Private static members",
String.Empty,
new VariableCollection[0],
GetSubVariables(ObjectMember.Flags.Static, ObjectMember.Flags.PublicStatic));
VariableCollection privateInstance = new VariableCollection("Private members",
String.Empty,
privateStatic.IsEmpty? new VariableCollection[0] : new VariableCollection[] {privateStatic},
GetSubVariables(ObjectMember.Flags.None, ObjectMember.Flags.PublicStatic));
VariableCollection publicStatic = new VariableCollection("Static members",
String.Empty,
new VariableCollection[0],
GetSubVariables(ObjectMember.Flags.PublicStatic, ObjectMember.Flags.PublicStatic));
if (baseClass != null) {
yield return baseClass.SubVariables;
}
if (!privateInstance.IsEmpty) {
yield return privateInstance;
}
if (!publicStatic.IsEmpty) {
yield return publicStatic;
}
}
}
IEnumerable<Variable> GetSubVariables(ObjectMember.Flags requiredFlags, ObjectMember.Flags mask) {
foreach(ObjectMember var in GetFieldVariables()) {
if ((var.MemberFlags & mask) == requiredFlags) {
yield return var;
}
}
foreach(ObjectMember var in GetPropertyVariables()) {
if ((var.MemberFlags & mask) == requiredFlags) {
yield return var;
}
}
}
public ObjectValueClass BaseClass {
get {
ICorDebugClass superClass = GetSuperClass(process, corClass);
if (superClass != null) {
return new ObjectValueClass(objectValue, superClass);
} else {
return null;
}
}
}
public IEnumerable<ObjectMember> GetFieldVariables()
{
foreach(FieldProps f in Module.MetaData.EnumFields(ClassToken)) {
FieldProps field = f; // One per scope/delegate
if (field.IsStatic && field.IsLiteral) continue; // Skip field
yield return new ObjectMember(
field.Name,
(field.IsStatic ? ObjectMember.Flags.Static : ObjectMember.Flags.None) |
(field.IsPublic ? ObjectMember.Flags.Public : ObjectMember.Flags.None),
new Value(
process,
new IExpirable[] {this.objectValue.TheValue},
new IMutable[] {this.objectValue.TheValue},
delegate { return GetCorValueOfField(field); }
)
);
}
}
ICorDebugValue GetCorValueOfField(FieldProps field)
{
if (!IsCorValueCompatible) throw new CannotGetValueException("Object type changed");
// Current frame is used to resolve context specific static values (eg. ThreadStatic)
ICorDebugFrame curFrame = null;
if (process.IsPaused && process.SelectedThread != null && process.SelectedThread.LastFunction != null && process.SelectedThread.LastFunction.CorILFrame != null) {
curFrame = process.SelectedThread.LastFunction.CorILFrame.CastTo<ICorDebugFrame>();
}
try {
if (field.IsStatic) {
return corClass.GetStaticFieldValue(field.Token, curFrame);
} else {
return CorObjectValue.GetFieldValue(corClass, field.Token);
}
} catch {
throw new CannotGetValueException("Can not get value of field");
}
}
IEnumerable<MethodProps> Methods {
get {
return this.Module.MetaData.EnumMethods(this.ClassToken);
}
}
public IEnumerable<ObjectMember> GetPropertyVariables()
{
foreach(MethodProps m in Methods) {
MethodProps method = m; // One per scope/delegate
if (method.HasSpecialName && method.Name.StartsWith("get_") && method.Name != "get_Item") {
ObjectMember.Flags flags = (method.IsStatic ? ObjectMember.Flags.Static : ObjectMember.Flags.None) |
(method.IsPublic ? ObjectMember.Flags.Public : ObjectMember.Flags.None);
yield return new ObjectMember(
method.Name.Remove(0, 4),
flags,
new CallFunctionEval(
process,
new IExpirable[] {this.objectValue.TheValue},
new IMutable[] {process.DebugeeState},
Module.CorModule.GetFunctionFromToken(method.Token),
method.IsStatic ? null : this.objectValue.TheValue, // this
new Value[] {}
)
); // args
}
}
}
protected static ICorDebugClass GetSuperClass(Process process, ICorDebugClass currClass)
{
Module currModule = process.GetModule(currClass.Module);
uint superToken = currModule.MetaData.GetTypeDefProps(currClass.Token).SuperClassToken;
// It has no base class
if ((superToken & 0x00FFFFFF) == 0x00000000) return null;
// TypeDef - Localy defined
if ((superToken & 0xFF000000) == 0x02000000) {
return currModule.CorModule.GetClassFromToken(superToken);
}
// TypeRef - Referencing to external assembly
if ((superToken & 0xFF000000) == 0x01000000) {
string fullTypeName = currModule.MetaData.GetTypeRefProps(superToken).Name;
foreach (Module superModule in process.Modules) {
// TODO: Does not work for nested
// TODO: preservesig
try {
uint token = superModule.MetaData.FindTypeDefByName(fullTypeName, 0).Token;
return superModule.CorModule.GetClassFromToken(token);
} catch {
continue;
}
}
}
throw new DebuggerException("Superclass not found");
}
}
}

61
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PrimitiveValue.cs

@ -1,61 +0,0 @@ @@ -1,61 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.ComponentModel;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
public class PrimitiveValue: ValueProxy
{
public override string AsString {
get {
if (Primitive != null) {
return Primitive.ToString();
} else {
return String.Empty;
}
}
}
public object Primitive {
get {
if (TheValue.CorType == CorElementType.STRING) {
return (TheValue.CorValue.CastTo<ICorDebugStringValue>()).String;
} else {
return (TheValue.CorValue.CastTo<ICorDebugGenericValue>()).Value;
}
}
set {
object newValue;
TypeConverter converter = TypeDescriptor.GetConverter(ManagedType);
try {
newValue = converter.ConvertFrom(value);
} catch {
throw new NotSupportedException("Can not convert " + value.GetType().ToString() + " to " + ManagedType.ToString());
}
if (TheValue.CorType == CorElementType.STRING) {
throw new NotSupportedException();
} else {
(TheValue.CorValue.CastTo<ICorDebugGenericValue>()).Value = newValue;
}
TheValue.NotifyChange();
}
}
internal PrimitiveValue(Value @value):base(@value)
{
}
protected override bool GetMayHaveSubVariables()
{
return false;
}
}
}

296
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/SignatureStream.cs

@ -1,296 +0,0 @@ @@ -1,296 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Runtime.InteropServices;
namespace Debugger {
unsafe class SignatureStream {
byte[] signature;
int currentPos;
public SignatureStream (byte[] signature)
{
this.signature = signature;
currentPos = 0;
}
public SignatureStream (IntPtr pSigBlob, uint sigBlobSize)
{
signature = new Byte[sigBlobSize];
Marshal.Copy(pSigBlob, signature, 0, (int)sigBlobSize);
currentPos = 0;
}
public bool EndOfStream {
get {
return currentPos >= signature.Length;
}
}
byte PeekByte {
get {
if (EndOfStream) throw new BadSignatureException();
return signature[currentPos];
}
}
byte ReadByte {
get {
byte value = PeekByte;
currentPos++;
return value;
}
}
uint ReadData(out int compressedSize)
{
if ((PeekByte & 0x80) == 0x00) {
compressedSize = 1;
return ReadByte;
}
if ((PeekByte & 0xC0) == 0x80) {
compressedSize = 2;
return (uint)(
(ReadByte & 0x3F) * 0x100 +
ReadByte
);
}
if ((PeekByte & 0xE0) == 0xC0) {
compressedSize = 4;
return (uint)(
(ReadByte & 0x1F) * 0x1000000 +
ReadByte * 0x10000 +
ReadByte * 0x100 +
ReadByte
);
}
throw new BadSignatureException();
}
public uint PeekData()
{
int oldPos = currentPos;
uint res = ReadData();
currentPos = oldPos;
return res;
}
public uint ReadData()
{
int compressedSize;
return ReadData(out compressedSize);
}
CorTokenType[] encodeTokenType = new CorTokenType[] {CorTokenType.mdtTypeDef, CorTokenType.mdtTypeRef, CorTokenType.mdtTypeSpec, CorTokenType.mdtBaseType};
public uint PeekToken()
{
int oldPos = currentPos;
uint res = ReadToken();
currentPos = oldPos;
return res;
}
public uint ReadToken()
{
uint data;
uint tokenType;
data = ReadData();
tokenType = (uint)encodeTokenType[data & 0x3];
return (data >> 2) | tokenType;
}
public uint PeekSignedInt()
{
int oldPos = currentPos;
uint res = ReadSignedInt();
currentPos = oldPos;
return res;
}
public uint ReadSignedInt()
{
int compressedSize;
bool signed;
uint data;
data = ReadData(out compressedSize);
signed = (data & 0x1) == 1;
data = data >> 1;
if (signed) {
switch (compressedSize) {
case 1:
data |= 0xffffffc0;
break;
case 2:
data |= 0xffffe000;
break;
case 4:
data |= 0xf0000000;
break;
default:
throw new BadSignatureException();
}
}
return data;
}
public uint PeekCallingConv()
{
int oldPos = currentPos;
uint res = ReadCallingConv();
currentPos = oldPos;
return res;
}
public uint ReadCallingConv()
{
return ReadData();
}
public CorElementType PeekElementType()
{
int oldPos = currentPos;
CorElementType res = ReadElementType();
currentPos = oldPos;
return res;
}
public CorElementType ReadElementType()
{
return (CorElementType)ReadData();
}
public void ReadCustomMod()
{
while (PeekElementType() == CorElementType.CMOD_OPT ||
PeekElementType() == CorElementType.CMOD_REQD) {
ReadElementType();
ReadToken();
}
}
public string ReadType()
{
CorElementType type = ReadElementType();
switch(type)
{
case CorElementType.BOOLEAN:
case CorElementType.CHAR:
case CorElementType.I1:
case CorElementType.U1:
case CorElementType.I2:
case CorElementType.U2:
case CorElementType.I4:
case CorElementType.U4:
case CorElementType.I8:
case CorElementType.U8:
case CorElementType.R4:
case CorElementType.R8:
case CorElementType.I:
case CorElementType.U:
case CorElementType.STRING:
case CorElementType.OBJECT:
return type.ToString();
case CorElementType.VALUETYPE:
case CorElementType.CLASS:
ReadToken();
return type.ToString();
case CorElementType.PTR:
ReadCustomMod();
if (PeekElementType() == CorElementType.VOID) {
ReadElementType();
break;
} else {
return "Pointer:" + ReadType();
}
case CorElementType.FNPTR:
ReadFunction();
break;
case CorElementType.ARRAY:
ReadType();
ReadArrayShape();
break;
case CorElementType.SZARRAY: // Short-cut for single dimension zero lower bound array
ReadCustomMod();
ReadType();
break;
default:
throw new BadSignatureException();
}
return "";
}
public void ReadArrayShape()
{
ReadData(); //rank
uint numSizes = ReadData();
for (int i = 0; i < numSizes; i++) {
ReadData(); //size
}
if (numSizes > 0) {
uint numLoBounds = ReadData();
for (int i = 0; i < numLoBounds; i++) {
ReadData(); //LoBound
}
}
}
public void ReadFunction()
{
uint callConv = ReadCallingConv();
uint paramCount = ReadData();
// Read return type
switch (ReadElementType()) {
case CorElementType.BYREF:
ReadType();
break;
case CorElementType.TYPEDBYREF:
break;
case CorElementType.VOID:
break;
default:
throw new BadSignatureException();
}
// Read params
for (int i = 0; i < paramCount; i++) {
ReadCustomMod();
switch (PeekElementType()) {
case CorElementType.BYREF:
ReadElementType();
ReadType();
break;
case CorElementType.TYPEDBYREF:
ReadElementType();
break;
default:
ReadType();
break;
}
}
}
}
}

32
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/BindingFlags.cs

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision: 2023 $</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
using Debugger.Wrappers.MetaData;
namespace Debugger
{
/// <summary>
/// Binding flags specify which members should be returned.
/// <para> Use 'or' operation to combine flags. </para>
/// </summary>
[Flags]
public enum BindingFlags {
/// Return instance (ie non-static members) members
Instance,
/// Return static members
Static,
/// Return public members
Public,
/// Return members which are not public
NonPublic,
/// Return all members
All = Instance | Static | Public | NonPublic
};
}

102
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/DebugType-Helpers.cs

@ -0,0 +1,102 @@ @@ -0,0 +1,102 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision: 2023 $</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
using Debugger.Wrappers.MetaData;
namespace Debugger
{
public partial class DebugType
{
IList<T> FilterMemberInfo<T>(List<T> input, BindingFlags bindingFlags) where T:MemberInfo
{
List<T> filtered = new List<T>();
foreach(T memberInfo in input) {
if (memberInfo.IsStatic && ((bindingFlags & BindingFlags.Static) != 0) ||
!memberInfo.IsStatic && ((bindingFlags & BindingFlags.Instance) != 0)) {
if (memberInfo.IsPrivate && ((bindingFlags & BindingFlags.NonPublic) != 0) ||
memberInfo.IsPublic && ((bindingFlags & BindingFlags.Public) != 0)) {
filtered.Add(memberInfo);
}
}
}
return filtered.AsReadOnly();
}
/// <summary>
/// Returns simple managed type coresponding to the debug type.
/// Any class yields System.Object
/// </summary>
public System.Type ManagedType {
get {
switch(this.corElementType) {
case CorElementType.BOOLEAN: return typeof(System.Boolean);
case CorElementType.CHAR: return typeof(System.Char);
case CorElementType.I1: return typeof(System.SByte);
case CorElementType.U1: return typeof(System.Byte);
case CorElementType.I2: return typeof(System.Int16);
case CorElementType.U2: return typeof(System.UInt16);
case CorElementType.I4: return typeof(System.Int32);
case CorElementType.U4: return typeof(System.UInt32);
case CorElementType.I8: return typeof(System.Int64);
case CorElementType.U8: return typeof(System.UInt64);
case CorElementType.R4: return typeof(System.Single);
case CorElementType.R8: return typeof(System.Double);
case CorElementType.I: return typeof(int);
case CorElementType.U: return typeof(uint);
case CorElementType.SZARRAY:
case CorElementType.ARRAY: return typeof(System.Array);
case CorElementType.OBJECT: return typeof(System.Object);
case CorElementType.STRING: return typeof(System.String);
default: return null;
}
}
}
/*
* Find the super class manually - unused since we have ICorDebugType.GetBase() in .NET 2.0
*
protected static ICorDebugClass GetSuperClass(Process process, ICorDebugClass currClass)
{
Module currModule = process.GetModule(currClass.Module);
uint superToken = currModule.MetaData.GetTypeDefProps(currClass.Token).SuperClassToken;
// It has no base class
if ((superToken & 0x00FFFFFF) == 0x00000000) return null;
// TypeDef - Localy defined
if ((superToken & 0xFF000000) == 0x02000000) {
return currModule.CorModule.GetClassFromToken(superToken);
}
// TypeRef - Referencing to external assembly
if ((superToken & 0xFF000000) == 0x01000000) {
string fullTypeName = currModule.MetaData.GetTypeRefProps(superToken).Name;
foreach (Module superModule in process.Modules) {
// TODO: Does not work for nested
// TODO: preservesig
try {
uint token = superModule.MetaData.FindTypeDefByName(fullTypeName, 0).Token;
return superModule.CorModule.GetClassFromToken(token);
} catch {
continue;
}
}
}
// TODO: Can also be TypeSpec = 0x1b000000
throw new DebuggerException("Superclass not found");
}
*/
}
}

340
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/DebugType.cs

@ -0,0 +1,340 @@ @@ -0,0 +1,340 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
using Debugger.Wrappers.MetaData;
namespace Debugger
{
/// <summary>
/// Represents a type in a debugee. That is, a class, array, value type or a primitive type.
/// <para> This class mimics the <see cref="System.Type"/> class. </para>
/// </summary>
public partial class DebugType: RemotingObjectBase
{
Process process;
ICorDebugType corType;
CorElementType corElementType;
// Class/ValueType specific data
ICorDebugClass corClass;
Module module;
TypeDefProps classProps;
// Cache
List<FieldInfo> fields;
List<MethodInfo> methods;
List<PropertyInfo> properties;
void AssertClassOrValueType()
{
if(!IsClass && !IsValueType) {
throw new DebuggerException("The type is not a class or value type.");
}
}
/// <summary> Gets the process in which the type was loaded </summary>
public Process Process {
get {
return process;
}
}
internal ICorDebugType CorType {
get {
return corType;
}
}
/// <summary>
/// Gets the module in which the class or value type is defined.
/// <para> Only applicable to class or value type! </para>
/// </summary>
public Module Module {
get {
AssertClassOrValueType();
return module;
}
}
/// <summary>
/// Gets the metadata token of the class or value type.
/// <para> Only applicable to class or value type! </para>
/// </summary>
public uint MetadataToken {
get {
AssertClassOrValueType();
return classProps.Token;
}
}
/// <summary> Returns a string describing the type </summary>
public string Name {
get {
// TODO: Improve
if(IsClass || IsValueType) {
return classProps.Name;
} else {
System.Type managedType = this.ManagedType;
if (managedType != null) {
return managedType.ToString();
} else {
return "<unknown>";
}
}
}
}
/// <summary> Gets a value indicating whether the type is an array </summary>
public bool IsArray {
get {
return this.corElementType == CorElementType.ARRAY ||
this.corElementType == CorElementType.SZARRAY;
}
}
/// <summary> Gets a value indicating whether the type is a class </summary>
public bool IsClass {
get {
return this.corElementType == CorElementType.CLASS ||
this.corElementType == CorElementType.OBJECT;
}
}
/// <summary> Gets a value indicating whether the type is a value type (that is, a structre in C#) </summary>
public bool IsValueType {
get {
return this.corElementType == CorElementType.VALUETYPE;
}
}
/// <summary> Gets a value indicating whether the type is a primitive type </summary>
public bool IsPrimitive {
get {
return this.corElementType == CorElementType.BOOLEAN ||
this.corElementType == CorElementType.CHAR ||
this.corElementType == CorElementType.I1 ||
this.corElementType == CorElementType.U1 ||
this.corElementType == CorElementType.I2 ||
this.corElementType == CorElementType.U2 ||
this.corElementType == CorElementType.I4 ||
this.corElementType == CorElementType.U4 ||
this.corElementType == CorElementType.I8 ||
this.corElementType == CorElementType.U8 ||
this.corElementType == CorElementType.R4 ||
this.corElementType == CorElementType.R8 ||
this.corElementType == CorElementType.I ||
this.corElementType == CorElementType.U ||
this.corElementType == CorElementType.STRING;
}
}
/// <summary> Gets a value indicating whether the type is an integer type </summary>
public bool IsInteger {
get {
return this.corElementType == CorElementType.I1 ||
this.corElementType == CorElementType.U1 ||
this.corElementType == CorElementType.I2 ||
this.corElementType == CorElementType.U2 ||
this.corElementType == CorElementType.I4 ||
this.corElementType == CorElementType.U4 ||
this.corElementType == CorElementType.I8 ||
this.corElementType == CorElementType.U8 ||
this.corElementType == CorElementType.I ||
this.corElementType == CorElementType.U;
}
}
/// <summary>
/// Gets the type from which this type inherits.
/// <para>
/// Returns null if the current type is <see cref="System.Object"/>.
/// </para>
/// </summary>
public DebugType BaseType {
get {
ICorDebugType baseType = corType.Base;
if (baseType != null) {
return new DebugType(process, baseType);
} else {
return null;
}
}
}
internal DebugType(Process process, ICorDebugType corType)
{
if (corType == null) throw new ArgumentNullException("corType");
this.process = process;
this.corType = corType;
this.corElementType = (CorElementType)corType.Type;
if (this.IsClass || this.IsValueType) {
this.corClass = corType.Class;
this.module = process.GetModule(corClass.Module);
this.classProps = module.MetaData.GetTypeDefProps(corClass.Token);
}
process.TraceMessage("Created type " + this.Name);
}
/// <summary>
/// Obtains instance of DebugType using process cache
/// </summary>
static internal DebugType Create(Process process, ICorDebugType corType)
{
return process.GetDebugType(corType);
}
/// <summary> Determines whether the current type is sublass of
/// the the given type. That is, it derives from the given type. </summary>
/// <remarks> Returns false if the given type is same as the current type </remarks>
public bool IsSubclassOf(DebugType superType)
{
DebugType type = this.BaseType;
while (type != null) {
if (this.Equals(type)) return true;
type = type.BaseType;
}
return false;
}
/// <summary> Determines whether the given object is instance of the
/// current type or can be implicitly cast to it </summary>
public bool IsInstanceOfType(Value objectInstance)
{
return this.Equals(objectInstance.Type) ||
this.IsSubclassOf(objectInstance.Type);
}
List<FieldInfo> GetAllFields()
{
AssertClassOrValueType();
// Build cache
if (fields == null) {
process.TraceMessage("Loading fields for type " + this.Name);
fields = new List<FieldInfo>();
foreach(FieldProps field in module.MetaData.EnumFields(this.MetadataToken)) {
// TODO: Why?
if (field.IsStatic && field.IsLiteral) continue; // Skip static literals
fields.Add(new FieldInfo(this, field));
};
}
return fields;
}
List<MethodInfo> GetAllMethods()
{
AssertClassOrValueType();
// Build cache
if (methods == null) {
process.TraceMessage("Loading methods for type " + this.Name);
methods = new List<MethodInfo>();
foreach(MethodProps m in module.MetaData.EnumMethods(this.MetadataToken)) {
methods.Add(new MethodInfo(this, m));
}
}
return methods;
}
// TODO: Handle indexers ("get_Item") in other code
List<PropertyInfo> GetAllProperties()
{
AssertClassOrValueType();
// Build cache
if (properties == null) {
process.TraceMessage("Loading properties for type " + this.Name);
properties = new List<PropertyInfo>();
// Collect data
Dictionary<string, MethodInfo> methods = new Dictionary<string, MethodInfo>();
Dictionary<string, object> names = new Dictionary<string, object>();
foreach(MethodInfo method in GetAllMethods()) {
if (method.IsSpecialName && (method.Name.StartsWith("get_") || method.Name.StartsWith("set_"))) {
methods.Add(method.Name, method);
names.Add(method.Name.Remove(0,4), null);
}
}
// Pair up getters and setters
foreach(KeyValuePair<string, object> kvp in names) {
MethodInfo getter = null;
MethodInfo setter = null;
methods.TryGetValue("get_" + kvp.Key, out getter);
methods.TryGetValue("set_" + kvp.Key, out setter);
properties.Add(new PropertyInfo(this, getter, setter));
}
}
return properties;
}
/// <summary> Return all public fields.</summary>
public IList<FieldInfo> GetFields()
{
return GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
}
/// <summary> Return all fields satisfing binding flags.</summary>
public IList<FieldInfo> GetFields(BindingFlags bindingFlags)
{
if (IsClass || IsValueType) {
return FilterMemberInfo(GetAllFields(), bindingFlags);
} else {
return new List<FieldInfo>();
}
}
/// <summary> Return all public methods.</summary>
public IList<MethodInfo> GetMethods()
{
return GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
}
/// <summary> Return all methods satisfing binding flags.</summary>
public IList<MethodInfo> GetMethods(BindingFlags bindingFlags)
{
if (IsClass || IsValueType) {
return FilterMemberInfo(GetAllMethods(), bindingFlags);
} else {
return new List<MethodInfo>();
}
}
/// <summary> Return all public properties.</summary>
public IList<PropertyInfo> GetProperties()
{
return GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
}
/// <summary> Return all properties satisfing binding flags.</summary>
public IList<PropertyInfo> GetProperties(BindingFlags bindingFlags)
{
if (IsClass || IsValueType) {
return FilterMemberInfo(GetAllProperties(), bindingFlags);
} else {
return new List<PropertyInfo>();
}
}
/// <summary> Compares two types </summary>
public override bool Equals(object obj)
{
return obj is DebugType &&
((DebugType)obj).CorType == this.CorType;
}
/// <summary> Get hash code of the object </summary>
public override int GetHashCode()
{
return base.GetHashCode();
}
}
}

109
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/FieldInfo.cs

@ -0,0 +1,109 @@ @@ -0,0 +1,109 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision: 2023 $</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
using Debugger.Wrappers.MetaData;
namespace Debugger
{
/// <summary>
/// Provides information about a field of some class.
/// </summary>
public class FieldInfo: MemberInfo
{
FieldProps fieldProps;
/// <summary> Gets a value indicating whether this field is literal field </summary>
public bool IsLiteral {
get {
return fieldProps.IsLiteral;
}
}
/// <summary> Gets a value indicating whether this field is private </summary>
public override bool IsPrivate {
get {
return !fieldProps.IsPublic;
}
}
/// <summary> Gets a value indicating whether this field is public </summary>
public override bool IsPublic {
get {
return fieldProps.IsPublic;
}
}
/// <summary> Gets a value indicating whether this field is static </summary>
public override bool IsStatic {
get {
return fieldProps.IsStatic;
}
}
/// <summary> Gets the metadata token associated with this field </summary>
public override uint MetadataToken {
get {
return fieldProps.Token;
}
}
/// <summary> Gets the name of this field </summary>
public override string Name {
get {
return fieldProps.Name;
}
}
internal FieldInfo(DebugType declaringType, FieldProps fieldProps):base (declaringType)
{
this.fieldProps = fieldProps;
}
/// <summary>
/// Given an object of correct type, get the value of this field
/// </summary>
public MemberValue GetValue(Value objectInstance) {
return new MemberValue(
this,
this.Process,
new IExpirable[] {objectInstance},
new IMutable[] {objectInstance},
delegate { return GetCorValue(objectInstance); }
);
}
ICorDebugValue GetCorValue(Value objectInstance)
{
if (!DeclaringType.IsInstanceOfType(objectInstance)) {
throw new CannotGetValueException("Object is not of type " + DeclaringType.Name);
}
// Current frame is used to resolve context specific static values (eg. ThreadStatic)
ICorDebugFrame curFrame = null;
if (this.Process.IsPaused &&
this.Process.SelectedThread != null &&
this.Process.SelectedThread.LastFunction != null &&
this.Process.SelectedThread.LastFunction.CorILFrame != null) {
curFrame = this.Process.SelectedThread.LastFunction.CorILFrame.CastTo<ICorDebugFrame>();
}
try {
if (this.IsStatic) {
return DeclaringType.CorType.GetStaticFieldValue(MetadataToken, curFrame);
} else {
return objectInstance.CorObjectValue.GetFieldValue(DeclaringType.CorType.Class, MetadataToken);
}
} catch {
throw new CannotGetValueException("Can not get value of field");
}
}
}
}

64
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/MemberInfo.cs

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision: 2023 $</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
using Debugger.Wrappers.MetaData;
namespace Debugger
{
/// <summary>
/// Provides information about a member of some class
/// (eg. a field or a method).
/// </summary>
public abstract class MemberInfo: RemotingObjectBase
{
DebugType declaringType;
/// <summary> Gets the process in which the type was loaded </summary>
public Process Process {
get {
return declaringType.Process;
}
}
/// <summary> Gets the type that declares this member element </summary>
public DebugType DeclaringType {
get {
return declaringType;
}
}
/// <summary> Gets a value indicating whether this member is private </summary>
public abstract bool IsPrivate { get; }
/// <summary> Gets a value indicating whether this member is public </summary>
public abstract bool IsPublic { get; }
/// <summary> Gets a value indicating whether this member is static </summary>
public abstract bool IsStatic { get; }
/// <summary> Gets the metadata token associated with this member </summary>
public abstract uint MetadataToken { get; }
/// <summary> Gets the name of this member </summary>
public abstract string Name { get; }
/// <summary> Gets the module in which this member is defined </summary>
public Module Module {
get {
return declaringType.Module;
}
}
internal MemberInfo(DebugType declaringType)
{
this.declaringType = declaringType;
}
}
}

126
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/MethodInfo.cs

@ -0,0 +1,126 @@ @@ -0,0 +1,126 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision: 2023 $</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
using Debugger.Wrappers.MetaData;
namespace Debugger
{
/// <summary>
/// Provides information about a method in a class
/// </summary>
public class MethodInfo: MemberInfo
{
MethodProps methodProps;
/// <summary> Gets a value indicating whether this method is private </summary>
public override bool IsPrivate {
get {
return !methodProps.IsPublic;
}
}
/// <summary> Gets a value indicating whether this method is public </summary>
public override bool IsPublic {
get {
return methodProps.IsPublic;
}
}
/// <summary> Gets a value indicating whether the name of this method
/// is marked as specail.</summary>
/// <remarks> For example, property accessors are marked as special </remarks>
public bool IsSpecialName {
get {
return methodProps.HasSpecialName;
}
}
/// <summary> Gets a value indicating whether this method is static </summary>
public override bool IsStatic {
get {
return methodProps.IsStatic;
}
}
/// <summary> Gets the metadata token associated with this method </summary>
public override uint MetadataToken {
get {
return methodProps.Token;
}
}
/// <summary> Gets the name of this method </summary>
public override string Name {
get {
return methodProps.Name;
}
}
internal ICorDebugFunction CorFunction {
get {
return this.Module.CorModule.GetFunctionFromToken(this.MetadataToken);
}
}
internal MethodInfo(DebugType declaringType, MethodProps methodProps):base (declaringType)
{
this.methodProps = methodProps;
}
/// <summary>
/// Get a method from a managed type, method name and argument count
/// </summary>
public static MethodInfo GetFromName(Process process, System.Type type, string name, int paramCount)
{
if (type.IsNested) throw new DebuggerException("Not implemented for nested types");
if (type.IsGenericType) throw new DebuggerException("Not implemented for generic types");
if (type.IsGenericParameter) throw new DebuggerException("Type can not be generic parameter");
foreach(Module module in process.Modules) {
TypeDefProps typeDefProps = module.MetaData.FindTypeDefByName(type.FullName, 0 /* enclosing class for nested */);
foreach(MethodProps methodProps in module.MetaData.EnumMethodsWithName(typeDefProps.Token, name)) {
if (module.MetaData.GetParamCount(methodProps.Token) == paramCount) {
ICorDebugFunction corFunction = module.CorModule.GetFunctionFromToken(methodProps.Token);
ICorDebugClass2 corClass = corFunction.Class.As<ICorDebugClass2>();
ICorDebugType corType = corClass.GetParameterizedType(type.IsValueType ? (uint)CorElementType.VALUETYPE : (uint)CorElementType.CLASS,
0,
new ICorDebugType[] {});
return new MethodInfo(DebugType.Create(process, corType), methodProps);
}
}
}
throw new DebuggerException("Not found");
}
/// <summary>
/// Synchronously invoke the method of an a given object
/// </summary>
public Value Invoke(Value objectInstance, Value[] arguments)
{
return Eval.InvokeMethod(
this,
this.IsStatic ? null : objectInstance,
arguments ?? new Value[0]
);
}
/// <summary>
/// Asynchronously invoke the method of an a given object
/// </summary>
public Eval AsyncInvoke(Value objectInstance, Value[] arguments)
{
return Eval.AsyncInvokeMethod(
this,
this.IsStatic ? null : objectInstance,
arguments ?? new Value[0]
);
}
}
}

120
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/PropertyInfo.cs

@ -0,0 +1,120 @@ @@ -0,0 +1,120 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision: 2023 $</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
using Debugger.Wrappers.MetaData;
namespace Debugger
{
/// <summary>
/// Provides information about a property in a class
/// </summary>
public class PropertyInfo: MemberInfo
{
MethodInfo getMethod;
MethodInfo setMethod;
/// <summary> Gets a value indicating whether this property is private </summary>
public override bool IsPrivate {
get {
return !(getMethod ?? setMethod).IsPublic;
}
}
/// <summary> Gets a value indicating whether this property is public </summary>
public override bool IsPublic {
get {
return (getMethod ?? setMethod).IsPublic;
}
}
/// <summary> Gets a value indicating whether this property is static </summary>
public override bool IsStatic {
get {
return (getMethod ?? setMethod).IsStatic;
}
}
/// <summary> Gets the metadata token associated with getter (or setter)
/// of this property </summary>
public override uint MetadataToken {
get {
return (getMethod ?? setMethod).MetadataToken;
}
}
/// <summary> Gets the name of this property </summary>
public override string Name {
get {
return (getMethod ?? setMethod).Name.Remove(0,4);
}
}
internal PropertyInfo(DebugType declaringType, MethodInfo getMethod, MethodInfo setMethod): base(declaringType)
{
if (getMethod == null && setMethod == null) throw new ArgumentNullException("Both getter and setter can not be null.");
this.getMethod = getMethod;
this.setMethod = setMethod;
}
/// <summary> Get the get accessor of the property </summary>
public MethodInfo GetGetMethod()
{
return getMethod;
}
/// <summary> Get the set accessor of the property </summary>
public MethodInfo GetSetMethod()
{
return setMethod;
}
/// <summary> Get the value of the property using the get accessor </summary>
public MemberValue GetValue(Value objectInstance)
{
return GetValue(objectInstance, null);
}
/// <summary> Get the value of indexer property </summary>
public MemberValue GetValue(Value objectInstance, Value[] parameters)
{
if (getMethod == null) throw new CannotGetValueException("Property does not have a get method");
Value returnedValue = getMethod.Invoke(objectInstance, parameters ?? new Value[0]);
return new MemberValue(
this,
this.Process,
new IExpirable[] {returnedValue},
new IMutable[] {returnedValue},
delegate { return returnedValue.CorValue; }
);
}
/// <summary> Set the value of the property using the set accessor </summary>
public Value SetValue(Value objectInstance, Value newValue)
{
return SetValue(objectInstance, newValue, null);
}
/// <summary> Set the value of indexer property </summary>
public Value SetValue(Value objectInstance, Value newValue, Value[] parameters)
{
if (setMethod == null) throw new CannotGetValueException("Property does not have a set method");
parameters = parameters ?? new Value[0];
Value[] allParams = new Value[1 + parameters.Length];
allParams[0] = newValue;
parameters.CopyTo(allParams, 1);
return setMethod.Invoke(objectInstance, allParams);
}
}
}

38
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/UnavailableValue.cs

@ -1,38 +0,0 @@ @@ -1,38 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
namespace Debugger
{
public class UnavailableValue: ValueProxy
{
string message;
public override string AsString {
get {
return message;
}
}
public override string Type {
get {
return String.Empty;
}
}
internal UnavailableValue(Value @value, string message):base(@value)
{
this.message = message;
}
protected override bool GetMayHaveSubVariables()
{
return false;
}
}
}

446
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Value.cs

@ -1,446 +0,0 @@ @@ -1,446 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
/// <summary>
/// Delegate that is used to get value. This delegate may be called at any time and should never return null.
/// </summary>
delegate ICorDebugValue CorValueGetter();
/// <summary>
/// Value is a container which holds data necessaty to obtain
/// the value of a given object even after continue. This level of
/// abstraction is necessary because the type of a value can change
/// (eg for local variable of type object)
///
/// Expiration: Once value expires it can not be used anymore.
/// Expiration is permanet - once value expires it stays expired.
/// Value expires when any object specified in constructor expires
/// or when process exits.
///
/// Mutation: As long as any dependecy does not mutate the last
/// obteined value is still considered up to date. (If continue is
/// called and internal value is neutred new copy will be obatined)
/// </summary>
public class Value: IExpirable, IMutable
{
protected Process process;
CorValueGetter corValueGetter;
IMutable[] mutateDependencies;
protected ValueProxy currentValue;
protected ICorDebugValue currentCorValue;
protected PauseSession currentCorValuePauseSession;
bool isExpired = false;
public event EventHandler Expired;
public event EventHandler<ProcessEventArgs> Changed;
public Process Process {
get {
return process;
}
}
public ICorDebugValue CorValue {
get {
return DereferenceUnbox(RawCorValue);
}
}
internal CorElementType CorType {
get {
return GetCorType(this.CorValue);
}
}
internal static CorElementType GetCorType(ICorDebugValue corValue)
{
if (corValue == null) {
return (CorElementType)0;
}
return (CorElementType)corValue.Type;
}
protected virtual ICorDebugValue RawCorValue {
get {
if (this.HasExpired) throw new CannotGetValueException("CorValue has expired");
if (currentCorValue == null || (currentCorValuePauseSession != process.PauseSession && !currentCorValue.Is<ICorDebugHandleValue>())) {
currentCorValue = corValueGetter();
currentCorValuePauseSession = process.PauseSession;
}
return currentCorValue;
}
}
public ValueProxy ValueProxy {
get {
if (currentValue == null) {
try {
currentValue = CreateValue();
} catch (CannotGetValueException e) {
currentValue = new UnavailableValue(this, e.Message);
}
}
return currentValue;
}
}
public bool HasExpired {
get {
return isExpired;
}
}
public ICorDebugValue SoftReference {
get {
if (this.HasExpired) throw new DebuggerException("CorValue has expired");
ICorDebugValue corValue = RawCorValue;
if (corValue != null && corValue.Is<ICorDebugHandleValue>()) {
return corValue;
}
corValue = DereferenceUnbox(corValue);
if (corValue != null && corValue.Is<ICorDebugHeapValue2>()) {
return corValue.As<ICorDebugHeapValue2>().CreateHandle(CorDebugHandleType.HANDLE_WEAK_TRACK_RESURRECTION).CastTo<ICorDebugValue>();
} else {
return corValue; // Value type - return value type
}
}
}
internal Value(Process process,
IExpirable[] expireDependencies,
IMutable[] mutateDependencies,
CorValueGetter corValueGetter)
{
this.process = process;
foreach(IExpirable exp in expireDependencies) {
AddExpireDependency(exp);
}
AddExpireDependency(process);
this.mutateDependencies = mutateDependencies;
if (!this.HasExpired) {
foreach(IMutable mut in mutateDependencies) {
AddMutateDependency(mut);
}
}
this.corValueGetter = corValueGetter;
}
void AddExpireDependency(IExpirable dependency)
{
if (dependency.HasExpired) {
MakeExpired();
} else {
dependency.Expired += delegate { MakeExpired(); };
}
}
void AddMutateDependency(IMutable dependency)
{
dependency.Changed += DependencyChanged;
}
void MakeExpired()
{
if (!isExpired) {
isExpired = true;
OnExpired(new ValueEventArgs(this));
foreach(IMutable mut in mutateDependencies) {
mut.Changed -= DependencyChanged;
}
}
}
void DependencyChanged(object sender, ProcessEventArgs e)
{
NotifyChange();
}
protected virtual void ClearCurrentValue()
{
currentValue = null;
currentCorValue = null;
currentCorValuePauseSession = null;
}
internal void NotifyChange()
{
ClearCurrentValue();
if (!isExpired) {
OnChanged(new ValueEventArgs(this));
}
}
protected virtual void OnChanged(ProcessEventArgs e)
{
if (Changed != null) {
Changed(this, e);
}
}
protected virtual void OnExpired(EventArgs e)
{
if (Expired != null) {
Expired(this, e);
}
}
internal static ICorDebugValue DereferenceUnbox(ICorDebugValue corValue)
{
// Method arguments can be passed 'by ref'
if (corValue.Type == (uint)CorElementType.BYREF) {
corValue = corValue.CastTo<ICorDebugReferenceValue>().Dereference();
}
// Pointers may be used in 'unsafe' code - CorElementType.PTR
// Classes need to be dereferenced
while (corValue.Is<ICorDebugReferenceValue>()) {
ICorDebugReferenceValue refValue = corValue.CastTo<ICorDebugReferenceValue>();
if (refValue.IsNull != 0) {
return null; // Reference is null
} else {
try {
corValue = refValue.Dereference();
// TODO: Investigate: Must not acutally be null
// eg. Assembly.AssemblyHandle See SD2-1117
if (corValue == null) return null; // Dereference() returned null
} catch {
return null; // Error during dereferencing
}
}
}
// Unbox value types
if (corValue.Is<ICorDebugBoxValue>()) {
corValue = corValue.CastTo<ICorDebugBoxValue>().Object.CastTo<ICorDebugValue>();
}
return corValue;
}
public enum ValueType {Null, Primitive, Array, Object, Unknown};
ValueType GetValueType()
{
ICorDebugValue corValue = this.CorValue;
if (corValue == null) {
return ValueType.Null;
}
switch(GetCorType(corValue)) {
case CorElementType.BOOLEAN:
case CorElementType.CHAR:
case CorElementType.I1:
case CorElementType.U1:
case CorElementType.I2:
case CorElementType.U2:
case CorElementType.I4:
case CorElementType.U4:
case CorElementType.I8:
case CorElementType.U8:
case CorElementType.R4:
case CorElementType.R8:
case CorElementType.I:
case CorElementType.U:
case CorElementType.STRING:
return ValueType.Primitive;
case CorElementType.ARRAY:
case CorElementType.SZARRAY: // Short-cut for single dimension zero lower bound array
return ValueType.Array;
case CorElementType.VALUETYPE:
case CorElementType.CLASS:
case CorElementType.OBJECT: // Short-cut for Class "System.Object"
return ValueType.Object;
default: // Unknown type
return ValueType.Unknown;
}
}
ValueProxy CreateValue()
{
ICorDebugValue corValue = this.CorValue;
switch(GetValueType()) {
case ValueType.Null: return new NullValue(this);
case ValueType.Primitive: return new PrimitiveValue(this);
case ValueType.Array: return new ArrayValue(this);
case ValueType.Object: return new ObjectValue(this);
default: throw new CannotGetValueException("Unknown value type");
}
}
public bool SetValue(Value newValue)
{
ICorDebugValue corValue = this.RawCorValue;
ICorDebugValue newCorValue = newValue.RawCorValue;
if (newCorValue.Type == (uint)CorElementType.BYREF) {
newCorValue = newCorValue.As<ICorDebugReferenceValue>().Dereference();
}
if (corValue.Is<ICorDebugReferenceValue>()) {
if (newCorValue.Is<ICorDebugObjectValue>()) {
ICorDebugClass corClass = newCorValue.As<ICorDebugObjectValue>().Class;
ICorDebugValue box = Eval.NewObject(process, corClass).RawCorValue;
newCorValue = box;
}
corValue.CastTo<ICorDebugReferenceValue>().SetValue(newCorValue.CastTo<ICorDebugReferenceValue>().Value);
return true;
} else {
return false;
}
}
/// <summary>
/// Returns true if the value is signed or unsigned integer of any size
/// </summary>
public bool IsInteger {
get {
CorElementType corType = CorType;
return corType == CorElementType.I1 ||
corType == CorElementType.U1 ||
corType == CorElementType.I2 ||
corType == CorElementType.U2 ||
corType == CorElementType.I4 ||
corType == CorElementType.U4 ||
corType == CorElementType.I8 ||
corType == CorElementType.U8 ||
corType == CorElementType.I ||
corType == CorElementType.U;
}
}
public VariableCollection GetDebugInfo()
{
return GetDebugInfo(this.RawCorValue);
}
public static VariableCollection GetDebugInfo(ICorDebugValue corValue)
{
List<VariableCollection> items = new List<VariableCollection>();
if (corValue.Is<ICorDebugValue>()) {
List<VariableCollection> more = new List<VariableCollection>();
more.Add(new VariableCollection("type", ((CorElementType)corValue.Type).ToString()));
more.Add(new VariableCollection("size", corValue.Size.ToString()));
more.Add(new VariableCollection("address", corValue.Address.ToString("X")));
items.Add(new VariableCollection("ICorDebugValue", "", more, null));
}
if (corValue.Is<ICorDebugValue2>()) items.Add(new VariableCollection("ICorDebugValue2", "", null, null));
if (corValue.Is<ICorDebugGenericValue>()) {
List<VariableCollection> more = new List<VariableCollection>();
try {
byte[] bytes = corValue.CastTo<ICorDebugGenericValue>().RawValue;
for(int i = 0; i < bytes.Length; i += 8) {
string val = "";
for(int j = i; j < bytes.Length && j < i + 8; j++) {
val += bytes[j].ToString("X2") + " ";
}
more.Add(new VariableCollection("data" + i.ToString("X2"), val));
}
} catch (ArgumentException) {
more.Add(new VariableCollection("data", "N/A"));
}
items.Add(new VariableCollection("ICorDebugGenericValue", "", more, null));
}
if (corValue.Is<ICorDebugReferenceValue>()) {
List<VariableCollection> more = new List<VariableCollection>();
ICorDebugReferenceValue refValue = corValue.CastTo<ICorDebugReferenceValue>();
bool isNull = refValue.IsNull != 0;
more.Add(new VariableCollection("isNull", isNull.ToString()));
if (!isNull) {
more.Add(new VariableCollection("address", refValue.Value.ToString("X")));
if (refValue.Dereference() != null) {
VariableCollection deRef = GetDebugInfo(refValue.Dereference());
more.Add(new VariableCollection("dereferenced", deRef.Value, deRef.SubCollections, deRef.Items));
} else {
more.Add(new VariableCollection("dereferenced", "N/A", null, null));
}
}
items.Add(new VariableCollection("ICorDebugReferenceValue", "", more, null));
}
if (corValue.Is<ICorDebugHeapValue>()) items.Add(new VariableCollection("ICorDebugHeapValue", "", null, null));
if (corValue.Is<ICorDebugHeapValue2>()) items.Add(new VariableCollection("ICorDebugHeapValue2", "", null, null));
if (corValue.Is<ICorDebugObjectValue>()) {
List<VariableCollection> more = new List<VariableCollection>();
bool isValue = corValue.CastTo<ICorDebugObjectValue>().IsValueClass != 0;
more.Add(new VariableCollection("isValue", isValue.ToString()));
items.Add(new VariableCollection("ICorDebugObjectValue", "", more, null));
}
if (corValue.Is<ICorDebugObjectValue2>()) items.Add(new VariableCollection("ICorDebugObjectValue2", "", null, null));
if (corValue.Is<ICorDebugBoxValue>()) {
List<VariableCollection> more = new List<VariableCollection>();
VariableCollection unboxed = GetDebugInfo(corValue.CastTo<ICorDebugBoxValue>().Object.CastTo<ICorDebugValue>());
more.Add(new VariableCollection("unboxed", unboxed.Value, unboxed.SubCollections, unboxed.Items));
items.Add(new VariableCollection("ICorDebugBoxValue", "", more, null));
}
if (corValue.Is<ICorDebugStringValue>()) items.Add(new VariableCollection("ICorDebugStringValue", "", null, null));
if (corValue.Is<ICorDebugArrayValue>()) items.Add(new VariableCollection("ICorDebugArrayValue", "", null, null));
if (corValue.Is<ICorDebugHandleValue>()) items.Add(new VariableCollection("ICorDebugHandleValue", "", null, null));
return new VariableCollection("$debugInfo", ((CorElementType)corValue.Type).ToString(), items.ToArray(), null);
}
internal static System.Type CorTypeToManagedType(CorElementType corType)
{
switch(corType)
{
case CorElementType.BOOLEAN: return typeof(System.Boolean);
case CorElementType.CHAR: return typeof(System.Char);
case CorElementType.I1: return typeof(System.SByte);
case CorElementType.U1: return typeof(System.Byte);
case CorElementType.I2: return typeof(System.Int16);
case CorElementType.U2: return typeof(System.UInt16);
case CorElementType.I4: return typeof(System.Int32);
case CorElementType.U4: return typeof(System.UInt32);
case CorElementType.I8: return typeof(System.Int64);
case CorElementType.U8: return typeof(System.UInt64);
case CorElementType.R4: return typeof(System.Single);
case CorElementType.R8: return typeof(System.Double);
case CorElementType.I: return typeof(int);
case CorElementType.U: return typeof(uint);
case CorElementType.SZARRAY:
case CorElementType.ARRAY: return typeof(System.Array);
case CorElementType.OBJECT: return typeof(System.Object);
case CorElementType.STRING: return typeof(System.String);
default: return null;
}
}
internal static string CorTypeToString(CorElementType corType)
{
Type manType = CorTypeToManagedType(corType);
if (manType == null) return "<unknown>";
return manType.ToString();
}
}
class CannotGetValueException: System.Exception
{
public CannotGetValueException(string message):base(message)
{
}
}
}

93
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ValueProxy.cs

@ -1,93 +0,0 @@ @@ -1,93 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
/// <summary>
/// Provides more specific access
/// </summary>
public abstract class ValueProxy: RemotingObjectBase
{
Value val;
public Value TheValue {
get {
return val;
}
}
public abstract string AsString {
get;
}
public virtual string Type {
get{
return Value.CorTypeToString(TheValue.CorType);
}
}
public virtual Type ManagedType {
get {
return Value.CorTypeToManagedType(TheValue.CorType);
}
}
public bool MayHaveSubVariables {
get {
#if DEBUG
return true;
#else
return GetMayHaveSubVariables();
#endif
}
}
protected abstract bool GetMayHaveSubVariables();
public VariableCollection SubVariables {
get {
VariableCollection subVars = GetSubVariables();
#if DEBUG
return new VariableCollection(subVars.Name,
subVars.Value,
Util.MergeLists(val.GetDebugInfo(), subVars.SubCollections).ToArray(),
subVars.Items);
#else
return subVars;
#endif
}
}
protected virtual VariableCollection GetSubVariables()
{
return new VariableCollection(new Variable[] {});
}
public Variable this[string variableName] {
get {
foreach(Variable v in SubVariables) {
if (v.Name == variableName) return v;
}
throw new DebuggerException("Subvariable " + variableName + " does not exist");
}
}
protected ValueProxy(Value @value)
{
if (@value == null) throw new ArgumentNullException("value");
this.val = @value;
}
public override string ToString()
{
return AsString;
}
}
}

51
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/NamedValue.cs

@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision: 2022 $</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
/// <summary>
/// NamedValue is a Value which has some name associated with it -
/// eg the name of the field that holds the value.
/// </summary>
public class NamedValue: Value
{
string name;
/// <summary> Gets the name associated with the value </summary>
public string Name {
get {
return name;
}
}
internal NamedValue(string name,
Process process,
IExpirable[] expireDependencies,
IMutable[] mutateDependencies,
CorValueGetter corValueGetter)
:base (process,
expireDependencies,
mutateDependencies,
corValueGetter)
{
this.name = name;
// TODO: clean up
if (name.StartsWith("<") && name.Contains(">") && name != "<Base class>") {
string middle = name.TrimStart('<').Split('>')[0]; // Get text between '<' and '>'
if (middle != "") {
this.name = middle;
}
}
}
}
}

71
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/NamedValueCollection.cs

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections;
using System.Collections.Generic;
namespace Debugger
{
/// <summary>
/// An enumerable collection of values accessible by name.
/// </summary>
public class NamedValueCollection: RemotingObjectBase, IEnumerable<NamedValue>, IEnumerable
{
internal static NamedValueCollection Empty = new NamedValueCollection(new NamedValue[0]);
Dictionary<string, List<NamedValue>> collection = new Dictionary<string, List<NamedValue>>();
IEnumerator<NamedValue> IEnumerable<NamedValue>.GetEnumerator()
{
foreach(KeyValuePair<string, List<NamedValue>> kvp in collection) {
foreach(NamedValue namedValue in kvp.Value) {
yield return namedValue;
}
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable<NamedValue>)this).GetEnumerator();
}
internal NamedValueCollection(IEnumerable<NamedValue> namedValues)
{
foreach(NamedValue namedValue in namedValues) {
string name = namedValue.Name;
if (collection.ContainsKey(name)) {
collection[name].Add(namedValue);
} else {
collection[name] = new List<NamedValue>(new NamedValue[] {namedValue});
}
}
}
/// <summary>
/// Gets a value by its name.
/// </summary>
public virtual NamedValue this[string variableName] {
get {
if (collection.ContainsKey(variableName)) {
foreach(NamedValue namedValue in collection[variableName]) {
return namedValue;
}
}
// int index = variableName.IndexOf('.');
// if (index != -1) {
// string rootVariable = variableName.Substring(0, index);
// string subVariable = variableName.Substring(index + 1);
// return this[rootVariable].Value.SubVariables[subVariable];
// }
throw new DebuggerException("Variable \"" + variableName + "\" is not in collection");
}
}
}
}

131
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value-Array.cs

@ -0,0 +1,131 @@ @@ -0,0 +1,131 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
//TODO: Support for lower bound
namespace Debugger
{
// This part of the class provides support for arrays
public partial class Value
{
ICorDebugArrayValue CorArrayValue {
get {
if (IsArray) {
return CorValue.CastTo<ICorDebugArrayValue>();
} else {
throw new DebuggerException("Value is not an array");
}
}
}
/// <summary> Returns true if the value is an array </summary>
public bool IsArray {
get {
return !IsNull && this.Type.IsArray;
}
}
/// <summary>
/// Gets the number of elements the array can store.
/// eg new object[4,5] returns 20
/// </summary>
public uint ArrayLenght {
get {
return CorArrayValue.Count;
}
}
/// <summary>
/// Gets the number of dimensions of the array.
/// eg new object[4,5] returns 2
/// </summary>
public uint ArrayRank {
get {
return CorArrayValue.Rank;
}
}
/// <summary>
/// Gets the lengths of individual dimensions.
/// eg new object[4,5] returns {4,5};
/// </summary>
public uint[] ArrayDimensions {
get {
return CorArrayValue.Dimensions;
}
}
/// <summary> Returns an element of a single-dimensional array </summary>
public ArrayElement GetArrayElement(uint index)
{
return GetArrayElement(new uint[] {index});
}
/// <summary> Returns an element of an array </summary>
public ArrayElement GetArrayElement(uint[] elementIndices)
{
uint[] indices = (uint[])elementIndices.Clone();
return new ArrayElement(
indices,
Process,
new IExpirable[] {this},
new IMutable[] {this},
delegate { return GetCorValueOfArrayElement(indices); }
);
}
// May be called later
ICorDebugValue GetCorValueOfArrayElement(uint[] indices)
{
if (!IsArray) {
throw new CannotGetValueException("The value is not an array");
}
if (indices.Length != ArrayRank) {
throw new CannotGetValueException("Given indicies do not have the same dimension as array.");
}
for (int i = 0; i < indices.Length; i++) {
if (indices[i] > ArrayDimensions[i]) {
throw new CannotGetValueException("Given indices are out of range of the array");
}
}
return CorArrayValue.GetElement(indices);
}
/// <summary> Returns all elements in the array </summary>
public NamedValueCollection GetArrayElements()
{
return new NamedValueCollection(GetArrayElementsEnum());
}
IEnumerable<NamedValue> GetArrayElementsEnum()
{
uint[] indices = new uint[ArrayRank];
uint rank = ArrayRank;
uint[] dimensions = ArrayDimensions;
while(true) { // Go thought all combinations
for (uint i = rank - 1; i >= 1; i--) {
if (indices[i] >= dimensions[i]) {
indices[i] = 0;
indices[i-1]++;
}
}
if (indices[0] >= dimensions[0]) break; // We are done
yield return GetArrayElement(indices);
indices[rank - 1]++;
}
}
}
}

72
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value-Common.cs

@ -0,0 +1,72 @@ @@ -0,0 +1,72 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
/// <summary>
/// Provides more specific access
/// </summary>
public partial class Value
{
/// <summary> Returns true if the value is null </summary>
public bool IsNull {
get {
return CorValue == null;
}
}
/// <summary> Gets a string representation of the value </summary>
public string AsString {
get {
if (IsNull) return "<null reference>";
if (IsArray) return "{" + this.Type.Name + "}";
if (IsObject) return "{" + this.Type.Name + "}";
if (IsPrimitive) return PrimitiveValue != null ? PrimitiveValue.ToString() : String.Empty;
throw new DebuggerException("Unknown value type");
}
}
// public bool MayHaveSubVariables {
// get {
// #if DEBUG
// if (IsNull) return true;
// if (IsArray) return true;
// if (IsObject) return true;
// if (IsPrimitive) return true;
// #else
// if (IsNull) return false;
// if (IsArray) return true;
// if (IsObject) return true;
// if (IsPrimitive) return false;
// #endif
// throw new DebuggerException("Unknown value type");
// }
// }
//
// public VariableCollection SubVariables {
// get {
// VariableCollection subVars = null;
// if (IsNull) subVars = new VariableCollection(new Variable[] {});
// if (IsArray) subVars = new VariableCollection(GetArrayElements());
// if (IsObject) subVars = this.ObjectSubVariables;
// if (IsPrimitive) subVars = new VariableCollection(new Variable[] {});
// if (subVars == null) throw new DebuggerException("Unknown value type");
// #if DEBUG
// return new VariableCollection(subVars.Name,
// subVars.Value,
// Util.MergeLists(this.GetDebugInfo(), subVars.SubCollections).ToArray(),
// subVars.Items);
// #else
// return subVars;
// #endif
// }
// }
}
}

124
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value-Helpers.cs

@ -0,0 +1,124 @@ @@ -0,0 +1,124 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision: 2022 $</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
public partial class Value
{
internal static ICorDebugValue DereferenceUnbox(ICorDebugValue corValue)
{
// Method arguments can be passed 'by ref'
if (corValue.Type == (uint)CorElementType.BYREF) {
corValue = corValue.CastTo<ICorDebugReferenceValue>().Dereference();
}
// Pointers may be used in 'unsafe' code - CorElementType.PTR
// Classes need to be dereferenced
while (corValue.Is<ICorDebugReferenceValue>()) {
ICorDebugReferenceValue refValue = corValue.CastTo<ICorDebugReferenceValue>();
if (refValue.IsNull != 0) {
return null; // Reference is null
} else {
try {
corValue = refValue.Dereference();
// TODO: Investigate: Must not acutally be null
// eg. Assembly.AssemblyHandle See SD2-1117
if (corValue == null) return null; // Dereference() returned null
} catch {
return null; // Error during dereferencing
}
}
}
// Unbox value types
if (corValue.Is<ICorDebugBoxValue>()) {
corValue = corValue.CastTo<ICorDebugBoxValue>().Object.CastTo<ICorDebugValue>();
}
return corValue;
}
/*
internal VariableCollection GetDebugInfo()
{
return GetDebugInfo(this.RawCorValue);
}
internal static VariableCollection GetDebugInfo(ICorDebugValue corValue)
{
List<VariableCollection> items = new List<VariableCollection>();
if (corValue.Is<ICorDebugValue>()) {
List<VariableCollection> more = new List<VariableCollection>();
more.Add(new VariableCollection("type", ((CorElementType)corValue.Type).ToString()));
more.Add(new VariableCollection("size", corValue.Size.ToString()));
more.Add(new VariableCollection("address", corValue.Address.ToString("X")));
items.Add(new VariableCollection("ICorDebugValue", "", more, null));
}
if (corValue.Is<ICorDebugValue2>()) items.Add(new VariableCollection("ICorDebugValue2", "", null, null));
if (corValue.Is<ICorDebugGenericValue>()) {
List<VariableCollection> more = new List<VariableCollection>();
try {
byte[] bytes = corValue.CastTo<ICorDebugGenericValue>().RawValue;
for(int i = 0; i < bytes.Length; i += 8) {
string val = "";
for(int j = i; j < bytes.Length && j < i + 8; j++) {
val += bytes[j].ToString("X2") + " ";
}
more.Add(new VariableCollection("data" + i.ToString("X2"), val));
}
} catch (ArgumentException) {
more.Add(new VariableCollection("data", "N/A"));
}
items.Add(new VariableCollection("ICorDebugGenericValue", "", more, null));
}
if (corValue.Is<ICorDebugReferenceValue>()) {
List<VariableCollection> more = new List<VariableCollection>();
ICorDebugReferenceValue refValue = corValue.CastTo<ICorDebugReferenceValue>();
bool isNull = refValue.IsNull != 0;
more.Add(new VariableCollection("isNull", isNull.ToString()));
if (!isNull) {
more.Add(new VariableCollection("address", refValue.Value.ToString("X")));
if (refValue.Dereference() != null) {
VariableCollection deRef = GetDebugInfo(refValue.Dereference());
more.Add(new VariableCollection("dereferenced", deRef.Value, deRef.SubCollections, deRef.Items));
} else {
more.Add(new VariableCollection("dereferenced", "N/A", null, null));
}
}
items.Add(new VariableCollection("ICorDebugReferenceValue", "", more, null));
}
if (corValue.Is<ICorDebugHeapValue>()) items.Add(new VariableCollection("ICorDebugHeapValue", "", null, null));
if (corValue.Is<ICorDebugHeapValue2>()) items.Add(new VariableCollection("ICorDebugHeapValue2", "", null, null));
if (corValue.Is<ICorDebugObjectValue>()) {
List<VariableCollection> more = new List<VariableCollection>();
bool isValue = corValue.CastTo<ICorDebugObjectValue>().IsValueClass != 0;
more.Add(new VariableCollection("isValue", isValue.ToString()));
items.Add(new VariableCollection("ICorDebugObjectValue", "", more, null));
}
if (corValue.Is<ICorDebugObjectValue2>()) items.Add(new VariableCollection("ICorDebugObjectValue2", "", null, null));
if (corValue.Is<ICorDebugBoxValue>()) {
List<VariableCollection> more = new List<VariableCollection>();
VariableCollection unboxed = GetDebugInfo(corValue.CastTo<ICorDebugBoxValue>().Object.CastTo<ICorDebugValue>());
more.Add(new VariableCollection("unboxed", unboxed.Value, unboxed.SubCollections, unboxed.Items));
items.Add(new VariableCollection("ICorDebugBoxValue", "", more, null));
}
if (corValue.Is<ICorDebugStringValue>()) items.Add(new VariableCollection("ICorDebugStringValue", "", null, null));
if (corValue.Is<ICorDebugArrayValue>()) items.Add(new VariableCollection("ICorDebugArrayValue", "", null, null));
if (corValue.Is<ICorDebugHandleValue>()) items.Add(new VariableCollection("ICorDebugHandleValue", "", null, null));
return new VariableCollection("$debugInfo", ((CorElementType)corValue.Type).ToString(), items.ToArray(), null);
}
*/
}
}

130
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value-Object.cs

@ -0,0 +1,130 @@ @@ -0,0 +1,130 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
// This part of the class provides support for classes and structures
public partial class Value
{
internal ICorDebugObjectValue CorObjectValue {
get {
if (IsObject) {
return CorValue.CastTo<ICorDebugObjectValue>();
} else {
throw new DebuggerException("Value is not an object");
}
}
}
/// <summary> Returns true if the value is a class or value type </summary>
public bool IsObject {
get {
return !IsNull && (this.Type.IsClass || this.Type.IsValueType);
}
}
/// <summary> Returns a text which is produced by calling object.ToString() </summary>
public Value ObjectToString {
get {
return Eval.AsyncInvokeMethod(
MethodInfo.GetFromName(Process, typeof(object), "ToString", 0),
this,
null
).Result;
}
}
/// <summary>
/// Get a field or property of an object with a given name.
/// </summary>
public NamedValue GetMember(string name)
{
return GetMembers()[name];
}
/// <summary>
/// Get all fields and properties of an object.
/// </summary>
public NamedValueCollection GetMembers()
{
return GetMembers(null, BindingFlags.All);
}
/// <summary>
/// Get fields and properties of an object which are defined by a given type.
/// </summary>
/// <param name="type"> Limit to type, null for all types </param>
/// <param name="bindingFlags"> Get only members with certain flags </param>
public NamedValueCollection GetMembers(DebugType type, BindingFlags bindingFlags)
{
if (IsObject) {
return new NamedValueCollection(GetObjectMembersEnum(type, bindingFlags));
} else {
return NamedValueCollection.Empty;
}
}
IEnumerable<NamedValue> GetObjectMembersEnum(DebugType type, BindingFlags bindingFlags)
{
DebugType currentType = type ?? this.Type;
while (currentType != null) {
foreach(FieldInfo field in currentType.GetFields(bindingFlags)) {
yield return field.GetValue(this);
}
foreach(PropertyInfo property in currentType.GetProperties(bindingFlags)) {
yield return property.GetValue(this);
}
if (type == null) {
currentType = currentType.BaseType;
} else {
yield break;
}
}
}
// public VariableCollection ObjectSubVariables {
// get {
// return new VariableCollection(String.Empty,
// String.Empty,
// GetSubCollections(this.Type),
// GetSubVariables(this.Type, BindingFlags.Public | BindingFlags.Instance));
// }
// }
// IEnumerable<VariableCollection> GetSubCollections(DebugType type)
// {
// if (type.BaseType != null) {
// yield return new VariableCollection("Base class",
// "{" + type.BaseType.Name + "}",
// GetSubCollections(type.BaseType),
// GetSubVariables(type.BaseType, BindingFlags.Public | BindingFlags.Instance));
// }
// VariableCollection privateStatic = new VariableCollection("Private static members",
// String.Empty,
// new VariableCollection[0],
// GetSubVariables(type, BindingFlags.NonPublic | BindingFlags.Static));
// VariableCollection privateInstance = new VariableCollection("Private members",
// String.Empty,
// privateStatic.IsEmpty ? new VariableCollection[0] : new VariableCollection[] {privateStatic},
// GetSubVariables(type, BindingFlags.NonPublic | BindingFlags.Instance));
// if (!privateInstance.IsEmpty) {
// yield return privateInstance;
// }
// VariableCollection publicStatic = new VariableCollection("Static members",
// String.Empty,
// new VariableCollection[0],
// GetSubVariables(type, BindingFlags.Public | BindingFlags.Static));
// if (!publicStatic.IsEmpty) {
// yield return publicStatic;
// }
// }
}
}

76
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value-Primitive.cs

@ -0,0 +1,76 @@ @@ -0,0 +1,76 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.ComponentModel;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
// This part of the class provides support for primitive types
// eg int, bool, string
public partial class Value
{
ICorDebugGenericValue CorGenericValue {
get {
if (IsPrimitive) {
return CorValue.CastTo<ICorDebugGenericValue>();
} else {
throw new DebuggerException("Value is not a primitive type");
}
}
}
/// <summary>
/// Returns true if the value is an primitive type.
/// eg int, bool, string
/// </summary>
public bool IsPrimitive {
get {
return !IsNull && this.Type.IsPrimitive;
}
}
/// <summary> Gets a value indicating whether the type is an integer type </summary>
public bool IsInteger {
get {
return !IsNull && this.Type.IsInteger;
}
}
/// <summary>
/// Gets or sets the value of a primitive type.
///
/// If setting of a value fails, NotSupportedException is thrown.
/// </summary>
public object PrimitiveValue {
get {
if (CorType == CorElementType.STRING) {
return (CorValue.CastTo<ICorDebugStringValue>()).String;
} else {
return CorGenericValue.Value;
}
}
set {
object newValue;
TypeConverter converter = TypeDescriptor.GetConverter(this.Type.ManagedType);
try {
newValue = converter.ConvertFrom(value);
} catch {
throw new NotSupportedException("Can not convert " + value.GetType().ToString() + " to " + this.Type.ManagedType.ToString());
}
if (CorType == CorElementType.STRING) {
throw new NotSupportedException();
} else {
CorGenericValue.Value = newValue;
}
NotifyChange();
}
}
}
}

217
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value.cs

@ -0,0 +1,217 @@ @@ -0,0 +1,217 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision: 2022 $</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
/// <summary>
/// Delegate that is used to get value. This delegate may be called at any time and should never return null.
/// </summary>
delegate ICorDebugValue CorValueGetter();
/// <summary>
/// Value class holds data necessaty to obtain the value of a given object
/// even after continue. It provides functions to examine the object.
/// </summary>
/// <remarks>
/// <para>
/// Expiration: Once value expires it can not be used anymore.
/// Expiration is permanet - once value expires it stays expired.
/// Value expires when any object specified in constructor expires
/// or when process exits.
/// </para>
/// <para>
/// Mutation: As long as any dependecy does not mutate the last
/// obteined value is still considered up to date. (If continue is
/// called and internal value is neutred, new copy will be obatined)
/// </para>
/// </remarks>
public partial class Value: RemotingObjectBase, IExpirable, IMutable
{
Process process;
CorValueGetter corValueGetter;
ICorDebugValue currentCorValue;
PauseSession currentCorValuePauseSession;
/// <summary> Occurs when the Value can not be used anymore </summary>
public event EventHandler Expired;
/// <summary> Occurs when the Value have potentialy changed </summary>
public event EventHandler<ProcessEventArgs> Changed;
bool isExpired = false;
/// <summary> The process that owns the value </summary>
public Process Process {
get {
return process;
}
}
/// <summary> Returns true if the Value have expired
/// and can not be used anymore </summary>
public bool HasExpired {
get {
return isExpired;
}
}
internal ICorDebugValue CorValue {
get {
return DereferenceUnbox(RawCorValue);
}
}
internal CorElementType CorType {
get {
ICorDebugValue corValue = this.CorValue;
if (corValue == null) {
return (CorElementType)0;
}
return (CorElementType)corValue.Type;
}
}
ICorDebugValue RawCorValue {
get {
if (this.HasExpired) throw new CannotGetValueException("CorValue has expired");
if (currentCorValue == null || (currentCorValuePauseSession != process.PauseSession && !currentCorValue.Is<ICorDebugHandleValue>())) {
currentCorValue = corValueGetter();
currentCorValuePauseSession = process.PauseSession;
}
return currentCorValue;
}
}
internal ICorDebugValue SoftReference {
get {
if (this.HasExpired) throw new DebuggerException("CorValue has expired");
ICorDebugValue corValue = RawCorValue;
if (corValue != null && corValue.Is<ICorDebugHandleValue>()) {
return corValue;
}
corValue = DereferenceUnbox(corValue);
if (corValue != null && corValue.Is<ICorDebugHeapValue2>()) {
return corValue.As<ICorDebugHeapValue2>().CreateHandle(CorDebugHandleType.HANDLE_WEAK_TRACK_RESURRECTION).CastTo<ICorDebugValue>();
} else {
return corValue; // Value type - return value type
}
}
}
internal Value(Process process,
IExpirable[] expireDependencies,
IMutable[] mutateDependencies,
CorValueGetter corValueGetter)
{
this.process = process;
AddExpireDependency(process);
foreach(IExpirable exp in expireDependencies) {
AddExpireDependency(exp);
}
foreach(IMutable mut in mutateDependencies) {
AddMutateDependency(mut);
}
this.corValueGetter = corValueGetter;
}
void AddExpireDependency(IExpirable dependency)
{
if (dependency.HasExpired) {
MakeExpired();
} else {
dependency.Expired += delegate { MakeExpired(); };
}
}
void MakeExpired()
{
if (!isExpired) {
isExpired = true;
OnExpired(new ValueEventArgs(this));
}
}
void AddMutateDependency(IMutable dependency)
{
dependency.Changed += delegate { NotifyChange(); };
}
internal void NotifyChange()
{
if (!isExpired) {
currentCorValue = null;
currentCorValuePauseSession = null;
OnChanged(new ValueEventArgs(this));
}
}
/// <summary> Is called when the value changes </summary>
protected virtual void OnChanged(ProcessEventArgs e)
{
if (Changed != null) {
Changed(this, e);
}
}
/// <summary> Is called when the value expires and can not be
/// used anymore </summary>
protected virtual void OnExpired(EventArgs e)
{
if (Expired != null) {
Expired(this, e);
}
}
/// <summary> Returns the <see cref="Debugger.DebugType"/> of the value </summary>
public DebugType Type {
get {
return DebugType.Create(process, RawCorValue.As<ICorDebugValue2>().ExactType);
}
}
/// <summary> Copy the acutal value from some other Value object </summary>
public bool SetValue(Value newValue)
{
ICorDebugValue corValue = this.RawCorValue;
ICorDebugValue newCorValue = newValue.RawCorValue;
if (newCorValue.Type == (uint)CorElementType.BYREF) {
newCorValue = newCorValue.As<ICorDebugReferenceValue>().Dereference();
}
if (corValue.Is<ICorDebugReferenceValue>()) {
if (newCorValue.Is<ICorDebugObjectValue>()) {
ICorDebugClass corClass = newCorValue.As<ICorDebugObjectValue>().Class;
ICorDebugValue box = Eval.NewObject(process, corClass).RawCorValue;
newCorValue = box;
}
corValue.CastTo<ICorDebugReferenceValue>().SetValue(newCorValue.CastTo<ICorDebugReferenceValue>().Value);
return true;
} else {
return false;
}
}
}
public class CannotGetValueException: DebuggerException
{
public CannotGetValueException(string message):base(message)
{
}
}
}

5
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/ValueEventArgs.cs → src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/ValueEventArgs.cs

@ -9,17 +9,22 @@ using System; @@ -9,17 +9,22 @@ using System;
namespace Debugger
{
/// <summary>
/// Provides data for events related to <see cref="Debugger.Value"/> class
/// </summary>
[Serializable]
public class ValueEventArgs : ProcessEventArgs
{
Value val;
/// <summary> The value that caused the event </summary>
public Value Value {
get {
return val;
}
}
/// <summary> Initializes a new instance of the class </summary>
public ValueEventArgs(Value val): base(val.Process)
{
this.val = val;

91
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variable.cs

@ -1,91 +0,0 @@ @@ -1,91 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
/// <summary>
///
/// </summary>
public class Variable: IExpirable, IMutable
{
string name;
Value val;
bool hasExpired;
public event EventHandler Expired;
public event EventHandler<ProcessEventArgs> Changed;
public Process Process {
get {
return val.Process;
}
}
public string Name {
get {
return name;
}
}
public Value Value {
get {
return val;
}
}
public ValueProxy ValueProxy {
get {
return val.ValueProxy;
}
}
public bool HasExpired {
get {
return hasExpired;
}
}
internal Variable(string name, Value @value)
{
if (@value == null) throw new ArgumentNullException("value");
this.name = name;
this.val = @value;
this.val.Expired += delegate(object sender, EventArgs e) { OnExpired(e); };
this.val.Changed += delegate(object sender, ProcessEventArgs e) { OnChanged(e); };
if (name.StartsWith("<") && name.Contains(">") && name != "<Base class>") {
string middle = name.TrimStart('<').Split('>')[0]; // Get text between '<' and '>'
if (middle != "") {
this.name = middle;
}
}
}
protected virtual void OnExpired(EventArgs e)
{
if (!hasExpired) {
hasExpired = true;
if (Expired != null) {
Expired(this, e);
}
}
}
protected virtual void OnChanged(ProcessEventArgs e)
{
if (Changed != null) {
Changed(this, e);
}
}
}
}

115
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/VariableCollection.cs

@ -1,115 +0,0 @@ @@ -1,115 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections;
using System.Collections.Generic;
namespace Debugger
{
[Serializable]
public class VariableCollection: RemotingObjectBase, IEnumerable<Variable>
{
public static VariableCollection Empty = new VariableCollection(new Variable[] {});
string name;
string val;
IEnumerable<VariableCollection> subCollectionsEnum;
IEnumerable<Variable> collectionEnum;
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerator<Variable> GetEnumerator()
{
return Items.GetEnumerator();
}
public string Name {
get {
return name;
}
}
public string Value {
get {
return val;
}
}
public IEnumerable<VariableCollection> SubCollections {
get {
return subCollectionsEnum;
}
}
public IEnumerable<Variable> Items {
get {
return collectionEnum;
}
}
public bool IsEmpty {
get {
return !SubCollections.GetEnumerator().MoveNext() &&
!Items.GetEnumerator().MoveNext();
}
}
internal VariableCollection(IEnumerable<Variable> collectionEnum)
:this(String.Empty, String.Empty, new VariableCollection[0], collectionEnum)
{
}
public VariableCollection(string name, string val):this(name, val, null, null)
{
}
public VariableCollection(string name, string val, IEnumerable<VariableCollection> subCollectionsEnum, IEnumerable<Variable> collectionEnum)
{
this.name = name;
this.val = val;
if (subCollectionsEnum != null) {
this.subCollectionsEnum = subCollectionsEnum;
} else {
this.subCollectionsEnum = new VariableCollection[0];
}
if (collectionEnum != null) {
this.collectionEnum = collectionEnum;
} else {
this.collectionEnum = new Variable[0];
}
}
public virtual Variable this[string variableName] {
get {
int index = variableName.IndexOf('.');
if (index != -1) {
string rootVariable = variableName.Substring(0, index);
string subVariable = variableName.Substring(index + 1);
return this[rootVariable].ValueProxy.SubVariables[subVariable];
} else {
foreach (Variable v in this) {
if (v.Name == variableName) return v;
}
}
throw new DebuggerException("Variable \"" + variableName + "\" is not in collection");
}
}
public override string ToString() {
string txt = "";
foreach(Variable v in this) {
txt += v.ToString() + "\n";
}
return txt;
}
}
}

27
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/VariableEventArgs.cs

@ -1,27 +0,0 @@ @@ -1,27 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
namespace Debugger
{
public class VariableEventArgs: ProcessEventArgs
{
Variable variable;
public Variable Variable {
get {
return variable;
}
}
public VariableEventArgs(Variable variable): base(variable.Value.Process)
{
this.variable = variable;
}
}
}

56
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variables/ArrayElement.cs

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
/// <summary>
/// Represents an element of an array
/// </summary>
public class ArrayElement: NamedValue
{
uint[] indicies;
/// <summary>
/// The indicies of the element; one for each dimension of
/// the array.
/// </summary>
public uint[] Indicies {
get {
return indicies;
}
}
internal ArrayElement(uint[] indicies,
Process process,
IExpirable[] expireDependencies,
IMutable[] mutateDependencies,
CorValueGetter corValueGetter)
:base (GetNameFromIndices(indicies),
process,
expireDependencies,
mutateDependencies,
corValueGetter)
{
this.indicies = indicies;
}
static string GetNameFromIndices(uint[] indices)
{
string elementName = "[";
for (int i = 0; i < indices.Length; i++) {
elementName += indices[i].ToString() + ",";
}
elementName = elementName.TrimEnd(new char[] {','}) + "]";
return elementName;
}
}
}

34
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variables/LocalVariable.cs

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
/// <summary>
/// Represents a local variable in a function
/// </summary>
public class LocalVariable: NamedValue
{
internal LocalVariable(string name,
Process process,
IExpirable[] expireDependencies,
IMutable[] mutateDependencies,
CorValueGetter corValueGetter)
:base (name,
process,
expireDependencies,
mutateDependencies,
corValueGetter)
{
}
}
}

47
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variables/MemberVariable.cs

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision: 2022 $</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
/// <summary>
/// Represents a member of class or value type -
/// that is, a field or a property
/// </summary>
public class MemberValue: NamedValue
{
MemberInfo memberInfo;
/// <summary>
/// Gets an MemberInfo object which can be used to obtain
/// metadata information about the member.
/// </summary>
public MemberInfo MemberInfo {
get {
return memberInfo;
}
}
internal MemberValue(MemberInfo memberInfo,
Process process,
IExpirable[] expireDependencies,
IMutable[] mutateDependencies,
CorValueGetter corValueGetter)
:base (memberInfo.Name,
process,
expireDependencies,
mutateDependencies,
corValueGetter)
{
this.memberInfo = memberInfo;
}
}
}

50
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variables/MethodArgument.cs

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
/// <summary>
/// Represents an argument of a function. That is, it refers to
/// the runtime value of function parameter.
/// </summary>
public class MethodArgument: NamedValue
{
int index;
/// <summary>
/// The index of the function parameter starting at 0.
/// </summary>
/// <remarks>
/// The implicit 'this' is excluded.
/// </remarks>
public int Index {
get {
return index;
}
}
internal MethodArgument(string name,
int index,
Process process,
IExpirable[] expireDependencies,
IMutable[] mutateDependencies,
CorValueGetter corValueGetter)
:base (name,
process,
expireDependencies,
mutateDependencies,
corValueGetter)
{
this.index = index;
}
}
}

10
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/LocalVariable.cs → src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variables/Variable.cs

@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// <version>$Revision: 2022 $</version>
// </file>
using System;
@ -12,11 +12,5 @@ using Debugger.Wrappers.CorDebug; @@ -12,11 +12,5 @@ using Debugger.Wrappers.CorDebug;
namespace Debugger
{
public class LocalVariable: Variable
{
public LocalVariable(string name, Value @value)
:base (name, @value)
{
}
}
}

107
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variables/VariableCollection.cs

@ -0,0 +1,107 @@ @@ -0,0 +1,107 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections;
using System.Collections.Generic;
namespace Debugger
{
// public class NamedValueCollection: RemotingObjectBase, IEnumerable<NamedValue>
// {
// public static NamedValueCollection Empty = new NamedValueCollection(new NamedValue[0]);
//
// string name;
// string val;
// IEnumerable<NamedValueCollection> subCollectionsEnum;
// IEnumerable<NamedValue> collectionEnum;
//
// IEnumerator IEnumerable.GetEnumerator()
// {
// return GetEnumerator();
// }
//
// public IEnumerator<NamedValue> GetEnumerator()
// {
// return Items.GetEnumerator();
// }
//
// public string Name {
// get {
// return name;
// }
// }
//
// public string Value {
// get {
// return val;
// }
// }
//
// public IEnumerable<NamedValueCollection> SubCollections {
// get {
// return subCollectionsEnum;
// }
// }
//
// public IEnumerable<NamedValue> Items {
// get {
// return collectionEnum;
// }
// }
//
// public bool IsEmpty {
// get {
// return !SubCollections.GetEnumerator().MoveNext() &&
// !Items.GetEnumerator().MoveNext();
// }
// }
//
// internal NamedValueCollection(IEnumerable<NamedValue> collectionEnum)
// :this(String.Empty, String.Empty, new VariableCollection[0], collectionEnum)
// {
// }
//
// public NamedValueCollection(string name, string val):this(name, val, null, null)
// {
// }
//
// public NamedValueCollection(string name, string val, IEnumerable<NamedValueCollection> subCollectionsEnum, IEnumerable<NamedValue> collectionEnum)
// {
// this.name = name;
// this.val = val;
// this.subCollectionsEnum = subCollectionsEnum ?? new VariableCollection[0];
// this.collectionEnum = collectionEnum ?? new Variable[0];
// }
//
//
// public virtual NamedValue this[string variableName] {
// get {
// int index = variableName.IndexOf('.');
// if (index != -1) {
// string rootVariable = variableName.Substring(0, index);
// string subVariable = variableName.Substring(index + 1);
// return this[rootVariable].Value.SubVariables[subVariable];
// } else {
// foreach (Variable v in this) {
// if (v.Name == variableName) return v;
// }
// }
// throw new DebuggerException("Variable \"" + variableName + "\" is not in collection");
// }
// }
//
// public override string ToString()
// {
// string txt = "";
// foreach(Variable v in this) {
// txt += v.ToString() + "\n";
// }
// return txt;
// }
// }
}

27
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variables/VariableEventArgs.cs

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
namespace Debugger
{
// public class VariableEventArgs: ProcessEventArgs
// {
// Variable variable;
//
// public Variable Variable {
// get {
// return variable;
// }
// }
//
// public VariableEventArgs(Variable variable): base(variable.Value.Process)
// {
// this.variable = variable;
// }
// }
}

24
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/Autogenerated/ICorDebugClass2.cs

@ -98,13 +98,29 @@ namespace Debugger.Wrappers.CorDebug @@ -98,13 +98,29 @@ namespace Debugger.Wrappers.CorDebug
}
public ICorDebugType GetParameterizedType(uint elementType, uint nTypeArgs, ref ICorDebugType ppTypeArgs)
public ICorDebugType GetParameterizedType(uint elementType, uint nTypeArgs, ICorDebugType[] ppTypeArgs)
{
ICorDebugType ppType;
Debugger.Interop.CorDebug.ICorDebugType ref_ppTypeArgs = ppTypeArgs.WrappedObject;
Debugger.Interop.CorDebug.ICorDebugType[] array_ppTypeArgs = new Debugger.Interop.CorDebug.ICorDebugType[ppTypeArgs.Length];
for (int i = 0; (i < ppTypeArgs.Length); i = (i + 1))
{
if ((ppTypeArgs[i] != null))
{
array_ppTypeArgs[i] = ppTypeArgs[i].WrappedObject;
}
}
Debugger.Interop.CorDebug.ICorDebugType out_ppType;
this.WrappedObject.GetParameterizedType(elementType, nTypeArgs, ref ref_ppTypeArgs, out out_ppType);
ppTypeArgs = ICorDebugType.Wrap(ref_ppTypeArgs);
this.WrappedObject.GetParameterizedType(elementType, nTypeArgs, array_ppTypeArgs, out out_ppType);
for (int i = 0; (i < ppTypeArgs.Length); i = (i + 1))
{
if ((array_ppTypeArgs[i] != null))
{
ppTypeArgs[i] = ICorDebugType.Wrap(array_ppTypeArgs[i]);
} else
{
ppTypeArgs[i] = null;
}
}
ppType = ICorDebugType.Wrap(out_ppType);
return ppType;
}

35
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/ICorDebugArrayValue.cs

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision: 1965 $</version>
// </file>
#pragma warning disable 1591
namespace Debugger.Wrappers.CorDebug
{
using System;
public partial class ICorDebugArrayValue
{
public unsafe uint[] Dimensions {
get {
uint[] dimensions = new uint[this.Rank];
fixed (void* pDimensions = dimensions) {
this.GetDimensions((uint)dimensions.Length, new IntPtr(pDimensions));
}
return dimensions;
}
}
public unsafe ICorDebugValue GetElement(uint[] indices)
{
fixed (void* pIndices = indices) {
return this.GetElement((uint)indices.Length, new IntPtr(pIndices));
}
}
}
}
#pragma warning restore 1591

6
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/FieldProps.cs

@ -5,11 +5,13 @@ @@ -5,11 +5,13 @@
// <version>$Revision$</version>
// </file>
#pragma warning disable 1591
using System;
namespace Debugger.Wrappers.MetaData
{
struct FieldProps
public struct FieldProps
{
public uint Token;
public string Name;
@ -35,3 +37,5 @@ namespace Debugger.Wrappers.MetaData @@ -35,3 +37,5 @@ namespace Debugger.Wrappers.MetaData
}
}
}
#pragma warning restore 1591

24
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/MetaData.cs

@ -5,6 +5,8 @@ @@ -5,6 +5,8 @@
// <version>$Revision$</version>
// </file>
#pragma warning disable 1591
using System;
using System.Collections.Generic;
using Debugger.Interop.MetaData;
@ -13,7 +15,10 @@ using Debugger.Wrappers.CorSym; @@ -13,7 +15,10 @@ using Debugger.Wrappers.CorSym;
namespace Debugger.Wrappers.MetaData
{
class MetaData: IDisposable
/// <summary>
/// Wrapper for the unmanaged metadata API
/// </summary>
public class MetaData: IDisposable
{
IMetaDataImport metaData;
@ -166,10 +171,6 @@ namespace Debugger.Wrappers.MetaData @@ -166,10 +171,6 @@ namespace Debugger.Wrappers.MetaData
out methodProps.ImplFlags);
});
methodProps.Signature = null;
//methodProps.Signature = new SignatureStream(pSigBlob, sigBlobSize);
//Marshal.FreeCoTaskMem(pSigBlob);
return methodProps;
}
@ -229,16 +230,7 @@ namespace Debugger.Wrappers.MetaData @@ -229,16 +230,7 @@ namespace Debugger.Wrappers.MetaData
metaData.FindTypeDefByName(typeName, enclosingClassToken, out typeDefToken);
return GetTypeDefProps(typeDefToken);
}
public MethodProps GetMethod(string type, string name, int paramCount)
{
TypeDefProps typeDefProps = FindTypeDefByName(type, 0);
foreach(MethodProps method in EnumMethodsWithName(typeDefProps.Token, name)) {
if (GetParamCount(method.Token) == paramCount) {
return method;
}
}
throw new DebuggerException("Not found");
}
}
}
#pragma warning restore 1591

7
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/MethodProps.cs

@ -5,11 +5,13 @@ @@ -5,11 +5,13 @@
// <version>$Revision$</version>
// </file>
#pragma warning disable 1591
using System;
namespace Debugger.Wrappers.MetaData
{
struct MethodProps
public struct MethodProps
{
public uint Token;
public string Name;
@ -17,7 +19,6 @@ namespace Debugger.Wrappers.MetaData @@ -17,7 +19,6 @@ namespace Debugger.Wrappers.MetaData
public uint Flags;
public uint ImplFlags;
public uint CodeRVA;
public SignatureStream Signature;
public bool IsStatic {
get {
@ -38,3 +39,5 @@ namespace Debugger.Wrappers.MetaData @@ -38,3 +39,5 @@ namespace Debugger.Wrappers.MetaData
}
}
}
#pragma warning restore 1591

6
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/ParamProps.cs

@ -5,11 +5,13 @@ @@ -5,11 +5,13 @@
// <version>$Revision$</version>
// </file>
#pragma warning disable 1591
using System;
namespace Debugger.Wrappers.MetaData
{
struct ParamProps
public struct ParamProps
{
public uint Token;
public string Name;
@ -18,3 +20,5 @@ namespace Debugger.Wrappers.MetaData @@ -18,3 +20,5 @@ namespace Debugger.Wrappers.MetaData
public uint Flags;
}
}
#pragma warning restore 1591

6
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/TypeDefProps.cs

@ -5,11 +5,13 @@ @@ -5,11 +5,13 @@
// <version>$Revision$</version>
// </file>
#pragma warning disable 1591
using System;
namespace Debugger.Wrappers.MetaData
{
struct TypeDefProps
public struct TypeDefProps
{
public uint Token;
public string Name;
@ -17,3 +19,5 @@ namespace Debugger.Wrappers.MetaData @@ -17,3 +19,5 @@ namespace Debugger.Wrappers.MetaData
public uint SuperClassToken;
}
}
#pragma warning restore 1591

6
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/MetaData/TypeRefProps.cs

@ -5,13 +5,17 @@ @@ -5,13 +5,17 @@
// <version>$Revision$</version>
// </file>
#pragma warning disable 1591
using System;
namespace Debugger.Wrappers.MetaData
{
struct TypeRefProps
public struct TypeRefProps
{
public uint Token;
public string Name;
}
}
#pragma warning restore 1591

4
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/NativeMethods.cs

@ -11,9 +11,9 @@ using System; @@ -11,9 +11,9 @@ using System;
using System.Runtime.InteropServices;
using System.Text;
namespace Debugger
namespace Debugger.Interop
{
internal static class NativeMethods
public static class NativeMethods
{
[DllImport("kernel32.dll")]
public static extern bool CloseHandle(IntPtr handle);

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/ResourceManager.cs

@ -11,6 +11,8 @@ using System; @@ -11,6 +11,8 @@ using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Debugger.Interop;
namespace Debugger.Wrappers
{
class TrackedObjectMetaData

Loading…
Cancel
Save