DbgEng 扩展 DLL 剖析

DbgEng 扩展 DLL 导出多个回调函数,其中一些可能是扩展命令的实现。

这些扩展 DLL 由 调试器引擎加载,并且可以在 Microsoft Windows 上执行用户模式或内核模式调试时提供额外的功能或任务自动化。

如果执行了 Windows 调试工具的完整安装,可以在安装目录的 sdk\samples\exts 子目录中找到名为“exts”的示例 DbgEng 扩展。

扩展命令

扩展 DLL 可以导出用于执行扩展命令的任意数量的函数。 每个函数在 .def 文件中明确声明为导出,其名称必须全部由小写字母组成。

用于实现扩展命令的函数必须与原型 PDEBUG_EXTENSION_CALL 匹配。

这些函数是根据标准 C++ 约定命名的,但不允许使用大写字母。 导出的函数名称和扩展命令名称相同,但扩展命令以感叹号 (!) 开头。 例如,将 myextension.dll 加载到调试器中,然后在调试器命令窗口中键入 !stack 时,调试器将在 myextension.dll 中查找名为 stack 的导出函数。

如果尚未加载 myextension.dll,或者如果其他扩展 DLL 中可能有同名的其他扩展命令,则可以在调试器命令窗口中键入 !myextension.stack ,以指示该 DLL 中的扩展 DLL 和扩展命令。

其他导出的函数

DbgEng 扩展 DLL 必须导出 DebugExtensionInitialize。 这会在加载 DLL 时调用,以初始化 DLL。 DLL 可以使用它初始化全局变量。

扩展 DLL 可以导出 DebugExtensionUninitialize。 如果导出此项,则会在卸载扩展 DLL 之前调用。 DLL 在卸载前可能会使用它进行清理。

扩展 DLL 可以导出 DebugExtensionNotify。 如果导出此项,则会在会话开始或结束以及目标启动或停止执行时调用它。 这些通知也会提供给向客户端注册的 IDebugEventCallbacks 对象。

扩展 DLL 可以导出 KnownStructOutput。 如果导出此项,将在加载 DLL 时调用它。 此函数返回 DLL 知道如何在单行上打印的结构列表。 稍后可能会调用它来格式化这些结构的实例以供打印。

用于加载 DbgEng 扩展 DLL 的引擎过程

加载扩展 DLL 时,引擎按以下顺序调用回调函数:

  1. DebugExtensionInitialize 被调用以便扩展 DLL 可以初始化。

  2. 如果导出,则在引擎有活动会话时调用 DebugExtensionNotify,如果会话已挂起且可访问,则再次调用。

  3. 如果导出,则调用 KnownStructOutput 以请求 DLL 知道如何在单行上打印的结构列表。

有关如何使用调试器加载和卸载扩展 DLL 的信息,请参阅加载调试器扩展 DLL,并参阅 使用调试器扩展命令了解有关执行扩展命令的信息。

调试器引擎将在调用扩展 DLL 时放置 try / except 块。 这会保护引擎免受扩展代码中某些类型的 Bug 的影响;但是,由于扩展调用在与引擎相同的线程中执行,它们仍可能导致引擎崩溃。