1 .. _devcycle-debugging: 2 3 ######### 4 Debugging 5 ######### 6 7 This document describes tools and techniques you can use to debug, monitor, 8 and measure your application's performance. 9 10 .. contents:: Table Of Contents 11 :local: 12 :backlinks: none 13 :depth: 3 14 15 Diagnostic information 16 ====================== 17 18 Viewing process statistics with the task manager 19 ------------------------------------------------ 20 21 You can use Chrome's Task Manager to display information about a Native Client 22 application: 23 24 #. Open the Task Manager by clicking the menu icon |menu-icon| and choosing 25 **Tools > Task manager**. 26 #. When the Task Manager window appears, verify that the columns displaying 27 memory information are visible. If they are not, right click in the header 28 row and select the memory items from the popup menu that appears. 29 30 A browser window running a Native Client application will have at least two 31 processes associated with it: a process for the app's top level (the render 32 process managing the page including its HTML and any JavaScript) and one or 33 more processes for each instance of a Native Client module embedded in the page 34 (each process running native code from one nexe file). The top-level process 35 appears with the application's icon and begins with the text "App:". A Native 36 Client process appears with a Chrome extension icon (a jigsaw puzzle piece 37 |puzzle|) and begins with the text "Native Client module" followed by the URL 38 of its manifest file. 39 40 From the Task Manager you can view the changing memory allocations of all the 41 processes associated with a Native Client application. Each process has its own 42 memory footprint. You can also see the rendering rate displayed as frames per 43 second (FPS). Note that the computation of render frames can be performed in 44 any process, but the rendering itself is always done in the top level 45 application process, so look for the rendering rate there. 46 47 Controlling the level of Native Client error and warning messages 48 ----------------------------------------------------------------- 49 50 Native Client prints warning and error messages to stdout and stderr. You can 51 increase the amount of Native Client's diagnostic output by setting the 52 following `environment variables 53 <http://en.wikipedia.org/wiki/Environment_variable>`_: 54 55 * NACL_DEBUG_ENABLE=1 56 * PPAPI_BROWSER_DEBUG=1 57 * NACL_PLUGIN_DEBUG=1 58 * NACL_PPAPI_PROXY_DEBUG=1 59 * NACL_SRPC_DEBUG=[1-255] (use a higher number for more verbose debug output) 60 * NACLVERBOSITY=[1-255] 61 62 Basic debugging 63 =============== 64 65 Writing messages to the JavaScript console 66 ------------------------------------------ 67 68 You can send messages from your C/C++ code to JavaScript using the PostMessage 69 call in the :doc:`Pepper messaging system <../coding/message-system>`. When the 70 JavaScript code receives a message, its message event handler can call 71 `console.log() <https://developer.mozilla.org/en/DOM/console.log>`_ to write 72 the message to the JavaScript `console </devtools/docs/console-api>`_ in 73 Chrome's Developer Tools. 74 75 Debugging with printf 76 --------------------- 77 78 Your C/C++ code can perform inline printf debugging to stdout and stderr by 79 calling fprintf() directly, or by using cover functions like these: 80 81 .. naclcode:: 82 83 #include <stdio.h> 84 void logmsg(const char* pMsg){ 85 fprintf(stdout,"logmsg: %s\n",pMsg); 86 } 87 void errormsg(const char* pMsg){ 88 fprintf(stderr,"logerr: %s\n",pMsg); 89 } 90 91 By default stdout and stderr will appear in Chrome's stdout and stderr stream 92 but they can also be redirected as described below. 93 94 Redirecting output to log files 95 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 96 97 You can redirect stdout and stderr to output files by setting these environment variables: 98 99 * ``NACL_EXE_STDOUT=c:\nacl_stdout.log`` 100 * ``NACL_EXE_STDERR=c:\nacl_stderr.log`` 101 102 There is another variable, ``NACLLOG``, that you can use to redirect Native 103 Client's internally-generated messages. This variable is set to stderr by 104 default; you can redirect these messages to an output file by setting the 105 variable as follows: 106 107 * ``NACLLOG=c:\nacl.log`` 108 109 .. Note:: 110 :class: note 111 112 **Note:** If you set the NACL_EXE_STDOUT, NACL_EXE_STDERR, or NACLLOG 113 variables to redirect output to a file, you must run Chrome with the 114 ``--no-sandbox`` flag. You must also be careful that each variable points to 115 a different file. 116 117 Redirecting output to the JavaScript console 118 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 119 120 You can also cause output from printf statements in your C/C++ code to be 121 relayed to the JavaScript side of your application through the Pepper messaging 122 system, where you can then write the output to the JavaScript console. Follow 123 these steps: 124 125 #. Set the NACL_EXE_STDOUT and NACL_EXE_STDERR environment variables as 126 follows: 127 128 * NACL_EXE_STDOUT=DEBUG_ONLY:dev://postmessage 129 * NACL_EXE_STDERR=DEBUG_ONLY:dev://postmessage 130 131 These settings tell Native Client to use PostMessage() to send output that 132 your Native Client module writes to stdout and stderr to the JavaScript side 133 of your application. 134 135 #. Register a JavaScript handler to receive messages from your Native Client 136 module: 137 138 .. naclcode:: 139 140 <div id="nacl_container"> 141 <script type="text/javascript"> 142 var container = document.getElementById('nacl_container'); 143 container.addEventListener('message', handleMessage, true); 144 </script> 145 <embed id="nacl_module" 146 src="my_application.nmf" 147 type="application/x-nacl" /> 148 </div> 149 150 #. Implement a simple JavaScript handler that logs the messages it receives to 151 the JavaScript console: 152 153 .. naclcode:: 154 155 function handleMessage(message_event) { 156 console.log(message_event.data); 157 } 158 159 This handler works in the simple case where the only messages your Native 160 Client module sends to JavaScript are messages with the output from stdout 161 and stderr. If your Native Client module also sends other messages to 162 JavaScript, your handler will need to be more complex. 163 164 Once you've implemented a message handler and set up the environment 165 variables as described above, you can check the JavaScript console to see 166 output that your Native Client module prints to stdout and stderr. Keep in 167 mind that your module makes a call to PostMessage() every time it flushes 168 stdout or stderr. Your application's performance will degrade considerably 169 if your module prints and flushes frequently, or if it makes frequent Pepper 170 calls to begin with (e.g., to render). 171 172 Logging calls to Pepper interfaces 173 ---------------------------------- 174 175 You can log all Pepper calls your module makes by passing the following flags 176 to Chrome on startup:: 177 178 --vmodule=ppb*=4 --enable-logging=stderr 179 180 181 The ``vmodule`` flag tells Chrome to log all calls to C Pepper interfaces that 182 begin with "ppb" (that is, the interfaces that are implemented by the browser 183 and that your module calls). The ``enable-logging`` flag tells Chrome to log 184 the calls to stderr. 185 186 .. _visual_studio: 187 188 Debugging with Visual Studio 189 ---------------------------- 190 191 If you develop on a Windows platform you can use the :doc:`Native Client Visual 192 Studio add-in <vs-addin>` to write and debug your code. The add-in defines new 193 project platforms that let you run your module in two different modes: As a 194 Pepper plugin and as a Native Client module. When running as a Pepper plugin 195 you can use the built-in Visual Studio debugger. When running as a Native 196 Client module Visual Studio will launch an instance of nacl-gdb for you and 197 link it to the running code. 198 199 .. _using_gdb: 200 201 Debugging with nacl-gdb 202 ----------------------- 203 204 The Native Client SDK includes a command-line debugger that you can use to 205 debug Native Client modules. The debugger is based on the GNU debugger `gdb 206 <http://www.gnu.org/software/gdb/>`_, and is located at 207 ``toolchain/<platform>_x86_newlib/bin/x86_64-nacl-gdb`` (where *<platform>* 208 is the platform of your development machine: ``win``, ``mac``, or 209 ``linux``). 210 211 Note that this same copy of GDB can be used to debug any NaCl program, 212 whether built using newlib or glibc for x86-32, x86-64 or ARM. In the SDK, 213 ``i686-nacl-gdb`` is an alias for ``x86_64-nacl-gdb``, and the ``newlib`` 214 and ``glibc`` toolchains both contain the same version of GDB. 215 216 .. _debugging_pnacl_pexes: 217 218 Debugging PNaCl pexes (with Pepper 35+) 219 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 220 221 If you want to use GDB to debug a program that is compiled with the PNaCl 222 toolchain, you must have a copy of the pexe from **before** running 223 ``pnacl-finalize``. The ``pnacl-finalize`` tool converts LLVM bitcode 224 to the stable PNaCl bitcode format, but it also strips out debug 225 metadata, which we need for debugging. In this section we'll give the 226 LLVM bitcode file a ``.bc`` file extension, and the PNaCl bitcode file 227 a ``.pexe`` file extension. The actual extension should not matter, but 228 it helps distinguish between the two types of files. 229 230 **Note** unlike the finalized copy of the pexe, the non-finalized debug copy 231 is not considered stable. This means that a debug copy of the PNaCl 232 application created by a Pepper N SDK is only guaranteed to run 233 with a matching Chrome version N. If the version of the debug bitcode pexe 234 does not match that of Chrome then the translation process may fail, and 235 you will see and error message in the JavaScript console. 236 237 Also, make sure you are passing the ``-g`` :ref:`compile option 238 <compile_flags>` to ``pnacl-clang`` to enable generating debugging info. 239 You might also want to omit ``-O2`` from the compile-time and link-time 240 options, otherwise GDB not might be able to print variables' values when 241 debugging (this is more of a problem with the PNaCl/LLVM toolchain than 242 with GCC). 243 244 Once you have built a non-stable debug copy of the pexe, list the URL of 245 that copy in your application's manifest file: 246 247 .. naclcode:: 248 249 { 250 "program": { 251 "pnacl-translate": { 252 "url": "release_version.pexe", 253 "optlevel": 2 254 }, 255 "pnacl-debug": { 256 "url": "debug_version.bc", 257 "optlevel": 0 258 } 259 } 260 } 261 262 Copy the ``debug_version.bc`` and ``nmf`` files to the location that 263 your local web server serves files from. 264 265 When you run Chrome with ``--enable-nacl-debug``, Chrome will translate 266 and run the ``debug_version.bc`` instead of ``release_version.pexe``. 267 Once the debug version is loaded, you are ready to :ref:`run nacl-gdb 268 <running_nacl_gdb>` 269 270 Whether you publish the NMF file containing the debug URL to the release 271 web server, is up to you. One reason to avoid publishing the debug URL 272 is that it is only guaranteed to work for the Chrome version that matches 273 the SDK version. Developers who may have left the ``--enable-nacl-debug`` 274 flag turned on may end up loading the debug copy of your application 275 (which may or may not work, depending on their version of Chrome). 276 277 278 Debugging PNaCl pexes (with older Pepper toolchains) 279 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 280 281 If you want to use GDB to debug a program that is compiled with the PNaCl 282 toolchain, you must convert the ``pexe`` file to a ``nexe``. (You can skip 283 this step if you are using the GCC toolchain, or if you are using 284 pepper 35 or later.) 285 286 * Firstly, make sure you are passing the ``-g`` :ref:`compile option 287 <compile_flags>` to ``pnacl-clang`` to enable generating debugging info. 288 You might also want to omit ``-O2`` from the compile-time and link-time 289 options. 290 291 * Secondly, use ``pnacl-translate`` to convert your ``pexe`` to one or more 292 ``nexe`` files. For example: 293 294 .. naclcode:: 295 :prettyprint: 0 296 297 <NACL_SDK_ROOT>/toolchain/win_pnacl/bin/pnacl-translate ^ 298 --allow-llvm-bitcode-input hello_world.pexe -arch x86-32 -o hello_world_x86_32.nexe 299 <NACL_SDK_ROOT>/toolchain/win_pnacl/bin/pnacl-translate ^ 300 --allow-llvm-bitcode-input hello_world.pexe -arch x86-64 -o hello_world_x86_64.nexe 301 302 For this, use the non-finalized ``pexe`` file produced by 303 ``pnacl-clang``, not the ``pexe`` file produced by ``pnacl-finalize``. 304 The latter ``pexe`` has debugging info stripped out. The option 305 ``--allow-llvm-bitcode-input`` tells ``pnacl-translate`` to accept a 306 non-finalized ``pexe``. 307 308 * Replace the ``nmf`` :ref:`manifest file <manifest_file>` that points to 309 your ``pexe`` file with one that points to the ``nexe`` files. For the 310 example ``nexe`` filenames above, the new ``nmf`` file would contain: 311 312 .. naclcode:: 313 :prettyprint: 0 314 315 { 316 "program": { 317 "x86-32": {"url": "hello_world_x86_32.nexe"}, 318 "x86-64": {"url": "hello_world_x86_64.nexe"}, 319 } 320 } 321 322 * Change the ``<embed>`` HTML element to use 323 ``type="application/x-nacl"`` rather than 324 ``type="application/x-pnacl"``. 325 326 * Copy the ``nexe`` and ``nmf`` files to the location that your local web 327 server serves files from. 328 329 .. Note:: 330 :class: note 331 332 **Note:** If you know whether Chrome is using the x86-32 or x86-64 333 version of the NaCl sandbox on your system, you can translate the 334 ``pexe`` once to a single x86-32 or x86-64 ``nexe``. Otherwise, you 335 might find it easier to translate the ``pexe`` to both ``nexe`` 336 formats as described above. 337 338 .. _running_nacl_gdb: 339 340 Running nacl-gdb 341 ~~~~~~~~~~~~~~~~ 342 343 Before you start using nacl-gdb, make sure you can :doc:`build <building>` your 344 module and :doc:`run <running>` your application normally. This will verify 345 that you have created all the required :doc:`application parts 346 <../coding/application-structure>` (.html, .nmf, and .nexe files, shared 347 libraries, etc.), that your server can access those resources, and that you've 348 configured Chrome correctly to run your application. The instructions below 349 assume that you are using a :ref:`local server <web_server>` to run your 350 application; one benefit of doing it this way is that you can check the web 351 server output to confirm that your application is loading the correct 352 resources. However, some people prefer to run their application as an unpacked 353 extension, as described in :doc:`Running Native Client Applications <running>`. 354 355 Follow the instructions below to debug your module with nacl-gdb: 356 357 #. Compile your module with the ``-g`` flag so that your .nexe retains symbols 358 and other debugging information (see the :ref:`recommended compile flags 359 <compile_flags>`). 360 #. Launch a local web server (e.g., the :ref:`web server <web_server>` included 361 in the SDK). 362 #. Launch Chrome with these three required flags: ``--enable-nacl --enable-nacl-debug --no-sandbox``. 363 364 You may also want to use some of the optional flags listed below. A typical 365 command looks like this:: 366 367 chrome --enable-nacl --enable-nacl-debug --no-sandbox --disable-hang-monitor localhost:5103 368 369 **Required flags:** 370 371 ``--enable-nacl`` 372 Enables Native Client for all applications, including those that are 373 launched outside the Chrome Web Store. 374 375 ``--enable-nacl-debug`` 376 Turns on the Native Client debug stub, opens TCP port 4014, and pauses 377 Chrome to let the debugger connect. 378 379 ``--no-sandbox`` 380 Turns off the Chrome sandbox (not the Native Client sandbox). This enables 381 the stdout and stderr streams, and lets the debugger connect. 382 383 **Optional flags:** 384 385 ``--disable-hang-monitor`` 386 Prevents Chrome from displaying a warning when a tab is unresponsive. 387 388 ``--user-data-dir=<directory>`` 389 Specifies the `user data directory 390 <http://www.chromium.org/user-experience/user-data-directory>`_ from which 391 Chrome should load its state. You can specify a different user data 392 directory so that changes you make to Chrome in your debugging session do 393 not affect your personal Chrome data (history, cookies, bookmarks, themes, 394 and settings). 395 396 ``--nacl-debug-mask=<nmf_url_mask1,nmf_url_mask2,...>`` 397 Specifies a set of debug mask patterns. This allows you to selectively 398 choose to debug certain applications and not debug others. For example, if 399 you only want to debug the NMF files for your applications at 400 ``https://example.com/app``, and no other NaCl applications found on the 401 web, specify ``--nacl-debug-mask=https://example.com/app/*.nmf``. This 402 helps prevent accidentally debugging other NaCl applications if you like 403 to leave the ``--enable-nacl-debug`` flag turned on. The pattern language 404 for the mask follows `chrome extension match patterns 405 </extensions/match_patterns>`_. The pattern set can be inverted by 406 prefixing the pattern set with the ``!`` character. 407 408 ``<URL>`` 409 Specifies the URL Chrome should open when it launches. The local server 410 that comes with the SDK listens on port 5103 by default, so the URL when 411 you're debugging is typically ``localhost:5103`` (assuming that your 412 application's page is called index.html and that you run the local server 413 in the directory where that page is located). 414 415 #. Navigate to your application's page in Chrome. (You don't need to do this if 416 you specified a URL when you launched Chrome in the previous step.) Chrome 417 will start loading the application, then pause and wait until you start 418 nacl-gdb and run the ``continue`` command. 419 420 #. Go to the directory with your source code, and run nacl-gdb from there. For 421 example:: 422 423 cd <NACL_SDK_ROOT>/examples/hello_world_gles 424 <NACL_SDK_ROOT>/toolchain/win_x86_newlib/bin/x86_64-nacl-gdb 425 426 The debugger will start and show you a gdb prompt:: 427 428 (gdb) 429 430 #. For debugging PNaCl pexes run the following gdb command lines 431 (skip to the next item if you are using NaCl instead of PNaCl):: 432 433 (gdb) target remote localhost:4014 434 (gdb) remote get nexe <path-to-save-translated-nexe-with-debug-info> 435 (gdb) file <path-to-save-translated-nexe-with-debug-info> 436 (gdb) remote get irt <path-to-save-NaCl-integrated-runtime> 437 (gdb) nacl-irt <path-to-saved-NaCl-integrated-runtime> 438 439 #. For NaCl nexes, run the following commands from the gdb command line:: 440 441 (gdb) target remote localhost:4014 442 (gdb) nacl-manifest <path-to-your-.nmf-file> 443 (gdb) remote get irt <path-to-save-NaCl-integrated-runtime> 444 (gdb) nacl-irt <path-to-saved-NaCl-integrated-runtime> 445 446 #. The command used for PNaCl and NaCl are described below: 447 448 ``target remote localhost:4014`` 449 Tells the debugger how to connect to the debug stub in the Native Client 450 application loader. This connection occurs through TCP port 4014 (note 451 that this port is distinct from the port which the local web server uses 452 to listen for incoming requests, typically port 5103). If you are 453 debugging multiple applications at the same time, the loader may choose 454 a port that is different from the default 4014 port. See the Chrome 455 task manager for the debug port. 456 457 ``remote get nexe <path>`` 458 This saves the application's main executable (nexe) to ``<path>``. 459 For PNaCl, this provides a convenient way to access the nexe that is 460 a **result** of translating your pexe. This can then be loaded with 461 the ``file <path>`` command. 462 463 ``nacl-manifest <path>`` 464 For NaCl (not PNaCl), this tells the debugger where to find your 465 application's executable (.nexe) files. The application's manifest 466 (.nmf) file lists your application's executable files, as well as any 467 libraries that are linked with the application dynamically. 468 469 ``remote get irt <path>`` 470 This saves the Native Client Integrated Runtime (IRT). Normally, 471 the IRT is located in the same directory as the Chrome executable, 472 or in a subdirectory named after the Chrome version. For example, if 473 you're running Chrome canary on Windows, the path to the IRT typically 474 looks something like ``C:/Users/<username>/AppData/Local/Google/Chrome 475 SxS/Application/23.0.1247.1/nacl_irt_x86_64.nexe``. 476 The ``remote get irt <path>`` saves that to the current working 477 directory so that you do not need to find where exactly the IRT 478 is stored alongside Chrome. 479 480 ``nacl-irt <path>`` 481 Tells the debugger where to find the Native Client Integrated Runtime 482 (IRT). ``<path>`` can either be the location of the copy saved by 483 ``remote get irt <path>`` or the copy that is installed alongside Chrome. 484 485 A couple of notes on how to specify path names in the nacl-gdb commands 486 above: 487 488 * You can use a forward slash to separate directories on Linux, Mac, and 489 Windows. If you use a backslash to separate directories on Windows, you 490 must escape the backslash by using a double backslash "\\" between 491 directories. 492 * If any directories in the path have spaces in their name, you must put 493 quotation marks around the path. 494 495 As an example, here is a what these nacl-gdb commands might look like on 496 Windows:: 497 498 target remote localhost:4014 499 nacl-manifest "C:/<NACL_SDK_ROOT>/examples/hello_world_gles/newlib/Debug/hello_world_gles.nmf" 500 nacl-irt "C:/Users/<username>/AppData/Local/Google/Chrome SxS/Application/23.0.1247.1/nacl_irt_x86_64.nexe" 501 502 To save yourself some typing, you can put put these nacl-gdb commands in a 503 script file, and execute the file when you run nacl-gdb, like so:: 504 505 <NACL_SDK_ROOT>/toolchain/win_x86_newlib/bin/x86_64-nacl-gdb -x <nacl-script-file> 506 507 If nacl-gdb connects successfully to Chrome, it displays a message such as 508 the one below, followed by a gdb prompt:: 509 510 0x000000000fc00200 in _start () 511 (gdb) 512 513 If nacl-gdb can't connect to Chrome, it displays a message such as 514 "``localhost:4014: A connection attempt failed``" or "``localhost:4014: 515 Connection timed out.``" If you see a message like that, make sure that you 516 have launched a web server, launched Chrome, and navigated to your 517 application's page before starting nacl-gdb. 518 519 Once nacl-gdb connects to Chrome, you can run standard gdb commands to execute 520 your module and inspect its state. Some commonly used commands are listed 521 below. 522 523 ``break <location>`` 524 set a breakpoint at <location>, e.g.:: 525 526 break hello_world.cc:79 527 break hello_world::HelloWorldInstance::HandleMessage 528 break Render 529 530 ``continue`` 531 resume normal execution of the program 532 533 ``next`` 534 execute the next source line, stepping over functions 535 536 ``step`` 537 execute the next source line, stepping into functions 538 539 ``print <expression>`` 540 print the value of <expression> (e.g., variables) 541 542 ``backtrace`` 543 print a stack backtrace 544 545 ``info breakpoints`` 546 print a table of all breakpoints 547 548 ``delete <breakpoint>`` 549 delete the specified breakpoint (you can use the breakpoint number displayed 550 by the info command) 551 552 ``help <command>`` 553 print documentation for the specified gdb <command> 554 555 ``quit`` 556 quit gdb 557 558 See the `gdb documentation 559 <http://sourceware.org/gdb/current/onlinedocs/gdb/#toc_Top>`_ for a 560 comprehensive list of gdb commands. Note that you can abbreviate most commands 561 to just their first letter (``b`` for break, ``c`` for continue, and so on). 562 563 To interrupt execution of your module, press <Ctrl-c>. When you're done 564 debugging, close the Chrome window and type ``q`` to quit gdb. 565 566 Debugging with other tools 567 ========================== 568 569 If you cannot use the :ref:`Visual Studio add-in <visual_studio>`, or you want 570 to use a debugger other than nacl-gdb, you must manually build your module as a 571 Pepper plugin (sometimes referred to as a "`trusted 572 <http://www.chromium.org/nativeclient/getting-started/getting-started-background-and-basics#TOC-Trusted-vs-Untrusted>`_" 573 or "in-process" plugin). Pepper plugins (.DLL files on Windows; .so files on 574 Linux; .bundle files on Mac) are loaded directly in either the Chrome renderer 575 process or a separate plugin process, rather than in Native Client. Building a 576 module as a trusted Pepper plugin allows you to use standard debuggers and 577 development tools on your system, but when you're finished developing the 578 plugin, you need to port it to Native Client (i.e., build the module with one 579 of the toolchains in the NaCl SDK so that the module runs in Native Client). 580 For details on this advanced development technique, see `Debugging a Trusted 581 Plugin 582 <http://www.chromium.org/nativeclient/how-tos/debugging-documentation/debugging-a-trusted-plugin>`_. 583 Note that starting with the ``pepper_22`` bundle, the NaCl SDK for Windows 584 includes pre-built libraries and library source code, making it much easier to 585 build a module into a .DLL. 586 587 Open source profiling tools 588 --------------------------- 589 590 For the brave-hearted there are open source tools at `Chromium.org 591 <http://www.chromium.org/nativeclient>`_ that describe how to do profiling on 592 `64-bit Windows 593 <https://sites.google.com/a/chromium.org/dev/nativeclient/how-tos/profiling-nacl-apps-on-64-bit-windows>`_ 594 and `Linux 595 <http://www.chromium.org/nativeclient/how-tos/limited-profiling-with-oprofile-on-x86-64>`_ 596 machines. 597 598 599 .. |menu-icon| image:: /images/menu-icon.png 600 .. |puzzle| image:: /images/puzzle.png 601