我正在使用MDBG示例制作一个托管.NET调试器。
目前,我正在与StepInto行为作斗争,而StepOut和StepOver似乎有效。
为了实现Just-My-Code
步进,我在模块加载时调用SetJMCStatus
。这很好,并且允许我只调试代码。
但由于我将整个模块设置为JMC,一些自动生成的代码开始发挥作用,并破坏了它的运行。这类代码的一个例子可以是auto-property。
由于调试器正在执行Il指令,随着步骤的深入,我进入了自动生成的get_propertyName
和set_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,所以我不确定提供任何代码是否有意义。。。如果是,我会编辑这个问题,只需添加一条评论!
任何关于这个话题的建议都将不胜感激!
问候,
Mike Stall暗示了一个选项,您可以为整个模块设置JMC,然后当调试器步进器中断时,检查该方法是否可调试,如果不可调试,则禁用其JMC状态并重新运行步进器。(我不确定这是否会导致行为的改变,如果恢复步进器需要在再次进入之前退出。(
您可以通过只为具有可用pdb的模块设置JMC,并为应用了[DebuggerNonUserCode]
的类/方法禁用JMC(也许还有[DeggerHidden](来改进这一点。但是,与其枚举所有的类/方法并检查它们是否具有该属性,不如枚举自定义属性并返回(设置了tkType但没有设置tk的IMetaDataImport::EnumCustomAttributes,然后使用IMetaDataImport:GetCustomAttributeProps来获取其应用对象(。
如果[CompilerGenerated]
属性在方法级别应用,您可能可以对其执行类似的操作,但在类级别应用时会得到误报(编译器将其应用于迭代器和异步方法的状态机,但两者都可能有未生成的代码(。