调试器StepInto自动生成的代码和JMC问题

时间:2016-08-11 13:29:50

标签: c# cil mdbg imetadataimport

我正在使用MDBG示例制作托管.NET调试器。

目前我正在努力解决StepInto行为,而StepOut和StepOver似乎也有效。

要实现Just-My-Code步进,我在模块加载时调用SetJMCStatus。这很好,允许我调试我的代码。

但由于我将整个模块设置为JMC,因此一些自动生成的代码会起作用并破坏步入。此类代码的示例可以是auto-property。

由于调试器正在执行Il指令,因此我逐步进入自动生成的get_propertyNameset_propertyName方法,这些方法被标记为我的代码,因为它们是我的模块的一部分。

为了区分这些自动生成的代码和我的代码,我可以使用调试符号的存在,在自动生成的代码的情况下会丢失。然后我可以简单地将方法标记为不是我的代码,以便在步进期间跳过它。

问题是我不知道在步进过程中进入内部之前会自动生成哪些方法。当我进入一个没有调试符号的方法时,我可以将其标记为不我的代码,但为时已晚 - 调试器停在它不应该停止的地方。

从理论上讲,我可以使用IMetadataImport迭代我的模块方法,并在调试器启动时设置它们的JMCStatus,但它看起来很昂贵:

 foreach (var methodToken in mdbgModule.Importer.EnumerateAllMethodTokens()) {
                var func = mdbgModule.GetFunction(methodToken);
                    if (func.SymMethod == null)
                        func.CorFunction.JMCStatus = false;
            }

如果我只知道接下来会执行什么功能,那么我就可以设置它的状态并防止第一次进入自动生成的代码。

我坚持使用MDBG方法进行步进,而不是改变任何东西,只需要调用SetJMCStatus,所以我不确定提供任何代码是否合理......如果是这样,我会编辑问题,只需添加评论!

非常感谢任何关于主题的建议!

此致

1 个答案:

答案 0 :(得分:1)

Mike Stall hinted在一个选项中,您可以为整个模块设置JMC,然后在调试器步进器中断时,检查方法是否可调试,如果没有则禁用它的JMC状态并重新运行步进器。 (如果恢复步进器需要在再次进入之前退出,我不确定这是否会导致行为改变。)

您可以通过仅为具有可用pdb的模块设置JMC并通过为应用了[DebuggerNonUserCode]的类/方法禁用JMC(也可能是[DebuggerHidden])来改进。但是,不是枚举所有类/方法并检查它们是否具有该属性,而是枚举自定义属性并返回(IMetaDataImport::EnumCustomAttributes tkType设置但不是tk,然后使用IMetaDataImport::GetCustomAttributeProps来获取应用的东西到)。

如果它在方法级别应用,您可以使用[CompilerGenerated]属性执行类似操作,但在类级别应用时会得到误报(编译器将其应用于迭代器和异步的状态机)方法,但两者都可能有非生成的代码。)