Windows 系统下的调试

本文档介绍了如何在 Windows 上使用 Visual Studio IDE 调试基于 Gecko 的应用程序,例如 Firefox、Thunderbird 和 SeaMonkey。

如果 VS 和您的 Gecko 应用程序在您在调试器下启动应用程序后不久就挂起,请参阅 加载调试符号的问题

启动调试器的方法

首先,需要安装 Visual Studio 扩展才能跟踪创建的子进程。一般来说,即使在非 e10s 模式下,Firefox 也不会直接启动主进程,而是通过启动程序进程启动它。这意味着 Visual Studio 只会附加到它找到的第一个进程,并且不会命中任何断点(甚至会通知您无法找到其位置)。Microsoft 子进程调试增强工具 允许自动附加到子进程,例如 Web 内容进程、GPU 进程等。通过转到“调试 > 其他调试目标 > 子进程调试设置”中的配置菜单并勾选复选框来启用它。

如果您已按照 在 Windows 上构建 Firefox 中的步骤操作,并且拥有本地调试版本,则可以 **从同一命令行执行此命令。**

./mach run --debug

它将打开 Visual Studio 并配置 Firefox 的运行选项。然后,您可以 **单击“启动”按钮** 运行 Firefox,它已附加到调试器中。

或者,如果您已通过 ./mach build-backend -b VisualStudio 生成了 Visual Studio 解决方案,则打开此解决方案允许您直接在调试器中运行 firefox.exe。要将其设置为启动项目,请右键单击该项目并选择 设为启动项目。如果是这种情况,它将显示为粗体。断点保留在每次运行中,这可能是调试启动问题的好方法。

**运行程序直到遇到断言。** 您将收到一个对话框,询问您是否要调试。点击“取消”。MSDEV IDE 将启动并加载断言发生的文件。这也会在可执行文件的目录中默认创建一个 Visual Studio Mozilla 项目。

**将调试器附加到现有的 Mozilla 进程。** 在 Visual Studio 中,选择调试 > 附加到进程。如果您想调试内容进程,您可以 **将鼠标悬停在** 您要调试的页面选项卡上,这将显示 pid。然后,您可以从“附加到进程”打开的对话框中选择该进程。您可以打开 about:processes 以查看所有子进程的 pid,包括选项卡,以及 GPU、网络等。有关更多信息,请参阅 使用 Visual Studio 调试器附加到正在运行的进程

**使用调试器启动 MSIX 安装的 Firefox。** 在 Visual Studio 中,选择调试 -> 其他调试目标 -> 调试已安装的应用程序包。在对话框中,选择要调试的已安装 Firefox 包,然后单击“启动”。

调试发布版和夜间构建

请参阅 使用 Mozilla 符号服务器源服务器 的步骤。

为 Firefox 创建 Visual Studio 项目

请参阅 此处

更改/设置要调试的可执行文件

要更改或设置要调试的可执行文件,请转到项目 > 属性 > 调试 > 命令。(截至 Visual Studio 2022。)

它应该显示您正在调试的可执行文件。如果为空或不正确,请手动添加可执行文件的正确路径。

命令行参数和环境变量

要更改或设置命令行选项,请转到项目 > 属性 > 调试 > 命令参数。

一些常见的选项包括浏览器启动后要打开的文件的 URL、启动配置文件管理器或选择配置文件。您还可以将控制台输出重定向到文件(例如添加“> filename.txt”,不带引号)。

自定义调试器的变量值视图

您可以自定义 Visual Studio 在变量视图中显示类的方式。默认情况下,VS 显示“{…}”,您需要单击加号图标展开成员。您可以更改此行为,并使 Visual Studio 显示您想要的任何数据成员,以任何顺序,并以您喜欢的格式显示,而不是仅仅显示“{…}”。

您需要在 toolkit/library 下找到一个名为“gecko.natvis”的文件。该文件包含类型列表及其在调试器中应如何显示的方式。它是 XML 文件,练习几次后,您应该能够上手。

要详细了解该文件,请参阅 使用 Natvis 框架在调试器中创建 C++ 对象的自定义视图

该文件已经包含了许多条目,可以简化您的工作,例如对几种字符串类型的支持。如果需要添加自定义类型,或出于调试目的想要更改现有条目,可以轻松编辑该文件。为了方便起见,它包含在所有生成的 Visual Studio 项目中,如果您在 Visual Studio 中编辑并保存它,它将立即获取更改。

在 Visual Studio 中处理多个进程

关闭“当一个进程中断时中断所有进程”以单步执行单个进程。

关闭“当一个进程中断时中断所有进程”会在“调试”菜单中添加“单步进入当前进程”、“单步执行当前进程”和“单步跳出当前进程”。

要使用其他进程暂停状态单步执行单个进程

  • 打开“当一个进程中断时中断所有进程”

  • 命中一个断点,该断点会停止所有进程

  • 关闭“当一个进程中断时中断所有进程”

  • 现在使用“单步进入当前进程”将使其他进程停止,并且只推进当前进程。

获取 stdout 和其他 FILE 句柄

在 Visual Studio 中的命令窗口中运行以下命令将返回 stdout 的值,该值可用于各种调试方法(例如 nsGenericElement::List),这些方法采用 FILE* 参数

Debug.EvaluateStatement {,,msvcr80d}(&__iob_func()[1])

(或者,您可以在立即窗口中评估 {,,msvcr80d}(&__iob_func()[1])

类似地,您可以使用 fopen 打开磁盘上的文件

>Debug.EvaluateStatement {,,msvcr80d}fopen("c:\\123", "w")
0x10311dc0 { ..snip.. }
>Debug.EvaluateStatement ((nsGenericElement*)0x03f0e710)->List((FILE*)0x10311dc0, 1)
<void>
>Debug.EvaluateStatement {,,msvcr80d}fclose((FILE*)0x10311dc0)
0x00000000

请注意,在刷新或关闭文件句柄之前,您可能看不到调试输出。

禁用断言

基本上有两种方法可以禁用断言。一种需要设置环境变量,而另一种仅影响内存中当前正在运行的程序实例。

环境变量

有一个环境变量可以禁用断言的中断。这通常是您设置它的方式

set XPCOM_DEBUG_BREAK=warn

环境变量除了 warn 之外还采用其他值,有关详细信息,请参阅 XPCOM_DEBUG_BREAK

请注意,与 Unix 不同,Windows 的默认值不是 warn,而是弹出对话框。要为 Visual Studio 设置环境变量,请使用项目 > 属性 > 调试 > 环境,然后单击小框。然后使用

XPCOM_DEBUG_BREAK=warn

修改运行代码

您通常不需要这样做(只需退出应用程序,设置上面描述的环境变量,然后重新运行它)。并且这可能是 **危险的**(例如 **损坏您的硬盘并损坏您的系统**)。因此,除非您对此感到满意,否则请不要这样做。**您已收到警告!**

可以更改内存中的中断代码(导致您进入调试器)为 NOP(无操作)。

您可以通过在调试器中运行程序直到遇到断言来执行此操作。您应该会看到一些汇编代码。一条汇编代码指令读取“int 3”。检查该行的内存地址。现在打开内存视图。在内存视图中键入/复制/拖动“int 3”的内存地址以使其更新该内存部分。将内存的值更改为“90”,关闭内存视图并点击“F5”继续。

在未附加调试器的情况下自动处理断言

当断言发生且没有附加调试器时,会运行一个小的辅助应用程序(`windbgdlg.exe </En/Automatically_Handle_Failed_Asserts_in_Debug_Builds>`__)。如果您对其进行配置,该应用程序可以自动选择对“是否要调试”对话框的响应,而不是提示您,有关更多信息,请参阅`windbgdlg.exe </En/Automatically_Handle_Failed_Asserts_in_Debug_Builds>`__。

调试优化构建

为了有效地调试优化构建,您应该启用调试信息,这实际上会将调试符号保留在优化代码中,以便您仍然可以设置断点等。由于代码已优化,因此单步执行代码有时会在调试器跳过某些内容时带来一些小惊喜。

您需要确保此配置参数已设置

ac_add_options --enable-debug

您还可以选择包含或排除特定模块。

控制台调试

当从内容进程打印到 STDOUT 时,控制台消息不会显示在 Windows 上。一种查看它的方法是简单地禁用 e10s(./mach run --disable-e10s),但为了在启用 e10s 的情况下进行调试,可以运行

./mach run ... 2>&1 | tee

也可能需要禁用内容沙箱(MOZ_DISABLE_CONTENT_SANDBOX=1 ./mach run ...)。

同时运行两个 Mozilla 实例

您可以通过使用 -P profile_name 命令行参数指定要使用的配置文件来同时运行两个 Mozilla 实例(例如调试和优化)。

调试 JavaScript

您可以使用来自 nsXPConnect.cpp 的辅助函数来检查和修改 MSVS 调试器中 JavaScript 代码的状态。

例如,要将当前 JavaScript 堆栈打印到 stdout,请在立即窗口中评估此内容

{,,xul}DumpJSStack()

Visual Studio 会在快速监视窗口中显示某些内容,但不会显示堆栈,您必须在操作系统控制台中查找输出。

此外,此神奇命令仅在 VS 堆栈上有 JS 时才有效。

调试 minidump

请参阅 调试 minidump

Windows 7 SP1 x64 上的事后调试问题?

如果您尝试使用 NS_DebugBreak 等在 64 位 Windows 7 上执行事后调试,但在您尝试继续调试时程序崩溃并出现访问冲突,则您可能遇到了与 AVX 支持相关的 Windows 错误。有关更多详细信息,包括解决方法,请参阅 此博文此 social.msdn 线程。(以防万一这些链接失效,解决方法是从

bcdedit /set xsavedisable 1

提升的命令提示符中执行以禁用 AVX 支持。)

有技巧吗?

如果您认为自己知道一个很酷的 Mozilla 调试技巧,请随时与 #developers 讨论,然后在此处发布。