tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

debugging_on_windows.rst (12732B)


      1 Debugging On Windows
      2 ====================
      3 
      4 This document explains how to debug Gecko based applications such as
      5 Firefox, Thunderbird, and SeaMonkey on Windows using the Visual Studio IDE.
      6 
      7 If VS and your Gecko application hang shortly after you launch the
      8 application under the debugger, see `Problems Loading Debug
      9 Symbols <#problems-loading-debug-symbols>`__.
     10 
     11 Ways to start the debugger
     12 ~~~~~~~~~~~~~~~~~~~~~~~~~~
     13 
     14 First of all, it's necessary to install a Visual Studio extension to be
     15 able to follow child processes as they are created. Firefox, in general,
     16 and even in non-e10s mode, does not start the main process directly, it
     17 starts it via a Launcher Process. This means that Visual Studio will
     18 only attach to the first process it finds, and will not hit any
     19 break-point (and even notifies you that it cannot find their location).
     20 
     21 For Visual Studio 2022 and above,
     22 `Microsoft Child Process Debugging Power Tool 2022+
     23 <https://marketplace.visualstudio.com/items?itemName=vsdbgplat.MicrosoftChildProcessDebuggingPowerTool2022>`__
     24 allows automatically attaching to child processes, such as Web Content
     25 process, GPU process, etc. Enable it by going its configuration menu in
     26 "Debug > Other debugging targets > Child process debugging settings",
     27 and ticking the box. The same extension exists for older versions of Visual
     28 Studio as
     29 `Microsoft Child Process Debugging Power Tool
     30 <https://marketplace.visualstudio.com/items?itemName=vsdbgplat.MicrosoftChildProcessDebuggingPowerTool>`__.
     31 
     32 If you have followed the steps in :ref:`Building Firefox for
     33 Windows <Building Firefox On Windows>`
     34 and have a local debug build, you can **execute this command from same command line.**
     35 
     36 .. code::
     37 
     38   ./mach run --debug
     39 
     40 It would open Visual Studio with Firefox's
     41 run options configured. You can **click "Start" button** to run Firefox
     42 then, already attached in the debugger.
     43 
     44 Alternatively, if you have generated the Visual Studio solution, via
     45 ``./mach build-backend -b VisualStudio``, opening this solution allows
     46 you to run ``firefox.exe`` directly in the debugger. To make it the
     47 startup project, right click on the project and select ``Set As Startup
     48 Project``. It appears bold when it's the case. Breakpoints are kept
     49 across runs, this can be a good way to debug startup issues.
     50 
     51 **Run the program until you hit an assertion.** You will get a dialog
     52 box asking if you would like to debug. Hit "Cancel". The MSDEV IDE will
     53 launch and load the file where the assertion happened. This will also
     54 create a Visual Studio Mozilla project in the directory of the executable
     55 by default.
     56 
     57 **Attach the debugger to an existing Mozilla process**.  In the Visual
     58 Studio, select Debug > Attach to Process. If you want to debug a content
     59 process, you can **hover on the tab** of page you want to debug, which
     60 would show the pid. You can then select the process from dialog opened
     61 from "Attach to Process". You can open ``about:processes`` to see the pid
     62 for all subprocesses, including tabs but also GPU, networking etc.
     63 For more information, see `Attach to Running Processes with the Visual Studio
     64 Debugger <http://msdn.microsoft.com/en-us/library/vstudio/3s68z0b3.aspx>`__.
     65 
     66 **Starting an MSIX installed Firefox with the debugger**. In Visual
     67 Studio, select Debug -> Other Debug Targets -> Debug Installed App Package.
     68 In the dialog, select the installed Firefox package you wish to debug
     69 and click "Start".
     70 
     71 Debugging Release and Nightly Builds
     72 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     73 
     74 Refer to the steps to :ref:`use the Mozilla symbol
     75 server <Using The Mozilla Symbol Server>` and :ref:`source
     76 server <Using The Mozilla Source Server>`
     77 
     78 Creating a Visual Studio project for Firefox
     79 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     80 
     81 Please refer to :ref:`this <Visual Studio Projects>`.
     82 
     83 Changing/setting the executable to debug
     84 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     85 
     86 To change or set the executable to debug, go to Project > Properties >
     87 Debugging > Command. (As of Visual Studio 2022.)
     88 
     89 It should show the executable you are debugging. If it is empty or
     90 incorrect, manually add the correct path to the executable.
     91 
     92 Command line parameters and environment variables
     93 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     94 
     95 To change or set the command line options, go to Project > Properties >
     96 Debugging > Command Arguments.
     97 
     98 Some common options would be the URL of the file you want the browser to
     99 open as soon as it starts, starting the Profile Manager, or selecting a
    100 profile. You can also redirect the console output to a file (by adding
    101 "``> filename.txt``" for example, without the quotes).
    102 
    103 Customizing the debugger's variable value view
    104 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    105 
    106 You can customize how Visual Studio displays classes in the variable view.
    107 By default VS displays "{...}" and you need to click the small + icon
    108 to expand the members. You can change this behaviour, and make Visual
    109 Studio display whatever data member you want in whatever order, formatted
    110 however you like instead of just "{...}".
    111 
    112 You need to locate a file called "gecko.natvis" under toolkit/library.
    113 The file contains a list of types and how they should be displayed in
    114 the debugger. It is XML and after a little practice you should be well
    115 on your way.
    116 
    117 To understand the file in detail refer to `Create custom views of C++
    118 objects in the debugger using the Natvis framework
    119 <https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects>`__
    120 
    121 The file already comes with a number of entries that will make your life
    122 easier, like support for several string types. If you need to add a custom
    123 type, or want to change an existing entry for debugging purposes, you can
    124 easily edit the file. For your convenience it is included in all generated
    125 Visual Studio projects, and if you edit and save it within Visual Studio, it
    126 will pick up the changes immediately.
    127 
    128 Handling multiple processes in Visual Studio
    129 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    130 Turn off "Break all processes when one process breaks" to single step a single
    131 process.
    132 
    133 Turning off "Break all processes when one process breaks" adds "Step Into
    134 Current Process", "Step Over Current Process" and "Step Out Current Process" to
    135 the "Debug" menu.
    136 
    137 To single step a single process with the other processes paused:
    138 
    139 - Turn on "Break all processes when one process breaks"
    140 - Hit a breakpoint which stops all processes
    141 - Turn off "Break all processes when one process breaks"
    142 - Now using "Step Into Current Process" will leave the other processes stopped
    143  and just advance the current one.
    144 
    145 Obtaining ``stdout`` and other ``FILE`` handles
    146 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    147 
    148 Running the following command in the Command Window in Visual Studio
    149 returns the value of ``stdout``, which can be used with various
    150 debugging methods (such as ``nsGenericElement::List``) that take a
    151 ``FILE*`` param:
    152 
    153 .. code::
    154 
    155   Debug.EvaluateStatement {,,msvcr80d}(&__iob_func()[1])
    156 
    157 (Alternatively you can evaluate ``{,,msvcr80d}(&__iob_func()[1])`` in
    158 the Immediate window)
    159 
    160 Similarly, you can open a file on the disk using ``fopen``:
    161 
    162 .. code::
    163 
    164   >Debug.EvaluateStatement {,,msvcr80d}fopen("c:\\123", "w")
    165   0x10311dc0 { ..snip.. }
    166   >Debug.EvaluateStatement ((nsGenericElement*)0x03f0e710)->List((FILE*)0x10311dc0, 1)
    167   <void>
    168   >Debug.EvaluateStatement {,,msvcr80d}fclose((FILE*)0x10311dc0)
    169   0x00000000
    170 
    171 Note that you may not see the debugging output until you flush or close
    172 the file handle.
    173 
    174 Disabling ASSERTIONS
    175 ~~~~~~~~~~~~~~~~~~~~
    176 
    177 There are basically two ways to disable assertions. One requires setting
    178 an environment variable, while the other affects only the currently
    179 running program instance in memory.
    180 
    181 Environment variable
    182 ^^^^^^^^^^^^^^^^^^^^
    183 
    184 There is an environment variable that can disable breaking for
    185 assertions. This is how you would normally set it:
    186 
    187 .. code::
    188 
    189   set XPCOM_DEBUG_BREAK=warn
    190 
    191 The environment variable takes also other values besides ``warn``, see
    192 ``XPCOM_DEBUG_BREAK`` for more details.
    193 
    194 Note that unlike Unix, the default for Windows is not warn, it's to pop
    195 up a dialog. To set the environment variable for Visual Studio, use
    196 Project > Properties > Debugging > Environment and click the little box.
    197 Then use
    198 
    199 .. code::
    200 
    201   XPCOM_DEBUG_BREAK=warn
    202 
    203 Changing running code
    204 ^^^^^^^^^^^^^^^^^^^^^
    205 
    206 You normally shouldn't need to do this (just quit the application, set
    207 the environment variable described above, and run it again). And this
    208 can be **dangerous** (like **trashing your hard disc and corrupting your
    209 system**). So unless you feel comfortable with this, don't do it. **You
    210 have been warned!**
    211 
    212 It is possible to change the interrupt code in memory (which causes you
    213 to break into debugger) to be a NOP (no operation).
    214 
    215 You do this by running the program in the debugger until you hit an
    216 assertion. You should see some assembly code. One assembly code
    217 instruction reads "int 3". Check the memory address for that line. Now
    218 open memory view. Type/copy/drag the memory address of "int 3" into the
    219 memory view to get it to update on that part of the memory. Change the
    220 value of the memory to "90", close the memory view and hit "F5" to
    221 continue.
    222 
    223 Automatically handling ASSERTIONS without a debugger attached
    224 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    225 
    226 When an assertion happens and there is not a debugger attached, a small
    227 helper application
    228 (```windbgdlg.exe`` </En/Automatically_Handle_Failed_Asserts_in_Debug_Builds>`__)
    229 is run. That application can automatically select a response to the "Do
    230 you want to debug" dialog instead of prompting if you configure it, for
    231 more info, see
    232 ```windbgdlg.exe`` </En/Automatically_Handle_Failed_Asserts_in_Debug_Builds>`__.
    233 
    234 Debugging optimized builds
    235 ~~~~~~~~~~~~~~~~~~~~~~~~~~
    236 
    237 To effectively debug optimized builds, you should enable debugging
    238 information which effectively leaves the debug symbols in optimized code
    239 so you can still set breakpoints etc. Because the code is optimized,
    240 stepping through the code may occasionally provide small surprises when
    241 the debugger jumps over something.
    242 
    243 You need to make sure this configure parameter is set:
    244 
    245 .. code::
    246 
    247   ac_add_options --enable-debug
    248 
    249 You can also choose to include or exclude specific modules.
    250 
    251 Console debugging
    252 ~~~~~~~~~~~~~~~~~
    253 
    254 When printing to STDOUT from a content process, the console message will
    255 not appear on Windows. One way to view it is simply to disable e10s
    256 (``./mach run --disable-e10s``) but in order to debug with e10s enabled
    257 one can run
    258 
    259 ::
    260 
    261   ./mach run ... 2>&1 | tee
    262 
    263 It may also be necessary to disable the content sandbox
    264 (``MOZ_DISABLE_CONTENT_SANDBOX=1 ./mach run ...``).
    265 
    266 Running two instances of Mozilla simultaneously
    267 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    268 
    269 You can run two instances of Mozilla (e.g. debug and optimized)
    270 simultaneously by specifying the profile to use with the ``-P profile_name``
    271 command-line argument.
    272 
    273 Debugging JavaScript
    274 ~~~~~~~~~~~~~~~~~~~~
    275 
    276 You can use helper functions from
    277 `nsXPConnect.cpp <https://searchfox.org/mozilla-central/source/js/xpconnect/src/nsXPConnect.cpp>`__
    278 to inspect and modify the state of JavaScript code from the MSVS
    279 debugger.
    280 
    281 For example, to print current JavaScript stack to stdout, evaluate this
    282 in Immediate window:
    283 
    284 .. code::
    285 
    286   {,,xul}DumpJSStack()
    287 
    288 Visual Studio will show you something in the quick watch window, but
    289 not the stack, you have to look in the OS console for the output.
    290 
    291 Also this magical command only works when you have JS on the VS stack.
    292 
    293 Debugging minidumps
    294 ~~~~~~~~~~~~~~~~~~~
    295 
    296 See :ref:`debugging a minidump <Debugging A Minidump>`.
    297 
    298 Problems post-mortem debugging on Windows 7 SP1 x64?
    299 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    300 
    301 If you attempt to use ``NS_DebugBreak`` etc to perform post-mortem
    302 debugging on a 64bit Windows 7, but as soon as you try and continue
    303 debugging the program crashes with an Access Violation, you may be
    304 hitting a Windows bug relating to AVX support.  For more details,
    305 including a work-around see `this blog
    306 post <http://www.os2museum.com/wp/?p=960>`__ or `this social.msdn
    307 thread <http://social.msdn.microsoft.com/Forums/vstudio/en-US/392ca62c-e502-42d9-adbc-b4e22d5da0c3/jit-debugging-32bit-app-crashing-with-access-violation>`__.
    308 (And just in-case those links die, the work-around is to execute
    309 
    310 ::
    311 
    312   bcdedit /set xsavedisable 1
    313 
    314 from an elevated command-prompt to disable AVX support.)
    315 
    316 Got a tip?
    317 ~~~~~~~~~~
    318 
    319 If you think you know a cool Mozilla debugging trick, feel free to
    320 discuss it with `#developers <https://chat.mozilla.org/#/room/#developers:mozilla.org>`__ and
    321 then post it here.
    322 
    323 .. |Screenshot of disabling assertions| image:: https://developer.mozilla.org/@api/deki/files/420/=Win32-debug-nop.png
    324   :class: internal