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