1Debugging On Windows 2==================== 3 4+--------------------------------------------------------------------+ 5| This page is an import from MDN and the contents might be outdated | 6+--------------------------------------------------------------------+ 7 8This document explains how to debug Gecko based applications such as 9Firefox, Thunderbird, and SeaMonkey on Windows using the Visual C++ IDE. 10 11If VC++ and your Gecko application hang shortly after you launch the 12application under the debugger, see `Problems Loading Debug 13Symbols <#problems-loading-debug-symbols>`__. 14 15Ways to start the debugger 16~~~~~~~~~~~~~~~~~~~~~~~~~~ 17 18First of all, it's necessary to install a Visual Studio extension to be 19able to follow child processes as they are created. Firefox, in general, 20and even in non-e10s mode, does not start the main process directly, it 21starts it via a Launcher Process. This means that Visual Studio will 22only attach to the first process it finds, and will not hit any 23break-point (and even notifies you that it cannot find their location). 24`Microsoft Child Process Debugging Power 25Tool <https://marketplace.visualstudio.com/items?itemName=vsdbgplat.MicrosoftChildProcessDebuggingPowerTool>`__ 26allows automatically attaching to child processes, such as Web Content 27process, GPU process, etc. Enable it by going its configuration menu in 28"Debug > Other debugging targets > Child process debugging settings", 29and ticking the box. 30 31If you have followed the steps in :ref:`Building Firefox for 32Windows <Building Firefox On Windows>` 33and have a local debug build, you can **execute this command from same command line.** 34 35.. code:: 36 37 ./mach run --debug 38 39It would open Visual Studio with Firefox's 40run options configured. You can **click "Start" button** to run Firefox 41then, already attached in the debugger. 42 43Alternatively, if you have generated the Visual Studio solution, via 44``./mach build-backend -b VisualStudio``, opening this solution allows 45you to run ``firefox.exe`` directly in the debugger. Making it the 46startup project, by right clicking on it (it appears bold when it's the 47case) can be useful. Breakpoints are kept across runs, this can be a 48good way to debug startup issues. 49 50**Run the program until you hit an assertion.** You will get a dialog 51box asking if you would like to debug. Hit "Cancel". The MSDEV IDE will 52launch and load the file where the assertion happened. This will also 53create a Visual C++ Mozilla project in the directory of the executable 54by default. 55 56**Attach the debugger to an existing Mozilla process**. In the Visual 57Studio, select Debug > Attach to Process. If you want to debug a content 58process, you can **hover on the tab** of page you want to debug, which 59would show the pid. You can then select the process from dialog opened 60from "Attach to Process". For more information, see `Attach to Running 61Processes with the Visual Studio 62Debugger <http://msdn.microsoft.com/en-us/library/vstudio/3s68z0b3.aspx>`__. 63 64**Starting an MSIX installed Firefox with the debugger**. In Visual 65Studio, select Debug -> Other Debug Targets -> Debug Installed App Package. 66In the dialog, select the installed Firefox package you wish to debug 67and click "Start". 68 69Debugging Release and Nightly Builds 70~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 71 72Refer to the steps to :ref:`use the Mozilla symbol 73server <Using The Mozilla Symbol Server>` and :ref:`source 74server <Using The Mozilla Source Server>` 75 76Creating a Visual C++ project for Firefox 77~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 78 79Please refer to :ref:`this <Visual Studio Projects>`. 80 81Changing/setting the executable to debug 82~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 83 84VC++ 6.0: To change or set the executable to debug, go to Project > 85Settings..., Debug tab and select General from the drop down list. 86"Executable for debug session:" should show the executable you are 87debugging. If it is empty or incorrect, use the arrow button and select 88Browse... to locate the executable. 89 90Command line parameters and environment variables 91~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 92 93VC++ 6.0: To change or set the command line options, go to Project > 94Settings..., Debug tab and select General from the drop down list. 95"Program arguments:" should show the options. 96 97Some common options would be the URL of the file you want the browser to 98open as soon as it starts, starting the Profile Manager, or selecting a 99profile. You can also redirect the console output to a file (by adding 100"``> filename.txt``" for example, without the quotes). 101 102In VC 7 and 8 this option is called Project > Properties > Debugging > 103Command Arguments. VC 8 also allows you to set environment variables 104there. 105 106Setting breakpoints in DLLs which are not yet loaded in memory 107~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 108 109VC++ 6.0: Go to Project > Settings..., Debug tab and select "Additional 110DLLs" from the drop down list. Check "Locate Additional DLLs" option. 111For each DLL, click the "New" button which creates a new entry and then 112hit the "..." buttons which lets you browse to the DLL. You will only be 113able to add one DLL at a time. 114 115VC++ 7.0 automatically finds additional DLLs. 116 117Customizing the debugger's variable value view 118~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 119 120You can customize how Visual C++ displays classes in the variable view. 121By default VC++ displays "{...}" and you need to click the small + icon 122to expand the members. You can change this behaviour, and make Visual 123C++ display whatever data member you want in whatever order, formatter 124however you like instead of just "{...}". 125 126You need to locate a file called "AUTOEXP.DAT" in your Visual C++ 127installation. By default it will be: 128 129VC++ 6.0: 130 131.. code:: 132 133 C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin\AUTOEXP.DAT 134 135VC++ 7.0: 136 137.. code:: 138 139 C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Packages\Debugger\AUTOEXP.DAT 140 141The file has information about the format in the beginning, and after a 142little practice you should be well on your way. Here are some entries 143that will make your life easier: 144 145:: 146 147 ;; Mozilla (1.7beta and later) 148 nsAutoString=<mData,su> 149 nsString=<mData,su> 150 nsCString=<mData,s> 151 nsCAutoString=<mData,s> 152 nsRect=x=<x,d> y=<y,d> width=<width,d>; height=<height,d> 153 nsStaticAtomWrapper=<mStaticAtom->mString,s> 154 nsIAtom=<mString,su> 155 ; the following are not necessary in vc8 156 nsCOMPtr<*>=<mRawPtr,x> 157 nsRefPtr=<mRawPtr,x> 158 nsAutoPtr=<mRawPtr,x> 159 160After you have made the changes and saved the file, you will need to 161restart Visual C++ for the changes to take effect. 162 163For XPCOM Strings (the "external" string API) you can use the following 164values: 165 166:: 167 168 ;; Mozilla (1.9) 169 ; Internal Strings 170 nsAString_internal=<mData,su>, length=<mLength,u> 171 nsACString_internal=<mData,s>, length=<mLength,u> 172 ; XPCOM Strings 173 nsAString=<nsStringContainer.v,su>, length=<nsStringContainer.d1,u> 174 nsACString=<nsCStringContainer.v,s>, length=<nsCStringContainer.d1,u> 175 nsStringContainer=<v,su>, length=<d1,u> 176 nsCStringContainer=<v,s>, length=<d1,u> 177 178There is a more extensive version of this file in progress in 179`AutoExpForVC8. <https://developer.mozilla.org/en-US/docs/Mozilla/Debugging/AutoExpForVC8>`__ 180 181Avoiding stepping into certain functions 182~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 183 184You can avoid stepping into certain functions, such as nsCOMPtr methods, 185using an undocumented feature of VC. See the blog post `How to Not Step 186Into Functions using the Visual C++ 187Debugger <http://blogs.msdn.com/andypennell/archive/2004/02/06/69004.aspx>`__ 188for details. 189 190Here are some wildcards you can use (tested with VC 8): 191 192.. code:: 193 194 nsCOMPtr.*\:\:.*=NoStepInto 195 (nsG|g)etter_*AddRefs.*=NoStepInto 196 NS_ConvertUTF.* 197 ; Might be too broad: 198 (ns|Promise)[^\:]*[sS]tring.* 199 ...add common functions to this list 200 201should probably make a .reg file for easy importing 202 203Obtaining ``stdout`` and other ``FILE`` handles 204~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 205 206Running the following command in the Command Window in Visual Studio 207returns the value of ``stdout``, which can be used with various 208debugging methods (such as ``nsGenericElement::List``) that take a 209``FILE*`` param: 210 211.. code:: 212 213 Debug.EvaluateStatement {,,msvcr80d}(&__iob_func()[1]) 214 215(Alternatively you can evaluate ``{,,msvcr80d}(&__iob_func()[1])`` in 216the QuickWatch window) 217 218Similarly, you can open a file on the disk using ``fopen``: 219 220.. code:: 221 222 >Debug.EvaluateStatement {,,msvcr80d}fopen("c:\\123", "w") 223 0x10311dc0 { ..snip.. } 224 >Debug.EvaluateStatement ((nsGenericElement*)0x03f0e710)->List((FILE*)0x10311dc0, 1) 225 <void> 226 >Debug.EvaluateStatement {,,msvcr80d}fclose((FILE*)0x10311dc0) 227 0x00000000 228 229Note that you may not see the debugging output until you flush or close 230the file handle. 231 232Disabling ASSERTIONS 233~~~~~~~~~~~~~~~~~~~~ 234 235There are basically two ways to disable assertions. One requires setting 236an environment variable, while the other affects only the currently 237running program instance in memory. 238 239Environment variable 240^^^^^^^^^^^^^^^^^^^^ 241 242There is an environment variable that can disable breaking for 243assertions. This is how you would normally set it: 244 245.. code:: 246 247 set XPCOM_DEBUG_BREAK=warn 248 249The environment variable takes also other values besides ``warn``, see 250``XPCOM_DEBUG_BREAK`` for more details. 251 252Note that unlike Unix, the default for Windows is not warn, it's to pop 253up a dialog. To set the environment variable for Visual Studio, use 254Project > Properties > Debugging > Environment and click the little box. 255Then use 256 257.. code:: 258 259 XPCOM_DEBUG_BREAK=warn 260 261Changing running code 262^^^^^^^^^^^^^^^^^^^^^ 263 264You normally shouldn't need to do this (just quit the application, set 265the environment variable described above, and run it again). And this 266can be **dangerous** (like **trashing your hard disc and corrupting your 267system**). So unless you feel comfortable with this, don't do it. **You 268have been warned!** 269 270It is possible to change the interrupt code in memory (which causes you 271to break into debugger) to be a NOP (no operation). 272 273You do this by running the program in the debugger until you hit an 274assertion. You should see some assembly code. One assembly code 275instruction reads "int 3". Check the memory address for that line. Now 276open memory view. Type/copy/drag the memory address of "int 3" into the 277memory view to get it to update on that part of the memory. Change the 278value of the memory to "90", close the memory view and hit "F5" to 279continue. 280 281| Confused? See the screenshot below: 282| |Screenshot of disabling assertions| 283 284VC++ 7.0? 285 286Automatically handling ASSERTIONS without a debugger attached 287~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 288 289When an assertion happens and there is not a debugger attached, a small 290helper application 291(```windbgdlg.exe`` </En/Automatically_Handle_Failed_Asserts_in_Debug_Builds>`__) 292is run. That application can automatically select a response to the "Do 293you want to debug" dialog instead of prompting if you configure it, for 294more info, see 295```windbgdlg.exe`` </En/Automatically_Handle_Failed_Asserts_in_Debug_Builds>`__. 296 297Debugging optimized builds 298~~~~~~~~~~~~~~~~~~~~~~~~~~ 299 300To effectively debug optimized builds, you should enable debugging 301information which effectively leaves the debug symbols in optimized code 302so you can still set breakpoints etc. Because the code is optimized, 303stepping through the code may occasionally provide small surprises when 304the debugger jumps over something. 305 306You need to make sure this configure parameter is set: 307 308.. code:: 309 310 --enable-debugger-info-modules=yes 311 312You can also choose to include or exclude specific modules. This is 313particularly useful to avoid linking layout with debugging information. 314 315Console debugging 316~~~~~~~~~~~~~~~~~ 317 318When printing to STDOUT from a content process, the console message will 319not appear on Windows. One way to view it is simply to disable e10s 320(``./mach run --disable-e10s``) but in order to debug with e10s enabled 321one can run 322 323:: 324 325 ./mach run ... 2>&1 | tee 326 327It may also be necessary to disable the content sandbox 328(``MOZ_DISABLE_CONTENT_SANDBOX=1 ./mach run ...``). 329 330Running two instances of Mozilla simultaneously 331~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 332 333You can run two instances of Mozilla (e.g. debug and optimized) 334simultaneously by setting the environment variable ``MOZ_NO_REMOTE``: 335 336.. code:: 337 338 set MOZ_NO_REMOTE=1 339 340Or, starting with Firefox 2 and other Gecko 1.8.1-based applications, 341you can use the ``-no-remote`` command-line switch instead (implemented 342in 343`bug 325509 <https://bugzilla.mozilla.org/show_bug.cgi?id=325509>`__). 344 345You can also specify the profile to use with the ``-P profile_name`` 346command-line argument. 347 348Debugging JavaScript 349~~~~~~~~~~~~~~~~~~~~ 350 351Use `Venkman <https://developer.mozilla.org/en-US/docs/Archive/Mozilla/Venkman>`__, the JavaScript Debugger for Mozilla. 352 353You can use helper functions from 354`nsXPConnect.cpp <https://searchfox.org/mozilla-central/source/js/xpconnect/src/nsXPConnect.cpp>`__ 355to inspect and modify the state of JavaScript code from the MSVS 356debugger. 357 358For example, to print current JavaScript stack to stdout, evaluate this 359in QuickWatch window: 360 361.. code:: 362 363 {,,xul}DumpJSStack() 364 365Visual C++ will show you something in the quick watch window, but 366not the stack, you have to look in the OS console for the output. 367 368Also this magical command only works when the VC++ stack is in certain 369states. It works when you have js_Interpret() in the newest stackframe 370 371Debugging minidumps 372~~~~~~~~~~~~~~~~~~~ 373 374See :ref:`debugging a minidump <Debugging A Minidump>`. 375 376Debugging treeherder builds 377~~~~~~~~~~~~~~~~~~~~~~~~~~~ 378 379See `Running Windows Debug Builds <https://developer.mozilla.org/en-US/docs/Archive/Mozilla/Running_Windows_Debug_Builds>`__ 380 381Problems Loading Debug Symbols 382~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 383 384If both your application and Visual C++ hang shortly after launching the 385application under the debugger, you may be hitting a known deadlock in 386the way Visual Studio downloads debug symbols for the system libraries; 387see 388https://connect.microsoft.com/VisualStudio/feedback/details/422970/hang-loading-rasapi32-pdb-when-using-symbol-server. 389 390There are two ways to work around this problem: 391 392#. Turn off automatic symbol downloading for system libraries: in Tools 393 > Options > Debugging > Symbols, uncheck the Microsoft symbol server. 394#. Pre-load all the Windows debug symbols. These instructions apply to 395 Visual Studio 10 on Windows 7; other software versions likely need to 396 have file paths adjusted. 397 398 #. Locate the Microsoft utility "SymChk.exe" on your system (it will 399 likely be in the installation directory of your Windows Debugging 400 Tools). 401 402 #. Find the directory where Visual Studio caches downloaded symbols; 403 in VC++ 10 open the menu to Tools > Options > Debugging > Symbols 404 and copy the field "Cache symbols in this directory". 405 406 #. In a command window, run 407 408 :: 409 410 symchk.exe /r C:\windows\SysWOW64\ /s "SRV*<your cache symbols directory>\MicrosoftPublicSymbols*http://msdl.microsoft.com/download/symbols" 411 412 | 413 | Note the "``\MicrosoftPublicSymbols``" appended to the cache 414 directory configured in Visual Studio. 415 416Downloading all symbols can take a long time; you can replace 417C:\windows\SysWOW64\\ with the name of a single .DLL to download symbols 418only for the specific libraries you are trying to debug. Unfortunately, 419it's hard to know which symbols to download without having VS hang and 420seeing the "Downloading symbols for <library>" status at the bottom left 421of the main window. 422 423Problems post-mortem debugging on Windows 7 SP1 x64? 424~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 425 426If you attempt to use ``NS_DebugBreak`` etc to perform post-mortem 427debugging on a 64bit Windows 7, but as soon as you try and continue 428debugging the program crashes with an Access Violation, you may be 429hitting a Windows bug relating to AVX support. For more details, 430including a work-around see `this blog 431post <http://www.os2museum.com/wp/?p=960>`__ or `this social.msdn 432thread <http://social.msdn.microsoft.com/Forums/vstudio/en-US/392ca62c-e502-42d9-adbc-b4e22d5da0c3/jit-debugging-32bit-app-crashing-with-access-violation>`__. 433(And just in-case those links die, the work-around is to execute 434 435:: 436 437 bcdedit /set xsavedisable 1 438 439from an elevated command-prompt to disable AVX support.) 440 441Got a tip? 442~~~~~~~~~~ 443 444If you think you know a cool Mozilla debugging trick, feel free to 445discuss it with `#developers <https://chat.mozilla.org/#/room/#developers:mozilla.org>`__ and 446then post it here. 447 448.. |Screenshot of disabling assertions| image:: https://developer.mozilla.org/@api/deki/files/420/=Win32-debug-nop.png 449 :class: internal 450