3

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

目前我正在努力解决 StepInto 的行为,而 StepOut 和 StepOver 似乎可以工作。

为了实现Just-My-Code步进,我正在调用SetJMCStatus模块加载。这很好用,让我只调试我的代码。

但是由于我将整个模块设置为 JMC,一些自动生成的代码开始发挥作用并破坏了单步执行。此类代码的一个示例可能是自动属性。

由于调试器正在执行 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,所以我不确定提供任何代码是否有意义......如果是这样,我将编辑问题,只需添加一条评论!

非常感谢您对主题的任何建议!

问候,

4

1 回答 1

1

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

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

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

于 2016-08-12T11:10:29.833 回答