gpt4 book ai didi

.net - 编写.NET互操作调试器

转载 作者:行者123 更新时间:2023-12-01 08:15:07 27 4
gpt4 key购买 nike

我正在开发一个用户模式(Ring3)代码级调试器。它还应支持.NET可执行文件的本机(x86)调试。基本上,我需要执行以下操作:

1).NET在隐身模式下加载某些模块,而没有LOAD_DLL_DEBUG_EVENT,并且即使没有可能获得可执行文件的名称也经常加载。我需要通知;

2)我还想在每次JIT编译器编译方法时都收到通知;

3)对于给定的CIL方法,我需要相应的本机CPU命令的地址;

4)堆栈遍历(托管堆栈帧的解码)也将不胜感激。

(当然,稍后还会有更多问题)。解决方案必须独立于.NET版本。 Microsoft提供了一个.NET调试API,可以解决问题1(部分),3和4;而.NET概要分析API可以解决2。

不幸的是,我在互操作模式下的调试器和.NET API不能一起使用。我已经有了一个具有断点,内存管理等功能的可靠且快速的调试引擎。我的程序是简化的单线程应用程序。在逐步模式下,它可以以每秒500.000个命令的速度跟踪,分析和协议调试后的代码。

微软的解决方案是完全不同的。 .NET调试器是一个聪明的野兽。如果要求我编写托管调试器,那将是我的首选。它从不挂起Debuggee,而只是暂停.NET执行,因此可以在Debuggee的上下文中调用mscoree和co。,它们可以完全访问内部结构。为了进行通信,它在Debuggee中创建了一个附加线程,在Debugger中创建了另一个线程。 (并且Continue()用于未处理的异常回调必须从另一个线程发送!)

对我来说,这意味着对我的代码进行大量更改,无休止的关键部分,信号量,共享内存和死锁。我不能使用内存断点。如果Debuggee发狂,则可能会影响助手DLL。在Debuggee上下文中执行可能还意味着对调试器应用程序的影响太大。

有没有一种非侵入性的,与版本无关的方法来解决列出的问题?

奥莉

最佳答案

很高兴看到其他人对编写.Net调试工具感兴趣!我认为简短的答案是Microsoft没有支持您要完成的任务的解决方案。当我们朝着这个方向发展时,我们还没有到那儿。在三个条件中:支持的,非侵入性的,与版本无关的,您将需要在某种程度上牺牲其中至少一个。

这些是您每个请求想到的一些选项:

1).NET在隐身模式下加载某些模块,而没有LOAD_DLL_DEBUG_EVENT,并且即使没有可能获得可执行文件的名称也经常加载。我需要通知;

a)通过我们的分析API注册分析器可以提供此通知。您将略微牺牲非侵入性目标,因为这需要在调试对象内部加载您自己的模块。但是,对于诸如此类的轻量级通知,您可能并没有过多地干扰状态。

b)使用ICorDebug API进行附加(如您所注意到的)可以从进程外提供此通知。但是,从CLR版本4开始的调试器启动了自己的本机调试事件循环,该循环往往无法与现有的本机调试基础结构很好地啮合。在Visual Studio中可以看到对混合模式调试的支持,但是它非常脆弱,非常复杂,我们通常不建议任何人将其用于自己的调试工具(http://blogs.msdn.com/b /jmstall/archive/2007/01/10/dont-write-an-interop-debugger.aspx)。即使您围绕它设计了一个完整的解决方案,您也会发现许多本机调试功能不再可用,调试模型更具侵入性,并且您的性能可能会下降。我认为您已经意识到这对您而言不可行,而只是在其他人也考虑类似情况时将其包括在内。

c)使用不受支持的技术,例如在CLR中找到一个位置来安装断点,或匹配windbg + sos的行为。当然,如果您这样做了,您的解决方案可能就不会具有版本适应性,并且没有人可以正式提供有关其工作方式的任何说明,但是有些工具编写者还是会这样做。

2)我还想在每次JIT编译器编译方法时都收到通知;

a)再次您注意到,分析API可以为您提供此回调。该选择牺牲了少量的非侵入性。

b)使用不受支持的技术(断点或与windbg / sos匹配的行为),您可能会提取此信息。与以前相同的警告。

c)仅出于完整性考虑,这里不是ICorDebug API的选项-代码被Jitted时没有回调。

3)对于给定的CIL方法,我需要相应的本机CPU命令的地址;

a)探查器API提供了一种合适的方法http://msdn.microsoft.com/en-us/library/ms231070.aspx,其代价是必须在debuggee进程内加载自己的dll。

b)从CLR 4.0版开始,ICorDebug确实提供了可以实现此目的的非侵入式调试选项。它与Visual Studio中的转储调试使用的支持相同。这个新模型与以前的ICorDebug支持非常不同,因为它完全放弃了对调试对象执行的控制,甚至不需要运行中的流程。要使用它,您将实现ICorDebugDataTarget接口,该接口是Read / WriteProcessMemory和Get / SetThreadContext的简单包装。如果您想要一个完全非侵入式的调试模型,则实现WriteProcessMemory和SetThreadContext是可选的。在较高级别,您可以通过以下方式使用此模型:

  • CLRCreateInstance(http://msdn.microsoft.com/zh-cn/library/dd537633.aspx)为您提供了ICLRDebugging接口
  • ICLRDebugging::OpenVirtualProcess(http://msdn.microsoft.com/zh-cn/library/dd537649.aspx)转换ICorDebugDataTarget-> ICorDebugProcess
  • 您可以使用ICorDebugProcess接口,类似于从ICorDebug::CreateProcess获取该接口时的用法,但是不会触发回调,也不会执行侵入性操作,例如创建断点,单步执行,函数求值等。 。 将工作。所有检查API(例如获取CIL方法的本机代码)将像以前一样工作。

  • 有关如何工作的更多信息,提供了mdbg 4.0版的源代码,并包括转储调试(http://www.microsoft.com/downloads/en/details.aspx?FamilyID=ce94e626-c43d-419c-8538-173f6a042ef5 )。总体而言,此方法受支持并且是非侵入性的,但是仅适用于.Net v4.0。

    c)与以前一样,不受支持的技术可以提取数据,类似于sos内部进行的操作。

    4)堆栈遍历(托管堆栈帧的解码)也将不胜感激。为简便起见,此游戏的播放方式与第3点类似。探查器和调试API均提供堆栈遍历功能。

    总而言之,我认为最好的向后兼容解决方案是在禁用大多数事件的情况下加载非常轻量级的探查器(或进入不受支持的调试器黑客地带)。将来,您可能最终想要通过OpenVirtualProcess获得的非侵入性调试API。虽然目前尚不支持通知(并且我无法保证将来会提供任何功能),但这是我所看到的。希望能有所帮助,如果您需要进一步深入研究特定的选项,我们可以做到。我知道我在这里偷了很多东西。

    谢谢,
    -诺亚

    关于.net - 编写.NET互操作调试器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5507000/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com