Browse Source

Rewritten the stepping engine;

Extensive unit test for stepping

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@3229 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 17 years ago
parent
commit
55e8e0bd7e
  1. 35
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Options/DebuggingOptions.cs
  2. 6
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Options/DebuggingOptionsPanel.cs
  3. 8
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Options/DebuggingSymbolsPanel.cs
  4. 11
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs
  5. 143
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Module.cs
  6. 22
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/NDebugger.cs
  7. 3
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Process-StateControl.cs
  8. 37
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/StackFrame.cs
  9. 127
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Stepper.cs
  10. 6
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Thread.cs
  11. 56
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Options.cs
  12. 35
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Internal/ManagedCallback.cs
  13. 16
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs
  14. 131
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/MethodInfo.cs
  15. 1
      src/AddIns/Misc/Debugger/Debugger.Tests/Project/Debugger.Tests.csproj
  16. 160
      src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebuggerAttributes.cs
  17. 32
      src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/Generics.cs
  18. 48
      src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/Metadata.cs
  19. 269
      src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/Stepping.cs

35
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Options/DebuggingOptions.cs

@ -20,35 +20,10 @@ namespace ICSharpCode.SharpDevelop.Services @@ -20,35 +20,10 @@ namespace ICSharpCode.SharpDevelop.Services
}
}
bool iCorDebugVisualizerEnabled;
bool showValuesInHexadecimal;
bool showArgumentNames;
bool showArgumentValues;
bool showExternalMethods;
public bool ICorDebugVisualizerEnabled {
get { return iCorDebugVisualizerEnabled; }
set { iCorDebugVisualizerEnabled = value; }
}
public bool ShowValuesInHexadecimal {
get { return showValuesInHexadecimal; }
set { showValuesInHexadecimal = value; }
}
public bool ShowArgumentNames {
get { return showArgumentNames; }
set { showArgumentNames = value; }
}
public bool ShowArgumentValues {
get { return showArgumentValues; }
set { showArgumentValues = value; }
}
public bool ShowExternalMethods {
get { return showExternalMethods; }
set { showExternalMethods = value; }
}
public bool ICorDebugVisualizerEnabled;
public bool ShowValuesInHexadecimal;
public bool ShowArgumentNames;
public bool ShowArgumentValues;
public bool ShowExternalMethods;
}
}

6
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Options/DebuggingOptionsPanel.cs

@ -5,11 +5,11 @@ @@ -5,11 +5,11 @@
// <version>$Revision$</version>
// </file>
using Debugger;
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Services;
@ -55,6 +55,10 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels @@ -55,6 +55,10 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels
opt.StepOverSingleLineProperties = stepOverSingleLineProperties.Checked;
opt.StepOverFieldAccessProperties = stepOverFieldAccessProperties.Checked;
Process proc = WindowsDebugger.CurrentProcess;
if (proc != null) {
proc.Debugger.ResetJustMyCodeStatus();
}
return true;
}
}

8
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Options/DebuggingSymbolsPanel.cs

@ -5,11 +5,11 @@ @@ -5,11 +5,11 @@
// <version>$Revision$</version>
// </file>
using Debugger;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Services;
@ -37,7 +37,11 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels @@ -37,7 +37,11 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels
public override bool StorePanelContents()
{
DebuggingOptions.Instance.SymbolsSearchPaths = pathList.GetList();
Process proc = WindowsDebugger.CurrentProcess;
if (proc != null) {
proc.Debugger.ReloadModuleSymbols();
proc.Debugger.ResetJustMyCodeStatus();
}
return true;
}
}

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

@ -93,6 +93,17 @@ namespace ICSharpCode.SharpDevelop.Services @@ -93,6 +93,17 @@ namespace ICSharpCode.SharpDevelop.Services
}
}
public static Debugger.Process CurrentProcess {
get {
WindowsDebugger dbgr = DebuggerService.CurrentDebugger as WindowsDebugger;
if (dbgr != null && dbgr.DebuggedProcess != null) {
return dbgr.DebuggedProcess;
} else {
return null;
}
}
}
protected virtual void OnProcessSelected(ProcessEventArgs e)
{
if (ProcessSelected != null) {

143
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Module.cs

@ -176,9 +176,11 @@ namespace Debugger @@ -176,9 +176,11 @@ namespace Debugger
fullPath = pModule.Name;
LoadSymbols(process.Options.SymbolsSearchPaths);
SetJustMyCodeStatus();
ResetJustMyCodeStatus();
}
/// <summary> Try to load the debugging symbols (.pdb) from the given path </summary>
public void LoadSymbols(string[] searchPath)
{
if (symReader == null) {
@ -189,146 +191,17 @@ namespace Debugger @@ -189,146 +191,17 @@ namespace Debugger
}
}
/// <summary>
/// Finds all classes and methods marked with DebuggerNonUserCode attribute
/// and marks them for JMC so that they are not stepped into
/// </summary>
public void SetJustMyCodeStatus()
/// <summary> Sets all code as being 'my code'. The code will be gradually
/// set to not-user-code as encountered acording to stepping options </summary>
public void ResetJustMyCodeStatus()
{
DateTime start, end;
uint unused = 0;
if (!this.Process.Options.EnableJustMyCode) {
corModule.CastTo<ICorDebugModule2>().SetJMCStatus(1, 0, ref unused);
return;
}
if (!this.HasSymbols) {
if (this.Process.Options.StepOverNoSymbols && !this.HasSymbols) {
// Optimization - set the code as non-user right away
corModule.CastTo<ICorDebugModule2>().SetJMCStatus(0, 0, ref unused);
return;
}
this.Process.TraceMessage("JMC for " + this.Filename);
start = Util.HighPrecisionTimer.Now;
// By default the code is my code
corModule.CastTo<ICorDebugModule2>().SetJMCStatus(1, 0, ref unused);
end = Util.HighPrecisionTimer.Now;
this.Process.TraceMessage(" * Defualt ({0} ms)", (end - start).TotalMilliseconds);
start = Util.HighPrecisionTimer.Now;
// Apply non-user code attributes
if (this.Process.Options.StepOverDebuggerAttributes) {
foreach(CustomAttributeProps ca in metaData.EnumCustomAttributeProps(0, 0)) {
MemberRefProps constructorMethod = metaData.GetMemberRefProps(ca.Type);
TypeRefProps attributeType = metaData.GetTypeRefProps(constructorMethod.DeclaringType);
if (attributeType.Name == "System.Diagnostics.DebuggerStepThroughAttribute" ||
attributeType.Name == "System.Diagnostics.DebuggerNonUserCodeAttribute" ||
attributeType.Name == "System.Diagnostics.DebuggerHiddenAttribute")
{
if (ca.Owner >> 24 == 0x02) { // TypeDef
ICorDebugClass2 corClass = corModule.GetClassFromToken(ca.Owner).CastTo<ICorDebugClass2>();
corClass.SetJMCStatus(0 /* false */);
if (this.Process.Options.Verbose) {
this.Process.TraceMessage("Class {0} marked as non-user code", metaData.GetTypeDefProps(ca.Owner).Name);
}
}
if (ca.Owner >> 24 == 0x06) { // MethodDef
DisableJustMyCode(ca.Owner);
}
}
}
}
end = Util.HighPrecisionTimer.Now;
this.Process.TraceMessage(" * Attributes ({0} ms)", (end - start).TotalMilliseconds);
start = Util.HighPrecisionTimer.Now;
// Mark all methods without symbols as non-user code
if (this.Process.Options.StepOverDebuggerAttributes) { // TODO: Remove
foreach(uint typeDef in metaData.EnumTypeDefs()) {
foreach(uint methodDef in metaData.EnumMethods(typeDef)) {
if (!HasMethodSymbols(methodDef)) {
DisableJustMyCode(methodDef);
}
}
}
}
end = Util.HighPrecisionTimer.Now;
this.Process.TraceMessage(" * All functions ({0} ms)", (end - start).TotalMilliseconds);
start = Util.HighPrecisionTimer.Now;
// Skip properties
if (this.Process.Options.StepOverAllProperties) {
foreach(uint typeDef in metaData.EnumTypeDefs()) {
foreach(PropertyProps prop in metaData.EnumPropertyProps(typeDef)) {
if ((prop.GetterMethod & 0xFFFFFF) != 0) {
if (!Process.Options.StepOverSingleLineProperties || IsSingleLine(prop.GetterMethod)) {
DisableJustMyCode(prop.GetterMethod);
}
}
if ((prop.SetterMethod & 0xFFFFFF) != 0) {
if (!Process.Options.StepOverSingleLineProperties || IsSingleLine(prop.SetterMethod)) {
DisableJustMyCode(prop.SetterMethod);
}
}
}
}
}
end = Util.HighPrecisionTimer.Now;
this.Process.TraceMessage(" * Properties ({0} ms)", (end - start).TotalMilliseconds);
// this.Process.TraceMessage("Set Just-My-Code for module \"{0}\" ({1} ms)", this.Filename, (end - start).TotalMilliseconds);
}
bool HasMethodSymbols(uint methodDef)
{
try {
return this.SymReader.GetMethod(methodDef) != null;
} catch (COMException) {
// Symbols not found
return false;
}
}
void DisableJustMyCode(uint methodDef)
{
MethodProps methodProps = metaData.GetMethodProps(methodDef);
TypeDefProps typeProps = metaData.GetTypeDefProps(methodProps.ClassToken);
ICorDebugFunction2 corFunction = corModule.GetFunctionFromToken(methodProps.Token).CastTo<ICorDebugFunction2>();
corFunction.SetJMCStatus(0 /* false */);
if (this.Process.Options.Verbose) {
this.Process.TraceMessage("Funciton {0}.{1} marked as non-user code", typeProps.Name, methodProps.Name);
}
}
bool IsSingleLine(uint methodDef)
{
ISymUnmanagedMethod symMethod;
try {
symMethod = this.SymReader.GetMethod(methodDef);
} catch (COMException) {
return false; // No symbols - can not determine
}
List<SequencePoint> seqPoints = new List<SequencePoint>(symMethod.SequencePoints);
seqPoints.Sort();
// Remove initial "{"
if (seqPoints.Count > 0 &&
seqPoints[0].Line == seqPoints[0].EndLine &&
seqPoints[0].EndColumn - seqPoints[0].Column <= 1) {
seqPoints.RemoveAt(0);
}
// Remove last "}"
int listIndex = seqPoints.Count - 1;
if (seqPoints.Count > 0 &&
seqPoints[listIndex].Line == seqPoints[listIndex].EndLine &&
seqPoints[listIndex].EndColumn - seqPoints[listIndex].Column <= 1) {
seqPoints.RemoveAt(listIndex);
}
// Is single line
return seqPoints.Count == 0 || seqPoints[0].Line == seqPoints[seqPoints.Count - 1].EndLine;
}
public void ApplyChanges(byte[] metadata, byte[] il)

22
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/NDebugger.cs

@ -204,6 +204,28 @@ namespace Debugger @@ -204,6 +204,28 @@ namespace Debugger
}
}
}
/// <summary> Try to load module symbols using the search path defined in the options </summary>
public void ReloadModuleSymbols()
{
foreach(Process process in this.Processes) {
foreach(Module module in process.Modules) {
module.LoadSymbols(process.Options.SymbolsSearchPaths);
}
}
TraceMessage("Reloaded symbols");
}
/// <summary> Reset the just my code status of modules. Use this after changing any stepping options. </summary>
public void ResetJustMyCodeStatus()
{
foreach(Process process in this.Processes) {
foreach(Module module in process.Modules) {
module.ResetJustMyCodeStatus();
}
}
TraceMessage("Just my code reseted");
}
}
[Serializable]

3
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Process-StateControl.cs

@ -273,8 +273,9 @@ namespace Debugger @@ -273,8 +273,9 @@ namespace Debugger
internal void DisableAllSteppers()
{
foreach(Thread thread in this.Threads) {
thread.CurrentStepIn = null;
foreach(Stepper stepper in thread.Steppers) {
stepper.PauseWhenComplete = false;
stepper.Ignore = true;
}
}
}

37
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/StackFrame.cs

@ -169,7 +169,7 @@ namespace Debugger @@ -169,7 +169,7 @@ namespace Debugger
/// <summary> Step out of the stack frame </summary>
public void AsyncStepOut()
{
new Stepper(this, "StackFrame step out").StepOut();
Stepper.StepOut(this, "normal");
process.AsyncContinue(DebuggeeStateAction.Clear);
}
@ -186,9 +186,17 @@ namespace Debugger @@ -186,9 +186,17 @@ namespace Debugger
}
if (stepIn) {
new Stepper(this, "StackFrame step in").StepIn(nextSt.StepRanges);
Stepper stepInStepper = Stepper.StepIn(this, nextSt.StepRanges, "normal");
this.Thread.CurrentStepIn = stepInStepper;
Stepper clearCurrentStepIn = Stepper.StepOut(this, "clear current step in");
clearCurrentStepIn.StepComplete += delegate {
if (this.Thread.CurrentStepIn == stepInStepper) {
this.Thread.CurrentStepIn = null;
}
};
clearCurrentStepIn.Ignore = true;
} else {
new Stepper(this, "StackFrame step over").StepOver(nextSt.StepRanges);
Stepper.StepOver(this, nextSt.StepRanges, "normal");
}
process.AsyncContinue(DebuggeeStateAction.Clear);
@ -378,5 +386,28 @@ namespace Debugger @@ -378,5 +386,28 @@ namespace Debugger
}
#endregion
public override bool Equals(object obj)
{
StackFrame other = obj as StackFrame;
return
other != null &&
other.Thread == this.Thread &&
other.ChainIndex == this.ChainIndex &&
other.FrameIndex == this.FrameIndex &&
other.MethodInfo == this.methodInfo;
}
public override int GetHashCode()
{
int hashCode = 0;
unchecked {
if (thread != null) hashCode += 1000000009 * thread.GetHashCode();
if (methodInfo != null) hashCode += 1000000093 * methodInfo.GetHashCode();
hashCode += 1000000097 * chainIndex.GetHashCode();
hashCode += 1000000103 * frameIndex.GetHashCode();
}
return hashCode;
}
}
}

127
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Stepper.cs

@ -11,83 +11,67 @@ using Debugger.Wrappers.CorDebug; @@ -11,83 +11,67 @@ using Debugger.Wrappers.CorDebug;
namespace Debugger
{
public class Stepper
enum StepperOperation {StepIn, StepOver, StepOut};
class Stepper
{
public enum StepperOperation {Idle, StepIn, StepOver, StepOut};
StackFrame stackFrame;
StepperOperation operation;
int[] stepRanges;
string name;
ICorDebugStepper corStepper;
StepperOperation operation = StepperOperation.Idle;
bool pauseWhenComplete = true;
bool ignore;
public event EventHandler<StepperEventArgs> StepComplete;
[Debugger.Tests.Ignore]
public Process Process {
get {
return stackFrame.Process;
}
get { return stackFrame.Process; }
}
public StackFrame StackFrame {
get {
return stackFrame;
}
}
public string Name {
get {
return name;
}
get { return stackFrame; }
}
public StepperOperation Operation {
get {
return operation;
}
get { return operation; }
}
public bool PauseWhenComplete {
get {
return pauseWhenComplete;
}
set {
pauseWhenComplete = value;
}
public int[] StepRanges {
get { return stepRanges; }
}
public bool JustMyCode {
set {
if (value) {
corStepper.SetUnmappedStopMask(CorDebugUnmappedStop.STOP_NONE);
corStepper.CastTo<ICorDebugStepper2>().SetJMC(1);
} else {
corStepper.SetUnmappedStopMask(CorDebugUnmappedStop.STOP_NONE);
corStepper.CastTo<ICorDebugStepper2>().SetJMC(0);
}
}
public string Name {
get { return name; }
}
public Stepper(StackFrame stackFrame, string name): this(stackFrame)
{
this.name = name;
public bool Ignore {
get { return ignore; }
set { ignore = value; }
}
public Stepper(StackFrame stackFrame)
private Stepper(StackFrame stackFrame, StepperOperation operation, int[] stepRanges, string name, bool justMyCode)
{
this.stackFrame = stackFrame;
this.operation = operation;
this.stepRanges = stepRanges;
this.name = name;
corStepper = stackFrame.CorILFrame.CreateStepper();
this.JustMyCode = Process.Options.EnableJustMyCode;
this.corStepper = stackFrame.CorILFrame.CreateStepper();
this.ignore = false;
this.StackFrame.Thread.Steppers.Add(this);
stackFrame.Thread.Steppers.Add(this);
if (justMyCode) {
corStepper.SetUnmappedStopMask(CorDebugUnmappedStop.STOP_NONE);
corStepper.CastTo<ICorDebugStepper2>().SetJMC(1);
}
}
protected internal virtual void OnStepComplete() {
protected internal virtual void OnStepComplete(CorDebugStepReason reason) {
this.corStepper = null;
if (StepComplete != null) {
StepComplete(this, new StepperEventArgs(this));
StepComplete(this, new StepperEventArgs(this, reason));
}
}
@ -96,45 +80,62 @@ namespace Debugger @@ -96,45 +80,62 @@ namespace Debugger
return this.corStepper == corStepper;
}
public void StepOut()
internal bool IsInStepRanges(int offset)
{
for(int i = 0; i < stepRanges.Length / 2; i++) {
if (stepRanges[2*i] <= offset && offset < stepRanges[2*i + 1]) {
return true;
}
}
return false;
}
public static Stepper StepOut(StackFrame stackFrame, string name)
{
operation = StepperOperation.StepOut;
JustMyCode = false; // Needed for multiple events. See docs\Stepping.txt
corStepper.StepOut();
// JMC off - Needed for multiple events. See docs\Stepping.txt
Stepper stepper = new Stepper(stackFrame, StepperOperation.StepOut, null, name, false);
stepper.corStepper.StepOut();
return stepper;
}
public void StepIn(int[] ranges)
public static Stepper StepIn(StackFrame stackFrame, int[] stepRanges, string name)
{
operation = StepperOperation.StepIn;
corStepper.StepRange(true /* step in */, ranges);
Stepper stepper = new Stepper(stackFrame, StepperOperation.StepIn, stepRanges, name, stackFrame.Process.Options.EnableJustMyCode);
stepper.corStepper.StepRange(true /* step in */, stepRanges);
return stepper;
}
public void StepOver(int[] ranges)
public static Stepper StepOver(StackFrame stackFrame, int[] stepRanges, string name)
{
operation = StepperOperation.StepOver;
corStepper.StepRange(false /* step over */, ranges);
Stepper stepper = new Stepper(stackFrame, StepperOperation.StepOver, stepRanges, name, stackFrame.Process.Options.EnableJustMyCode);
stepper.corStepper.StepRange(false /* step over */, stepRanges);
return stepper;
}
public override string ToString()
{
return string.Format("{0} in {1} pause={2} \"{3}\"", Operation, StackFrame.ToString(), PauseWhenComplete, name);
return string.Format("{0} from {1} name=\"{2}\"", this.Operation, this.StackFrame.ToString(), this.Name);
}
}
[Serializable]
public class StepperEventArgs: ProcessEventArgs
class StepperEventArgs: ProcessEventArgs
{
Stepper stepper;
CorDebugStepReason reason;
public Stepper Stepper {
get {
return stepper;
}
get { return stepper; }
}
public CorDebugStepReason Reason {
get { return reason; }
}
public StepperEventArgs(Stepper stepper): base(stepper.Process)
public StepperEventArgs(Stepper stepper, CorDebugStepReason reason): base(stepper.Process)
{
this.stepper = stepper;
this.reason = reason;
}
}
}

6
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Thread.cs

@ -23,6 +23,7 @@ namespace Debugger @@ -23,6 +23,7 @@ namespace Debugger
ICorDebugThread corThread;
bool hasExited = false;
Stepper currentStepIn;
List<Stepper> steppers = new List<Stepper>();
StackFrame selectedStackFrame;
@ -50,6 +51,11 @@ namespace Debugger @@ -50,6 +51,11 @@ namespace Debugger
private set { hasExited = value; }
}
internal Stepper CurrentStepIn {
get { return currentStepIn; }
set { currentStepIn = value; }
}
/// <summary> From time to time the thread may be in invalid state. </summary>
public bool IsInValidState {
get {

56
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Options.cs

@ -10,53 +10,13 @@ namespace Debugger @@ -10,53 +10,13 @@ namespace Debugger
{
public class Options
{
bool enableJustMyCode = true;
bool stepOverNoSymbols = true;
bool stepOverDebuggerAttributes = true;
bool stepOverAllProperties = false;
bool stepOverSingleLineProperties = false;
bool stepOverFieldAccessProperties = true;
bool verbose = false;
string[] symbolsSearchPaths = new string[0];
public bool EnableJustMyCode {
get { return enableJustMyCode; }
set { enableJustMyCode = value; }
}
public bool StepOverNoSymbols {
get { return stepOverNoSymbols; }
set { stepOverNoSymbols = value; }
}
public bool StepOverDebuggerAttributes {
get { return stepOverDebuggerAttributes; }
set { stepOverDebuggerAttributes = value; }
}
public bool StepOverAllProperties {
get { return stepOverAllProperties; }
set { stepOverAllProperties = value; }
}
public bool StepOverSingleLineProperties {
get { return stepOverSingleLineProperties; }
set { stepOverSingleLineProperties = value; }
}
public bool StepOverFieldAccessProperties {
get { return stepOverFieldAccessProperties; }
set { stepOverFieldAccessProperties = value; }
}
public bool Verbose {
get { return verbose; }
set { verbose = value; }
}
public string[] SymbolsSearchPaths {
get { return symbolsSearchPaths; }
set { symbolsSearchPaths = value; }
}
public bool EnableJustMyCode = true;
public bool StepOverNoSymbols = true;
public bool StepOverDebuggerAttributes = true;
public bool StepOverAllProperties = false;
public bool StepOverSingleLineProperties = false;
public bool StepOverFieldAccessProperties = true;
public bool Verbose = false;
public string[] SymbolsSearchPaths = new string[0];
}
}

35
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Internal/ManagedCallback.cs

@ -12,6 +12,7 @@ @@ -12,6 +12,7 @@
// Replace with:
// \1\2\n\1{\n\1\tEnterCallback(PausedReason.Other, "\3");\n\1\t\n\1\tExitCallback_Continue();\n\1}
using Debugger.MetaData;
using System;
using System.Runtime.InteropServices;
using Debugger.Wrappers.CorDebug;
@ -125,20 +126,34 @@ namespace Debugger @@ -125,20 +126,34 @@ namespace Debugger
Thread thread = process.GetThread(pThread);
Stepper stepper = thread.GetStepper(pStepper);
process.TraceMessage(" - stepper info: " + stepper.ToString());
StackFrame currentStackFrame = process.SelectedThread.MostRecentStackFrame;
process.TraceMessage(" - stopped at {0} because of {1}", currentStackFrame.MethodInfo.FullName, stepper.ToString());
thread.Steppers.Remove(stepper);
stepper.OnStepComplete();
if (stepper.PauseWhenComplete) {
if (process.SelectedThread.MostRecentStackFrame.HasSymbols &&
process.SelectedThread.MostRecentStackFrame.MethodInfo.IsMyCode) {
// This is a good place, let's stay here
pauseOnNextExit = true;
stepper.OnStepComplete(reason);
if (stepper.Ignore) {
// The stepper is ignored
process.TraceMessage(" - ignored");
} else if (thread.CurrentStepIn != null &&
thread.CurrentStepIn.StackFrame.Equals(currentStackFrame) &&
thread.CurrentStepIn.IsInStepRanges((int)currentStackFrame.CorInstructionPtr)) {
Stepper.StepIn(currentStackFrame, thread.CurrentStepIn.StepRanges, "finishing step in");
process.TraceMessage(" - finishing step in");
} else if (currentStackFrame.MethodInfo.StepOver) {
if (process.Options.EnableJustMyCode) {
currentStackFrame.MethodInfo.MarkAsNonUserCode();
process.TraceMessage(" - method {0} marked as non user code", currentStackFrame.MethodInfo.FullName);
Stepper.StepIn(currentStackFrame, new int[] {0, int.MaxValue}, "seeking user code");
process.TraceMessage(" - seeking user code");
} else {
// Continue stepping to leave this place
Stepper.StepOut(currentStackFrame, "stepping out of non-user code");
process.TraceMessage(" - stepping out of non-user code");
}
} else {
// User-code method
pauseOnNextExit = true;
process.TraceMessage(" - pausing in user code");
}
ExitCallback();

16
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs

@ -30,7 +30,6 @@ namespace Debugger.MetaData @@ -30,7 +30,6 @@ namespace Debugger.MetaData
string fullName;
// Class/ValueType specific
ICorDebugClass corClass;
Module module;
TypeDefProps classProps;
@ -81,7 +80,7 @@ namespace Debugger.MetaData @@ -81,7 +80,7 @@ namespace Debugger.MetaData
/// <para> Only applicable to class or value type! </para>
/// </summary>
[Debugger.Tests.Ignore]
public uint MetadataToken {
public uint Token {
get {
AssertClassOrValueType();
return classProps.Token;
@ -326,9 +325,8 @@ namespace Debugger.MetaData @@ -326,9 +325,8 @@ namespace Debugger.MetaData
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);
this.module = process.GetModule(corType.Class.Module);
this.classProps = module.MetaData.GetTypeDefProps(corType.Class.Token);
}
if (this.IsClass || this.IsValueType || this.IsArray || this.IsPointer) {
@ -489,7 +487,7 @@ namespace Debugger.MetaData @@ -489,7 +487,7 @@ namespace Debugger.MetaData
void LoadMemberInfo()
{
// Load interfaces
foreach(InterfaceImplProps implProps in module.MetaData.EnumInterfaceImplProps(this.MetadataToken)) {
foreach(InterfaceImplProps implProps in module.MetaData.EnumInterfaceImplProps(this.Token)) {
if ((implProps.Interface & 0xFF000000) == (uint)CorTokenType.TypeDef ||
(implProps.Interface & 0xFF000000) == (uint)CorTokenType.TypeRef)
{
@ -498,13 +496,13 @@ namespace Debugger.MetaData @@ -498,13 +496,13 @@ namespace Debugger.MetaData
}
// Load fields
foreach(FieldProps field in module.MetaData.EnumFieldProps(this.MetadataToken)) {
foreach(FieldProps field in module.MetaData.EnumFieldProps(this.Token)) {
if (field.IsStatic && field.IsLiteral) continue; // Skip static literals TODO: Why?
members.Add(new FieldInfo(this, field));
};
// Load methods
foreach(MethodProps m in module.MetaData.EnumMethodProps(this.MetadataToken)) {
foreach(MethodProps m in module.MetaData.EnumMethodProps(this.Token)) {
members.Add(new MethodInfo(this, m));
}
@ -581,7 +579,7 @@ namespace Debugger.MetaData @@ -581,7 +579,7 @@ namespace Debugger.MetaData
if (this.IsClass || this.IsValueType) {
return (other.IsClass || other.IsValueType) &&
other.Module == this.Module &&
other.MetadataToken == this.MetadataToken;
other.Token == this.Token;
}
if (this.IsPointer) {
return other.IsPointer &&

131
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/MethodInfo.cs

@ -20,7 +20,6 @@ namespace Debugger.MetaData @@ -20,7 +20,6 @@ namespace Debugger.MetaData
public class MethodInfo: MemberInfo
{
MethodProps methodProps;
FieldInfo backingField;
/// <summary> Gets the name of this method </summary>
public override string Name {
@ -29,10 +28,6 @@ namespace Debugger.MetaData @@ -29,10 +28,6 @@ namespace Debugger.MetaData
}
}
internal FieldInfo BackingField {
get { return backingField; }
}
/// <summary> Gets a value indicating whether this member has the private access modifier</summary>
public override bool IsPrivate {
get { return methodProps.IsPrivate; }
@ -83,26 +78,59 @@ namespace Debugger.MetaData @@ -83,26 +78,59 @@ namespace Debugger.MetaData
}
}
public bool IsMyCode {
/// <summary> Gets value indicating whether this method should be stepped over
/// accoring to current options </summary>
public bool StepOver {
get {
return this.CorFunction.CastTo<ICorDebugFunction2>().JMCStatus != 0;
}
set {
this.CorFunction.CastTo<ICorDebugFunction2>().SetJMCStatus(value ? 1 : 0);
Options opt = this.Process.Options;
if (opt.StepOverNoSymbols) {
if (this.SymMethod == null) return true;
}
if (opt.StepOverDebuggerAttributes) {
if (this.HasDebuggerAttribute) return true;
}
if (opt.StepOverAllProperties) {
if (this.IsProperty)return true;
}
if (opt.StepOverSingleLineProperties) {
if (this.IsProperty && this.IsSingleLine) return true;
}
if (opt.StepOverFieldAccessProperties) {
if (this.IsProperty && this.BackingField != null) return true;
}
return false;
}
}
internal MethodInfo(DebugType declaringType, MethodProps methodProps):base (declaringType)
{
this.methodProps = methodProps;
this.backingField = GetBackingField();
}
// TODO: More accurate
bool IsProperty {
get {
return this.Name.StartsWith("get_") || this.Name.StartsWith("set_");
}
}
FieldInfo backingFieldCache;
bool getBackingFieldCalled;
internal FieldInfo BackingField {
get {
if (!getBackingFieldCalled) {
backingFieldCache = GetBackingField();
getBackingFieldCalled = true;
}
return backingFieldCache;
}
}
// Is this method in form 'return this.field;'?
FieldInfo GetBackingField()
{
if (this.IsStatic) return null;
if (this.IsStatic) return null; // TODO: Make work for static
if (this.ParameterCount != 0) return null;
ICorDebugCode corCode;
@ -177,6 +205,83 @@ namespace Debugger.MetaData @@ -177,6 +205,83 @@ namespace Debugger.MetaData
return null;
}
bool? isSingleLineCache;
bool IsSingleLine {
get {
// Note symbols might get loaded manually later by the user
ISymUnmanagedMethod symMethod = this.SymMethod;
if (symMethod == null) return false; // No symbols - can not determine
if (isSingleLineCache.HasValue) return isSingleLineCache.Value;
List<SequencePoint> seqPoints = new List<SequencePoint>(symMethod.SequencePoints);
seqPoints.Sort();
// Remove initial "{"
if (seqPoints.Count > 0 &&
seqPoints[0].Line == seqPoints[0].EndLine &&
seqPoints[0].EndColumn - seqPoints[0].Column <= 1) {
seqPoints.RemoveAt(0);
}
// Remove last "}"
int listIndex = seqPoints.Count - 1;
if (seqPoints.Count > 0 &&
seqPoints[listIndex].Line == seqPoints[listIndex].EndLine &&
seqPoints[listIndex].EndColumn - seqPoints[listIndex].Column <= 1) {
seqPoints.RemoveAt(listIndex);
}
// Is single line
isSingleLineCache = seqPoints.Count == 0 || seqPoints[0].Line == seqPoints[seqPoints.Count - 1].EndLine;
return isSingleLineCache.Value;
}
}
bool? hasDebuggerAttributeCache;
bool HasDebuggerAttribute {
get {
if (hasDebuggerAttributeCache.HasValue) return hasDebuggerAttributeCache.Value;
MetaDataImport metaData = this.Module.MetaData;
hasDebuggerAttributeCache = false;
// Look on the method
foreach(CustomAttributeProps ca in metaData.EnumCustomAttributeProps(methodProps.Token, 0)) {
MemberRefProps constructorMethod = metaData.GetMemberRefProps(ca.Type);
TypeRefProps attributeType = metaData.GetTypeRefProps(constructorMethod.DeclaringType);
if (attributeType.Name == "System.Diagnostics.DebuggerStepThroughAttribute" ||
attributeType.Name == "System.Diagnostics.DebuggerNonUserCodeAttribute" ||
attributeType.Name == "System.Diagnostics.DebuggerHiddenAttribute")
{
hasDebuggerAttributeCache = true;
}
}
// Look on the type
foreach(CustomAttributeProps ca in metaData.EnumCustomAttributeProps(this.DeclaringType.Token, 0)) {
MemberRefProps constructorMethod = metaData.GetMemberRefProps(ca.Type);
TypeRefProps attributeType = metaData.GetTypeRefProps(constructorMethod.DeclaringType);
if (attributeType.Name == "System.Diagnostics.DebuggerStepThroughAttribute" ||
attributeType.Name == "System.Diagnostics.DebuggerNonUserCodeAttribute" ||
attributeType.Name == "System.Diagnostics.DebuggerHiddenAttribute")
{
hasDebuggerAttributeCache = true;
}
}
return hasDebuggerAttributeCache.Value;
}
}
internal void MarkAsNonUserCode()
{
this.CorFunction.CastTo<ICorDebugFunction2>().SetJMCStatus(0 /* false */);
if (this.Process.Options.Verbose) {
this.Process.TraceMessage("Funciton {0} marked as non-user code", this.FullName);
}
}
/// <summary>
/// Get a method from a managed type, method name and argument count
/// </summary>

1
src/AddIns/Misc/Debugger/Debugger.Tests/Project/Debugger.Tests.csproj

@ -46,7 +46,6 @@ @@ -46,7 +46,6 @@
<Compile Include="Src\TestPrograms\Breakpoint.cs" />
<Compile Include="Src\TestPrograms\Callstack.cs" />
<Compile Include="Src\TestPrograms\DebuggeeKilled.cs" />
<Compile Include="Src\TestPrograms\DebuggerAttributes.cs" />
<Compile Include="Src\TestPrograms\DebugTypes.cs" />
<Compile Include="Src\TestPrograms\DefinedTypes.cs" />
<Compile Include="Src\TestPrograms\Exception.cs" />

160
src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebuggerAttributes.cs

@ -1,160 +0,0 @@ @@ -1,160 +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.Diagnostics;
namespace Debugger.Tests.TestPrograms
{
public class DebuggerAttributes
{
public static void Main()
{
System.Diagnostics.Debugger.Break();
Internal();
IgnoredClass.Internal();
StepOut1();
IgnoredClass.Internal_Pass();
new DefaultCtorClass().Target();
int s = ShortProperty;
int l = LongProperty;
}
[DebuggerStepThrough]
static void StepOut1()
{
StepOut2();
}
static void StepOut2()
{
}
[DebuggerStepThrough]
static void Internal()
{
}
[DebuggerNonUserCode]
public class IgnoredClass
{
public static void Internal()
{
}
public static void Internal_Pass()
{
NotIgnoredClass.Target();
}
}
public class NotIgnoredClass
{
public static void Target()
{
}
}
public class DefaultCtorClass
{
public void Target()
{
}
}
public static int ShortProperty {
get {
return 1;
}
}
public static int LongProperty {
get {
return
1;
}
}
}
}
#if TEST_CODE
namespace Debugger.Tests {
using NUnit.Framework;
using Debugger.Wrappers.CorDebug;
using Debugger.Wrappers.MetaData;
public partial class DebuggerTests
{
//[NUnit.Framework.Test]
public void DebuggerAttributes()
{
StartTest("DebuggerAttributes.cs");
process.SelectedStackFrame.StepInto(); // Break command
process.SelectedStackFrame.StepInto(); // Internal
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepInto(); // IgnoredClass.Internal
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepInto(); // StepOut1
Assert.AreEqual("StepOut2", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepOut();
process.SelectedStackFrame.StepOver(); // Finish the step out
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepInto(); // IgnoredClass.Internal_Pass
Assert.AreEqual("Target", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepOut();
process.SelectedStackFrame.StepOver(); // Finish the step out
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepInto(); // Generated default constructor
Assert.AreEqual("Target", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepOut();
process.SelectedStackFrame.StepOver(); // Finish the step out
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepInto(); // ShortProperty
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepInto(); // LongProperty
Assert.AreEqual("get_LongProperty", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepOut();
process.SelectedStackFrame.StepOver(); // Finish the step out
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
EndTest();
}
}
}
#endif
#if EXPECTED_OUTPUT
<?xml version="1.0" encoding="utf-8"?>
<DebuggerTests>
<Test
name="DebuggerAttributes.cs">
<ProcessStarted />
<ModuleLoaded>mscorlib.dll (No symbols)</ModuleLoaded>
<ModuleLoaded>DebuggerAttributes.exe (Has symbols)</ModuleLoaded>
<DebuggingPaused>Break</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<ProcessExited />
</Test>
</DebuggerTests>
#endif // EXPECTED_OUTPUT

32
src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/Generics.cs

@ -146,14 +146,14 @@ namespace Debugger.Tests { @@ -146,14 +146,14 @@ namespace Debugger.Tests {
DeclaringType="Debugger.Tests.TestPrograms.GenericClass&lt;System.Int32,System.String&gt;"
FullName="Debugger.Tests.TestPrograms.GenericClass&lt;System.Int32,System.String&gt;.Metod"
IsInternal="False"
IsMyCode="True"
IsPrivate="False"
IsProtected="False"
IsPublic="True"
IsSpecialName="False"
IsStatic="False"
Module="Generics.exe"
Name="Metod">
Name="Metod"
StepOver="False">
<DeclaringType>
<DebugType
BaseType="System.Object"
@ -211,14 +211,14 @@ namespace Debugger.Tests { @@ -211,14 +211,14 @@ namespace Debugger.Tests {
DeclaringType="Debugger.Tests.TestPrograms.GenericClass&lt;System.Int32,System.String&gt;"
FullName="Debugger.Tests.TestPrograms.GenericClass&lt;System.Int32,System.String&gt;.GenericMethod"
IsInternal="False"
IsMyCode="True"
IsPrivate="False"
IsProtected="False"
IsPublic="True"
IsSpecialName="False"
IsStatic="False"
Module="Generics.exe"
Name="GenericMethod">
Name="GenericMethod"
StepOver="False">
<DeclaringType>
<DebugType
BaseType="System.Object"
@ -276,14 +276,14 @@ namespace Debugger.Tests { @@ -276,14 +276,14 @@ namespace Debugger.Tests {
DeclaringType="Debugger.Tests.TestPrograms.GenericClass&lt;System.Int32,System.String&gt;"
FullName="Debugger.Tests.TestPrograms.GenericClass&lt;System.Int32,System.String&gt;.StaticMetod"
IsInternal="False"
IsMyCode="True"
IsPrivate="False"
IsProtected="False"
IsPublic="True"
IsSpecialName="False"
IsStatic="True"
Module="Generics.exe"
Name="StaticMetod">
Name="StaticMetod"
StepOver="False">
<DeclaringType>
<DebugType
BaseType="System.Object"
@ -341,14 +341,14 @@ namespace Debugger.Tests { @@ -341,14 +341,14 @@ namespace Debugger.Tests {
DeclaringType="Debugger.Tests.TestPrograms.GenericClass&lt;System.Int32,System.String&gt;"
FullName="Debugger.Tests.TestPrograms.GenericClass&lt;System.Int32,System.String&gt;.StaticGenericMethod"
IsInternal="False"
IsMyCode="True"
IsPrivate="False"
IsProtected="False"
IsPublic="True"
IsSpecialName="False"
IsStatic="True"
Module="Generics.exe"
Name="StaticGenericMethod">
Name="StaticGenericMethod"
StepOver="False">
<DeclaringType>
<DebugType
BaseType="System.Object"
@ -406,14 +406,14 @@ namespace Debugger.Tests { @@ -406,14 +406,14 @@ namespace Debugger.Tests {
DeclaringType="Debugger.Tests.TestPrograms.GenericStruct&lt;System.Int32,System.String&gt;"
FullName="Debugger.Tests.TestPrograms.GenericStruct&lt;System.Int32,System.String&gt;.Metod"
IsInternal="False"
IsMyCode="True"
IsPrivate="False"
IsProtected="False"
IsPublic="True"
IsSpecialName="False"
IsStatic="False"
Module="Generics.exe"
Name="Metod">
Name="Metod"
StepOver="False">
<DeclaringType>
<DebugType
BaseType="System.ValueType"
@ -471,14 +471,14 @@ namespace Debugger.Tests { @@ -471,14 +471,14 @@ namespace Debugger.Tests {
DeclaringType="Debugger.Tests.TestPrograms.GenericStruct&lt;System.Int32,System.String&gt;"
FullName="Debugger.Tests.TestPrograms.GenericStruct&lt;System.Int32,System.String&gt;.GenericMethod"
IsInternal="False"
IsMyCode="True"
IsPrivate="False"
IsProtected="False"
IsPublic="True"
IsSpecialName="False"
IsStatic="False"
Module="Generics.exe"
Name="GenericMethod">
Name="GenericMethod"
StepOver="False">
<DeclaringType>
<DebugType
BaseType="System.ValueType"
@ -536,14 +536,14 @@ namespace Debugger.Tests { @@ -536,14 +536,14 @@ namespace Debugger.Tests {
DeclaringType="Debugger.Tests.TestPrograms.GenericStruct&lt;System.Int32,System.String&gt;"
FullName="Debugger.Tests.TestPrograms.GenericStruct&lt;System.Int32,System.String&gt;.StaticMetod"
IsInternal="False"
IsMyCode="True"
IsPrivate="False"
IsProtected="False"
IsPublic="True"
IsSpecialName="False"
IsStatic="True"
Module="Generics.exe"
Name="StaticMetod">
Name="StaticMetod"
StepOver="False">
<DeclaringType>
<DebugType
BaseType="System.ValueType"
@ -601,14 +601,14 @@ namespace Debugger.Tests { @@ -601,14 +601,14 @@ namespace Debugger.Tests {
DeclaringType="Debugger.Tests.TestPrograms.GenericStruct&lt;System.Int32,System.String&gt;"
FullName="Debugger.Tests.TestPrograms.GenericStruct&lt;System.Int32,System.String&gt;.StaticGenericMethod"
IsInternal="False"
IsMyCode="True"
IsPrivate="False"
IsProtected="False"
IsPublic="True"
IsSpecialName="False"
IsStatic="True"
Module="Generics.exe"
Name="StaticGenericMethod">
Name="StaticGenericMethod"
StepOver="False">
<DeclaringType>
<DebugType
BaseType="System.ValueType"

48
src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/Metadata.cs

@ -150,168 +150,168 @@ namespace Debugger.Tests { @@ -150,168 +150,168 @@ namespace Debugger.Tests {
DeclaringType="Debugger.Tests.TestPrograms.Metadata"
FullName="Debugger.Tests.TestPrograms.Metadata.get_privateProperty"
IsInternal="False"
IsMyCode="True"
IsPrivate="True"
IsProtected="False"
IsPublic="False"
IsSpecialName="True"
IsStatic="False"
Module="Metadata.exe"
Name="get_privateProperty" />
Name="get_privateProperty"
StepOver="False" />
</Item>
<Item>
<MethodInfo
DeclaringType="Debugger.Tests.TestPrograms.Metadata"
FullName="Debugger.Tests.TestPrograms.Metadata.get_publicProperty"
IsInternal="False"
IsMyCode="True"
IsPrivate="False"
IsProtected="False"
IsPublic="True"
IsSpecialName="True"
IsStatic="False"
Module="Metadata.exe"
Name="get_publicProperty" />
Name="get_publicProperty"
StepOver="False" />
</Item>
<Item>
<MethodInfo
DeclaringType="Debugger.Tests.TestPrograms.Metadata"
FullName="Debugger.Tests.TestPrograms.Metadata.get_protectedProperty"
IsInternal="False"
IsMyCode="True"
IsPrivate="False"
IsProtected="True"
IsPublic="False"
IsSpecialName="True"
IsStatic="False"
Module="Metadata.exe"
Name="get_protectedProperty" />
Name="get_protectedProperty"
StepOver="False" />
</Item>
<Item>
<MethodInfo
DeclaringType="Debugger.Tests.TestPrograms.Metadata"
FullName="Debugger.Tests.TestPrograms.Metadata.get_internalProperty"
IsInternal="True"
IsMyCode="True"
IsPrivate="False"
IsProtected="False"
IsPublic="False"
IsSpecialName="True"
IsStatic="False"
Module="Metadata.exe"
Name="get_internalProperty" />
Name="get_internalProperty"
StepOver="False" />
</Item>
<Item>
<MethodInfo
DeclaringType="Debugger.Tests.TestPrograms.Metadata"
FullName="Debugger.Tests.TestPrograms.Metadata.get_staticProperty"
IsInternal="False"
IsMyCode="True"
IsPrivate="True"
IsProtected="False"
IsPublic="False"
IsSpecialName="True"
IsStatic="True"
Module="Metadata.exe"
Name="get_staticProperty" />
Name="get_staticProperty"
StepOver="False" />
</Item>
<Item>
<MethodInfo
DeclaringType="Debugger.Tests.TestPrograms.Metadata"
FullName="Debugger.Tests.TestPrograms.Metadata.privateMethod"
IsInternal="False"
IsMyCode="True"
IsPrivate="True"
IsProtected="False"
IsPublic="False"
IsSpecialName="False"
IsStatic="False"
Module="Metadata.exe"
Name="privateMethod" />
Name="privateMethod"
StepOver="False" />
</Item>
<Item>
<MethodInfo
DeclaringType="Debugger.Tests.TestPrograms.Metadata"
FullName="Debugger.Tests.TestPrograms.Metadata.publicMethod"
IsInternal="False"
IsMyCode="True"
IsPrivate="False"
IsProtected="False"
IsPublic="True"
IsSpecialName="False"
IsStatic="False"
Module="Metadata.exe"
Name="publicMethod" />
Name="publicMethod"
StepOver="False" />
</Item>
<Item>
<MethodInfo
DeclaringType="Debugger.Tests.TestPrograms.Metadata"
FullName="Debugger.Tests.TestPrograms.Metadata.protectedMethod"
IsInternal="False"
IsMyCode="True"
IsPrivate="False"
IsProtected="True"
IsPublic="False"
IsSpecialName="False"
IsStatic="False"
Module="Metadata.exe"
Name="protectedMethod" />
Name="protectedMethod"
StepOver="False" />
</Item>
<Item>
<MethodInfo
DeclaringType="Debugger.Tests.TestPrograms.Metadata"
FullName="Debugger.Tests.TestPrograms.Metadata.internalMethod"
IsInternal="True"
IsMyCode="True"
IsPrivate="False"
IsProtected="False"
IsPublic="False"
IsSpecialName="False"
IsStatic="False"
Module="Metadata.exe"
Name="internalMethod" />
Name="internalMethod"
StepOver="False" />
</Item>
<Item>
<MethodInfo
DeclaringType="Debugger.Tests.TestPrograms.Metadata"
FullName="Debugger.Tests.TestPrograms.Metadata.staticMethod"
IsInternal="False"
IsMyCode="True"
IsPrivate="True"
IsProtected="False"
IsPublic="False"
IsSpecialName="False"
IsStatic="True"
Module="Metadata.exe"
Name="staticMethod" />
Name="staticMethod"
StepOver="False" />
</Item>
<Item>
<MethodInfo
DeclaringType="Debugger.Tests.TestPrograms.Metadata"
FullName="Debugger.Tests.TestPrograms.Metadata.Main"
IsInternal="False"
IsMyCode="True"
IsPrivate="False"
IsProtected="False"
IsPublic="True"
IsSpecialName="False"
IsStatic="True"
Module="Metadata.exe"
Name="Main" />
Name="Main"
StepOver="False" />
</Item>
<Item>
<MethodInfo
DeclaringType="Debugger.Tests.TestPrograms.Metadata"
FullName="Debugger.Tests.TestPrograms.Metadata..ctor"
IsInternal="False"
IsMyCode="False"
IsPrivate="False"
IsProtected="False"
IsPublic="True"
IsSpecialName="True"
IsStatic="False"
Module="Metadata.exe"
Name=".ctor" />
Name=".ctor"
StepOver="True" />
</Item>
<Item>
<PropertyInfo

269
src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/Stepping.cs

@ -6,35 +6,118 @@ @@ -6,35 +6,118 @@
// </file>
using System;
using System.Diagnostics;
namespace Debugger.Tests.TestPrograms
{
public class Stepping
{
public static void Main()
[DebuggerStepThrough]
static void StepRoot()
{
System.Diagnostics.Debugger.Break();
System.Diagnostics.Debug.WriteLine("1"); // Step over external code
Sub(); // Step in internal code
Sub2(); // Step over internal code
IgnoredClass.StepLeft();
StepRight();
}
[DebuggerNonUserCode]
public class IgnoredClass {
public static void StepLeft() {}
}
public static void Sub()
{ // Step in noop
System.Diagnostics.Debug.WriteLine("2"); // Step in external code
System.Diagnostics.Debug.WriteLine("3"); // Step out
System.Diagnostics.Debug.WriteLine("4");
static void StepRight() {}
public class DefaultCtorClass {
public void Target() {}
}
public static int ShortProperty {
get {
return 1;
}
}
static int field = 1;
public static int FieldProperty {
get {
return
field;
}
}
[DebuggerNonUserCode]
static void ZigZag1()
{
try {
ZigZag2();
} catch (System.Exception) {
try {
ZigZag2();
} catch (System.Exception) {
}
}
}
static void ZigZag2()
{ // ... we end up here
System.Diagnostics.Debug.Write("ZigZag2");
ZigZag3(); // Stepping in here ...
}
[DebuggerNonUserCode]
static void ZigZag3()
{
throw new System.Exception();
}
[DebuggerNonUserCode]
static void CatchExcpetion()
{
try {
ThrowExcpetion();
} catch (System.Exception) {
}
}
public static void Sub2()
[DebuggerNonUserCode]
static void ThrowExcpetion()
{
System.Diagnostics.Debug.WriteLine("5");
throw new System.Exception();
}
static event EventHandler MyEvent;
[DebuggerNonUserCode]
static void Event1(object sender, EventArgs e) {}
static void Event2(object sender, EventArgs e) {}
[DebuggerNonUserCode]
static void Event3(object sender, EventArgs e) {}
static void Event4(object sender, EventArgs e) {}
public static void Main()
{
MyEvent += Event1;
MyEvent += Event2;
MyEvent += Event3;
MyEvent += Event4;
System.Diagnostics.Debugger.Break();
string theasnwer = 42.ToString();
StepRoot();
new DefaultCtorClass().Target();
int s = ShortProperty;
int f = FieldProperty;
CatchExcpetion();
ZigZag1();
MyEvent(null, EventArgs.Empty);
}
}
}
#if TEST_CODE
namespace Debugger.Tests {
using NUnit.Framework;
using Debugger.Wrappers.CorDebug;
using Debugger.Wrappers.MetaData;
public partial class DebuggerTests
{
[NUnit.Framework.Test]
@ -42,31 +125,72 @@ namespace Debugger.Tests { @@ -42,31 +125,72 @@ namespace Debugger.Tests {
{
StartTest("Stepping.cs");
ObjectDumpToString("NextStatement", process.SelectedStackFrame.NextStatement);
process.SelectedStackFrame.StepOver(); // Debugger.Break
ObjectDumpToString("NextStatement", process.SelectedStackFrame.NextStatement);
process.SelectedStackFrame.StepOver(); // Debug.WriteLine 1
ObjectDumpToString("NextStatement", process.SelectedStackFrame.NextStatement);
process.SelectedStackFrame.StepInto(); // Method Sub
ObjectDumpToString("NextStatement", process.SelectedStackFrame.NextStatement);
process.SelectedStackFrame.StepInto(); // '{'
ObjectDumpToString("NextStatement", process.SelectedStackFrame.NextStatement);
SourcecodeSegment start = process.SelectedStackFrame.NextStatement;
process.SelectedStackFrame.StepInto(); // Debug.WriteLine 2
ObjectDumpToString("NextStatement", process.SelectedStackFrame.NextStatement);
process.SelectedStackFrame.StepOut(); // Method Sub
ObjectDumpToString("NextStatement", process.SelectedStackFrame.NextStatement);
process.SelectedStackFrame.StepOver(); // Method Sub
ObjectDumpToString("NextStatement", process.SelectedStackFrame.NextStatement);
process.SelectedStackFrame.StepOver(); // Method Sub2
ObjectDumpToString("NextStatement", process.SelectedStackFrame.NextStatement);
foreach (bool jmcEnabled in new bool[] {true, true, false}) {
ObjectDump("Log", "Starting run with JMC=" + jmcEnabled.ToString());
process.SelectedStackFrame.SetIP(start.Filename, start.StartLine + 1, start.StartColumn);
process.Options.EnableJustMyCode = jmcEnabled;
process.Options.StepOverSingleLineProperties = true;
process.Options.StepOverFieldAccessProperties = true;
process.SelectedStackFrame.StepInto(); // 42.ToString()
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
if (jmcEnabled) {
process.SelectedStackFrame.StepInto(); // StepRoot
Assert.AreEqual("StepRight", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepOut();
process.SelectedStackFrame.StepOver(); // Finish the step out
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
} else {
process.SelectedStackFrame.StepInto(); // StepRoot
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
}
process.SelectedStackFrame.StepInto(); // Generated default constructor
Assert.AreEqual("Target", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepOut();
process.SelectedStackFrame.StepOver(); // Finish the step out
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepInto(); // ShortProperty
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
// TODO: Does not work for static
// process.SelectedStackFrame.StepInto(); // FieldProperty
process.SelectedStackFrame.StepOver(); // FieldProperty
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepInto(); // CatchExcpetion
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
if (jmcEnabled) {
process.SelectedStackFrame.StepInto(); // ZigZag1
process.SelectedStackFrame.StepOver();
process.SelectedStackFrame.StepOver();
Assert.AreEqual("ZigZag2", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepInto();
Assert.AreEqual("ZigZag2", process.SelectedStackFrame.MethodInfo.Name);
Assert.AreEqual(3, process.SelectedStackFrame.NextStatement.StartColumn);
process.SelectedStackFrame.StepOut();
process.SelectedStackFrame.StepOver(); // Finish the step out
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
} else {
process.SelectedStackFrame.StepInto(); // ZigZag1
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
}
process.SelectedStackFrame.StepInto(); // MyEvent
Assert.AreEqual("Event2", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepOut();
Assert.AreEqual("Event4", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepOut();
process.SelectedStackFrame.StepOver(); // Finish the step out
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
}
EndTest();
}
@ -82,32 +206,75 @@ namespace Debugger.Tests { @@ -82,32 +206,75 @@ namespace Debugger.Tests {
<ProcessStarted />
<ModuleLoaded>mscorlib.dll (No symbols)</ModuleLoaded>
<ModuleLoaded>Stepping.exe (Has symbols)</ModuleLoaded>
<ModuleLoaded>System.dll (No symbols)</ModuleLoaded>
<DebuggingPaused>Break</DebuggingPaused>
<NextStatement>Stepping.cs:16,4-16,40</NextStatement>
<Log>Starting run with JMC=True</Log>
<DebuggingPaused>SetIP</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<ModuleLoaded>System.dll (No symbols)</ModuleLoaded>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<NextStatement>Stepping.cs:17,4-17,44</NextStatement>
<ModuleLoaded>System.Configuration.dll (No symbols)</ModuleLoaded>
<ModuleLoaded>System.Xml.dll (No symbols)</ModuleLoaded>
<LogMessage>1\r\n</LogMessage>
<LogMessage>ZigZag2</LogMessage>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<LogMessage>ZigZag2</LogMessage>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<Log>Starting run with JMC=True</Log>
<DebuggingPaused>SetIP</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<LogMessage>ZigZag2</LogMessage>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<LogMessage>ZigZag2</LogMessage>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<Log>Starting run with JMC=False</Log>
<DebuggingPaused>SetIP</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<DebuggingPaused>StepComplete</DebuggingPaused>
<NextStatement>Stepping.cs:18,4-18,10</NextStatement>
<DebuggingPaused>StepComplete</DebuggingPaused>
<NextStatement>Stepping.cs:23,3-23,4</NextStatement>
<LogMessage>ZigZag2</LogMessage>
<LogMessage>ZigZag2</LogMessage>
<DebuggingPaused>StepComplete</DebuggingPaused>
<NextStatement>Stepping.cs:24,4-24,44</NextStatement>
<LogMessage>2\r\n</LogMessage>
<DebuggingPaused>StepComplete</DebuggingPaused>
<NextStatement>Stepping.cs:25,4-25,44</NextStatement>
<LogMessage>3\r\n</LogMessage>
<LogMessage>4\r\n</LogMessage>
<DebuggingPaused>StepComplete</DebuggingPaused>
<NextStatement>Stepping.cs:18,4-18,10</NextStatement>
<DebuggingPaused>StepComplete</DebuggingPaused>
<NextStatement>Stepping.cs:19,4-19,11</NextStatement>
<LogMessage>5\r\n</LogMessage>
<DebuggingPaused>StepComplete</DebuggingPaused>
<NextStatement>Stepping.cs:20,3-20,4</NextStatement>
<ProcessExited />
</Test>
</DebuggerTests>

Loading…
Cancel
Save