原文链接:https://developer.chrome.com/native-client/devguide/devcycle/debugging
注意:已针对ChromeOS以外的平台公布了此处所述技术的弃用。
请访问我们的 迁移指南 了解详情。
调试
本文档介绍了可用于调试,监视和测量应用程序性能的工具和技术。
诊断信息
使用任务管理器查看流程统计信息
您可以使用Chrome的任务管理器显示有关Native Client应用程序的信息:
- 单击菜单图标并选择“ 工具”>“任务管理器”,打开“任务管理器”。
- 出现“任务管理器”窗口时,请验证显示内存信息的列是否可见。如果不是,请右键单击标题行,然后从显示的弹出菜单中选择内存项。
运行Native Client应用程序的浏览器窗口至少有两个与之关联的进程:应用程序顶层的进程(管理页面的呈现进程,包括其HTML和JavaScript)以及Native Client模块的每个实例的一个或多个进程嵌入在页面中(每个进程从一个nexe或pexe文件运行本机代码)。顶级进程随应用程序的图标一起显示,并以文本“Tab:”开头。将显示一个Native Client进程,其中包含Chrome扩展程序图标(拼图游戏部分),并以文本“Native Client module:”开头,后跟其清单文件的URL。
从任务管理器中,您可以查看与Native Client应用程序关联的所有进程的更改内存分配。每个进程都有自己的内存占用。您还可以看到渲染率显示为每秒帧数(FPS)。请注意,渲染帧的计算可以在任何过程中执行,但渲染本身总是在顶级应用程序进程中完成,因此请在那里查找渲染率。
控制Native Client错误和警告消息的级别
Native Client将警告和错误消息输出到stdout和stderr。您可以通过设置以下环境变量来增加Native Client的诊断输出量:
NACL_PLUGIN_DEBUG=1
NACL_SRPC_DEBUG=[1-255]
(使用更高的数字以获得更详细的调试输出)NACLVERBOSITY=[1-255]
基本调试
将消息写入JavaScript控制台
您可以使用Pepper消息传递系统中的PostMessage()
调用将C / C ++代码中的消息发送到JavaScript 。当JavaScript代码收到消息时,其消息事件处理程序可以调用console.log()将消息写入Chrome的Developer Tools中的JavaScript 控制台。
使用printf进行调试
您的C / C ++代码可以通过直接调用fprintf()或使用这样的封面函数对stdout和stderr执行内联printf调试:
#include <stdio.h>
void logmsg(const char* pMsg){
fprintf(stdout,"logmsg: %s\n",pMsg);
}
void errormsg(const char* pMsg){
fprintf(stderr,"logerr: %s\n",pMsg);
}
使用Chrome的stdout和stderr Streams
默认情况下,stdout和stderr将出现在Chrome的stdout和stderr流中,但它们也可以重定向到日志文件。(请参阅下一节。)在Mac和Linux上,从终端启动Chrome会使stderr和stdout出现在该终端中。如果您以这种方式启动Chrome,请确保它不会附加到现有实例。一种简单的方法是将新目录作为用户数据目录(chrome --user-data-dir=<newdir>
)传递给chrome 。
将输出重定向到日志文件
您可以通过设置以下环境变量将stdout和stderr重定向到输出文件:
NACL_EXE_STDOUT=c:\nacl_stdout.log
NACL_EXE_STDERR=c:\nacl_stderr.log
还有另一个变量,NACLLOG
可用于重定向Native Client的内部生成的消息。默认情况下,此变量设置为stderr; 您可以通过设置变量将这些消息重定向到输出文件,如下所示:
NACLLOG=c:\nacl.log
注意:如果你设置的NACL_EXE_STDOUT
,NACL_EXE_STDERR
或 NACLLOG
变量输出重定向到一个文件,你必须与运行Chrome的--no-sandbox
标志。您还必须小心每个变量指向不同的文件。
记录对Pepper接口的调用
您可以通过在启动时将以下标志传递给Chrome来记录模块所做的所有Pepper调用:
--vmodule=ppb*=4 --enable-logging=stderr
该vmodule
标志告诉Chrome记录对以“ppb”开头的C Pepper接口的所有调用(即,浏览器实现的接口以及模块调用的接口)。该enable-logging
标志告诉Chrome将调用记录到stderr。
使用Visual Studio进行调试
如果在Windows平台上进行开发,则可以使用Native Client Visual Studio加载项来编写和调试代码。该加载项定义了新的项目平台,使您可以在两种不同的模式下运行模块:作为Pepper插件和Native Client模块。作为Pepper插件运行时,您可以使用内置的Visual Studio调试器。作为Native Client模块运行时,Visual Studio将为您启动nacl-gdb实例并将其链接到正在运行的代码。
使用nacl-gdb进行调试
Native Client SDK包含一个命令行调试器,可用于调试Native Client模块。调试器是基于GNU调试器GDB,并且位于pepper_<version>/toolchain/<platform>_x86_newlib/bin/x86_64-nacl-gdb
(其中 <平台>是您的开发机器的平台:win
,mac
,或 linux
)。
请注意,相同的GDB副本可用于调试任何NaCl程序,无论是使用newlib还是glibc为x86-32,x86-64或ARM构建。在SDK中, i686-nacl-gdb
是别名x86_64-nacl-gdb
,newlib
而且glibc
工具链都包含相同版本的GDB。
调试PNaCl pexes(Pepper 35或更高版本)
如果要使用GDB调试使用PNaCl工具链编译的程序,则必须在运行 之前获得pexe的副本pnacl-finalize
。该pnacl-finalize
工具将LLVM bitcode转换为稳定的PNaCl bitcode格式,但它也删除了我们调试所需的调试元数据。在本节中,我们将为LLVM bitcode文件提供.bc
文件扩展名,并为PNaCl bitcode文件提供.pexe
文件扩展名。实际的扩展名无关紧要,但它有助于区分这两种类型的文件。
注意,与pexe的最终副本不同,未最终化的调试副本不被认为是稳定的。这意味着Pepper N SDK创建的PNaCl应用程序的调试副本仅保证与匹配的Chrome版本N一起运行。如果调试bitcode pexe的版本与Chrome的版本不匹配,则翻译过程可能会失败,并且您将在JavaScript控制台中看到错误消息。
此外,请确保您传递的-g
编译选项 ,以pnacl-clang
使生成的调试信息。您可能还想省略-O2
编译时和链接时选项,否则GDB在调试时可能无法打印变量的值(这对于PNaCl / LLVM工具链而言比GCC更有问题)。
一旦构建了pexe的非稳定调试副本,请在应用程序的清单文件中列出该副本的URL:
{
"program": {
"portable": {
"pnacl-translate": {
"url": "release_version.pexe",
"optlevel": 2
},
"pnacl-debug": {
"url": "debug_version.bc",
"optlevel": 0
}
}
}
}
将debug_version.bc
和nmf
文件复制到本地Web服务器提供文件的位置。
当您运行Chrome时--enable-nacl-debug
,Chrome会翻译并运行debug_version.bc
而不是release_version.pexe
。加载调试版本后,即可运行nacl-gdb
是否将包含调试URL的NMF文件发布到发布Web服务器,由您决定。避免发布调试URL的一个原因是,它只能保证适用于与SDK版本匹配的Chrome版本。可能已--enable-nacl-debug
打开该标志的开发人员 最终可能会加载您的应用程序的调试副本(可能会也可能不会,这取决于他们的Chrome版本)。
调试PNaCl pexes(使用较旧的Pepper工具链)
如果要使用GDB调试使用PNaCl工具链编译的程序,则必须将pexe
文件转换为nexe
。(如果您使用的是GCC工具链,或者您使用的是35或更高版本的辣椒,则可以跳过此步骤。)
- 首先,确保你传递的
-g
编译选项,以pnacl-clang
使生成的调试信息。您可能还想省略-O2
编译时和链接时选项。 -
其次,用于
pnacl-translate
将您转换pexe
为一个或多个nexe
文件。例如:nacl_sdk/pepper_<version>/toolchain/win_pnacl/bin/pnacl-translate \ --allow-llvm-bitcode-input hello_world.pexe -arch x86-32 \ -o hello_world_x86_32.nexe nacl_sdk/pepper_<version>/toolchain/win_pnacl/bin/pnacl-translate \ --allow-llvm-bitcode-input hello_world.pexe -arch x86-64 \ -o hello_world_x86_64.nexe
为此,请使用
pexe
由其生成的非最终文件pnacl-clang
,而不是pexe
由其生成的文件pnacl-finalize
。后者pexe
调试信息已被删除。该选项--allow-llvm-bitcode-input
告诉pnacl-translate
接受未定型pexe
。 -
替换
nmf
清单文件指向你的pexe
文件,一个指向nexe
文件。对于nexe
上面的示例文件名,新nmf
文件将包含: -
更改{ "program": { "x86-32": {"url": "hello_world_x86_32.nexe"}, "x86-64": {"url": "hello_world_x86_64.nexe"}, } }
<embed>
要使用的HTML元素type="application/x-nacl"
而不是type="application/x-pnacl"
。 - 将
nexe
和nmf
文件复制到本地Web服务器提供文件的位置。
注意:如果您知道Chrome是否在系统上使用x86-32或x86-64版本的NaCl沙箱,则可以将 pexe
一次转换为单个x86-32或x86-64 nexe
。否则,您可能会发现 如上所述pexe
将两种nexe
格式转换为更容易。
运行nacl-gdb
在开始使用nacl-gdb之前,请确保您可以构建模块并正常运行应用程序。这将验证您是否已创建所有必需的应用程序部件(.html,.nmf和.nexe文件,共享库等),您的服务器可以访问这些资源,以及您是否已正确配置Chrome以运行应用。以下说明假定您使用本地服务器来运行您的应用程序; 这样做的一个好处是,您可以检查Web服务器输出以确认您的应用程序正在加载正确的资源。但是,有些人更喜欢将其应用程序作为解压缩的扩展运行,如运行本机客户端应用程序中所述。
按照以下说明使用nacl-gdb调试模块:
-
使用
-g
标志编译模块,以便.nexe保留符号和其他调试信息(请参阅建议的编译标志)。 -
启动本地Web服务器(例如,SDK中包含的Web服务器)。
-
使用以下三个必需标志启动Chrome :
--enable-nacl --enable-nacl-debug --no-sandbox
.您可能还想使用下面列出的一些可选标志。典型的命令如下所示:
chrome --enable-nacl --enable-nacl-debug --no-sandbox --disable-hang-monitor localhost:5103
必需的标志:
--enable-nacl
为所有应用程序启用Native Client,包括在Chrome Web Store外部启动的应用程序。
--enable-nacl-debug
打开Native Client调试存根,打开TCP端口4014,并暂停Chrome以让调试器连接。
--no-sandbox
关闭Chrome沙箱(而不是Native Client沙箱)。这将启用stdout和stderr流,并让调试器连接。
可选标志:
--disable-hang-monitor
当标签无响应时,防止Chrome显示警告。
--user-data-dir=<directory>
指定Chrome应从中加载其状态的用户数据目录。您可以指定其他用户数据目录,以便在调试会话中对Chrome所做的更改不会影响您的个人Chrome数据(历史记录,Cookie,书签,主题和设置)。
--nacl-debug-mask=<nmf_url_mask1,nmf_url_mask2,...>
指定一组调试掩码模式。这允许您有选择地选择调试某些应用程序而不调试其他应用程序。例如,如果您只想为应用程序调试NMF文件
https://example.com/app
,而不是在Web上找到其他NaCl应用程序,请指定--nacl-debug-mask=https://example.com/app/*.nmf
。如果您想--enable-nacl-debug
打开旗帜,这有助于防止意外调试其他NaCl应用程序。掩码的模式语言遵循chrome扩展匹配模式。可以通过在模式集前加上!
字符来反转模式集。<URL>
指定Chrome启动时应打开的网址。SDK附带的本地服务器默认侦听端口5103,因此调试时的URL通常是
localhost:5103
(假设您的应用程序页面名为index.html,并且您在该页面所在的目录中运行本地服务器)位于)。 -
导航到Chrome中的应用程序页面。(如果您在上一步中启动Chrome时指定了网址,则无需执行此操作。)Chrome将开始加载应用程序,然后暂停并等待,直到您启动nacl-gdb并运行
continue
命令。 -
转到包含源代码的目录,然后从那里运行nacl-gdb。例如:
cd nacl_sdk/pepper_<version>/examples/demo/drive nacl_sdk/pepper_<version>/toolchain/win_x86_newlib/bin/x86_64-nacl-gdb
调试器将启动并显示gdb提示符:
(gdb)
-
运行debugging命令行。
对于PNaCl:
(gdb) target remote localhost:4014 (gdb) remote get nexe <path-to-save-translated-nexe-with-debug-info> (gdb) file <path-to-save-translated-nexe-with-debug-info> (gdb) remote get irt <path-to-save-NaCl-integrated-runtime> (gdb) nacl-irt <path-to-saved-NaCl-integrated-runtime>
对于NaCl:
(gdb) target remote localhost:4014 (gdb) nacl-manifest <path-to-your-.nmf-file> (gdb) remote get irt <path-to-save-NaCl-integrated-runtime> (gdb) nacl-irt <path-to-saved-NaCl-integrated-runtime>
-
用于PNaCl和NaCl的命令如下所述:
target remote localhost:4014
告诉调试器如何连接到Native Client应用程序加载器中的调试存根。此连接通过TCP端口4014进行(请注意,此端口与本地Web服务器用于侦听传入请求的端口不同,通常是端口5103)。如果您同时调试多个应用程序,则加载程序可能会选择与默认4014端口不同的端口。有关调试端口,请参阅Chrome任务管理器。
remote get nexe <path>
这将应用程序的主要可执行文件(nexe)保存到
<path>
。对于PNaCl,这提供了一种方便的方式来访问由于翻译你的pexe 而导致的nexe。然后可以使用该file <path>
命令加载它。nacl-manifest <path>
对于NaCl(不是PNaCl),这告诉调试器在哪里可以找到应用程序的可执行文件(.nexe)。应用程序的清单(.nmf)文件列出了应用程序的可执行文件,以及动态链接到应用程序的任何库。
remote get irt <path>
这样可以保存Native Client集成运行时(IRT)。通常,IRT与Chrome可执行文件位于同一目录中,或位于以Chrome版本命名的子目录中。例如,如果您在Windows上运行Chrome canary,则IRT的路径通常类似于
C:/Users/<username>/AppData/Local/Google/Chrome SxS/Application/23.0.1247.1/nacl_irt_x86_64.nexe
。将其remote get irt <path>
保存到当前工作目录,以便您无需查找IRT的存储位置。nacl-irt <path>
告诉调试器在哪里可以找到Native Client集成运行时(IRT)。
<path>
可以是保存的副本的位置,也可以remote get irt <path>
是与Chrome一起安装的副本。关于如何在上面的nacl-gdb命令中指定路径名的几点注意事项:
例如,以下是这些nacl-gdb命令在Windows上的外观:
target remote localhost:4014 nacl-manifest "C:/nacl_sdk/pepper_<version>/examples/hello_world_gles/newlib/Debug/hello_world_gles.nmf" nacl-irt "C:/Users/<username>/AppData/Local/Google/Chrome SxS/Application/23.0.1247.1/nacl_irt_x86_64.nexe"
为了节省一些输入,您可以将这些nacl-gdb命令放在脚本文件中,并在运行nacl-gdb时执行该文件,如下所示:
nacl_sdk/pepper_<version>/toolchain/win_x86_newlib/bin/x86_64-nacl-gdb -x <nacl-script-file>
如果nacl-gdb成功连接到Chrome,它会显示一条消息,如下面的消息,然后是gdb提示符:
0x000000000fc00200 in _start () (gdb)
如果nacl-gdb无法连接到Chrome,它会显示一条消息,例如“
localhost:4014: A connection attempt failed
”或“localhost:4014: Connection timed out.
”如果您看到类似这样的消息,请确保您已启动网络服务器,启动Chrome并导航到您的应用程序页面之前启动nacl-gdb。-
您可以使用正斜杠来分隔Linux,Mac和Windows上的目录。如果使用反斜杠在Windows上分隔目录,则必须在目录之间使用双反斜杠“\”来转义反斜杠。
-
如果路径中的任何目录名称中包含空格,则必须在路径周围加上引号。
-
nacl-gdb连接到Chrome后,您可以运行标准gdb命令来执行模块并检查其状态。下面列出了一些常用命令。
break <location>
在<location>设置断点,例如:
break hello_world.cc:79
break hello_world::HelloWorldInstance::HandleMessage
break Render
continue
恢复程序的正常执行
next
执行下一个源代码行,逐步执行函数
step
执行下一个源代码行,进入函数
print <expression>
打印<expression>的值(例如,变量)
backtrace
打印堆栈回溯
info breakpoints
打印所有断点的表
delete <breakpoint>
删除指定的断点(可以使用info命令显示的断点号)
help <command>
打印指定gdb <command>的文档
quit
退出gdb
有关gdb命令的完整列表,请参阅gdb文档。请注意,您可以将大多数命令缩写为它们的第一个字母(b
用于中断,c
用于继续等)。
要中断模块的执行,请按<Ctrl-c>。完成调试后,关闭Chrome窗口并键入q
以退出gdb。
使用其他工具进行调试
如果您不能使用Visual Studio加载项,或者您想使用除nacl-gdb之外的调试器,则必须手动将模块构建为Pepper插件(有时称为“ 受信任 ”或“进程内”插件)。Pepper插件(Windows上的.DLL文件; Linux上的.so文件; Mac上的.bundle文件)直接加载到Chrome渲染器进程或单独的插件进程中,而不是在Native Client中。将模块构建为可信的Pepper插件允许您在系统上使用标准调试器和开发工具,但是当您完成开发插件时,需要将其移植到Native Client(即,使用其中一个工具链构建模块)在NaCl SDK中,以便模块在Native Client中运行)。有关此高级开发技术的详细信息,请参阅调试受信任的插件。请注意,从pepper_22
包中开始,NaCl SDK for Windows包含预先构建的库和库源代码,使得将模块构建到.DLL中更加容易。
CC-By 3.0许可下提供的内容