diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Module.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Module.cs index 28e697b10f..233c509ef0 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Module.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Module.cs @@ -172,6 +172,37 @@ namespace Debugger symReader = metaData.GetSymReader(fullPath, null); JMCStatus = SymbolsLoaded; + + FindNonUserCode(); + } + + /// + /// Finds all classes and methods marked with DebuggerNonUserCode attribute + /// and it marks them for JMC so that they are not stepped into + /// + void FindNonUserCode() + { + if (this.SymbolsLoaded) { + 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") + { + if (ca.Owner >> 24 == 0x02) { // TypeDef + ICorDebugClass2 corClass = corModule.GetClassFromToken(ca.Owner).CastTo(); + corClass.SetJMCStatus(0 /* false */); + this.Process.TraceMessage("Class {0} marked as non-user code", metaData.GetTypeDefProps(ca.Owner).Name); + } + if (ca.Owner >> 24 == 0x06) { // MethodDef + ICorDebugFunction2 corFunction = corModule.GetFunctionFromToken(ca.Owner).CastTo(); + corFunction.SetJMCStatus(0 /* false */); + MethodProps methodProps = metaData.GetMethodProps(ca.Owner); + this.Process.TraceMessage("Function {0}.{1} marked as non-user code", metaData.GetTypeDefProps(methodProps.ClassToken).Name, methodProps.Name); + } + } + } + } } public void ApplyChanges(byte[] metadata, byte[] il) diff --git a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Debugger.Tests.csproj b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Debugger.Tests.csproj index 95740f7c88..71f83b60a0 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Debugger.Tests.csproj +++ b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Debugger.Tests.csproj @@ -26,7 +26,7 @@ DEBUG;TRACE;TEST_CODE - TRACE + TRACE;TEST_CODE diff --git a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebuggerAttributes.cs b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebuggerAttributes.cs index 7a497e0e6b..aa616d1ea5 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebuggerAttributes.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebuggerAttributes.cs @@ -17,6 +17,7 @@ namespace Debugger.Tests.TestPrograms System.Diagnostics.Debug.WriteLine("Start"); System.Diagnostics.Debugger.Break(); Internal(); + IgnoredClass.Internal(); System.Diagnostics.Debug.WriteLine("End"); } @@ -25,11 +26,22 @@ namespace Debugger.Tests.TestPrograms { System.Diagnostics.Debug.WriteLine("Internal"); } + + [DebuggerNonUserCode] + public class IgnoredClass + { + public static void Internal() + { + System.Diagnostics.Debug.WriteLine("Internal"); + } + } } } #if TEST_CODE namespace Debugger.Tests { + using NUnit.Framework; + using Debugger.Wrappers.CorDebug; using Debugger.Wrappers.MetaData; public partial class DebuggerTests @@ -38,17 +50,13 @@ namespace Debugger.Tests { public void DebuggerAttributes() { StartTest("DebuggerAttributes.cs"); - process.SelectedStackFrame.StepOver(); + process.SelectedStackFrame.StepInto(); - Module module = process.SelectedStackFrame.MethodInfo.Module; - foreach(ModuleRefProps mRef in module.MetaData.EnumModuleRefProps()) { - - } - uint typeRef = module.MetaData.FindTypeRef(0, "System.Diagnostics.DebuggerStepThroughAttribute"); - foreach(CustomAttributeProps ca in module.MetaData.EnumCustomAttributeProps(0, 0)) { - MemberRefProps memProps = module.MetaData.GetMemberRefProps(ca.Type); - TypeRefProps typeDefProps = module.MetaData.GetTypeRefProps(memProps.DeclaringType); - } + process.SelectedStackFrame.StepInto(); + Assert.AreEqual(process.SelectedStackFrame.MethodInfo.Name, "Main"); + process.SelectedStackFrame.StepInto(); + Assert.AreEqual(process.SelectedStackFrame.MethodInfo.Name, "Main"); + EndTest(); } } @@ -68,8 +76,10 @@ namespace Debugger.Tests { Start\r\n Break StepComplete + Internal\r\n StepComplete Internal\r\n + StepComplete End\r\n