tor-browser

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

debugging_firefox_with_gdb.rst (10782B)


      1 Debugging Firefox with GDB
      2 ==========================
      3 
      4 This page details how you can more easily debug Firefox with gdb. :ref:`rr
      5 <Debugging Firefox with rr>` is most often a better choice to debug a problem,
      6 but sometimes it isn't possible to use it, such as attempting to reproduce a
      7 race condition or when performance is important to reproduce an issue. ``rr``
      8 chaos mode allows reproducing a lot of issues though, and should be tried.
      9 
     10 Where can I find general gdb documentation?
     11 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     12 
     13 Using GDB is beyond the scope of this document. Documentation is likely
     14 available on your system if you have GDB installed, in the form of
     15 **info,** **man** pages, or the gnome help browser. Additionally, you
     16 can use a graphical front-end to GDB like
     17 `ddd <https://www.gnu.org/software/ddd/>`__ or
     18 `insight <https://sourceware.org/insight/>`__. For more information see
     19 https://sourceware.org/gdb/current/onlinedocs/gdb/
     20 
     21 How to debug Firefox with gdb?
     22 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     23 
     24 Firefox is a multiprocess application, with a parent process, and several child
     25 processes, each specialized and sandboxed differently.
     26 
     27 .. code:: bash
     28 
     29   $ ./mach run --debugger=gdb
     30 
     31 allows running Firefox in gdb, and debug the parent process. You can substitute
     32 ``run`` with another action, such as ``test``, ``mochitest``, ``xpcshell-test``,
     33 etc.
     34 
     35 Debugging child processes can be done by attaching the debugger.
     36 
     37 .. code:: bash
     38 
     39   $ gdb --pid <pid>
     40 
     41 There's a number of ways to find the PID of a process: hovering over a tab for a
     42 content process, opening ``about:processes``, using ``ps ... | grep firefox`` on
     43 the command line, etc.
     44 
     45 Sometimes, it is desirable to attach to a child process at startup, to diagnose
     46 something very close to the start of the process. Setting the environment
     47 variable ``MOZ_DEBUG_CHILD_PROCESS=10`` will make each new process print an few
     48 informative lines, including the process type and its PID. The process with then
     49 sleep for a number of seconds equal to the value of the environment variable,
     50 allowing to attach a debugger.
     51 
     52 .. code:: bash
     53 
     54   $ MOZ_DEBUG_CHILD_PROCESS=10 ./mach run
     55   ...
     56   ...
     57   ...
     58 
     59   CHILDCHILDCHILDCHILD (process type tab)
     60   debug me @ 65230
     61 
     62   ...
     63   ...
     64   ...
     65 
     66 Attaching gdb to Firefox might fail on Linux distributions that enable common
     67 kernel hardening features such as the Yama security module. If you encounter the
     68 following error when attaching:
     69 
     70 .. code:: bash
     71 
     72   $ gdb --pid <pid>
     73   ...
     74   ...
     75 
     76   Attaching to process <pid>
     77   ptrace: Operation not permitted.
     78 
     79 Check the contents of `/proc/sys/kernel/yama/ptrace_scope`. If  it set to `1`
     80 you won't be able to attach to processes, set it to `0` from a root shell:
     81 
     82 .. code:: bash
     83 
     84  \# echo 0 > /proc/sys/kernel/yama/ptrace_scope
     85 
     86 If you still can't attach check your setup carefully. Do not, under any
     87 circumstances, run gdb as root. Since gdb can execute arbitrary code and spawn
     88 shells it can be extremely dangerous to use it with root permissions.
     89 
     90 
     91 Advanced gdb configuration
     92 ~~~~~~~~~~~~~~~~~~~~~~~~~~
     93 
     94 The preferred method, is using the
     95 :ref:`mach` command-line tool to run the
     96 debugger, which can bypass several optional defaults. Use "mach help
     97 run" to get more details. If inside the source directory, you would use
     98 "./mach". Please note that
     99 :ref:`mach is aware of mozconfigs <Configuring Build Options>`.
    100 
    101 .. code:: bash
    102 
    103   $ ./mach run --debug [arguments to pass to firefox]
    104 
    105 If you need to direct arguments to gdb, you can use '--debugger-args'
    106 options via the command line parser, taking care to adhere to shell
    107 splitting rules. For example, if you wanted to run the command 'show
    108 args' when gdb starts, you would use:
    109 
    110 .. code:: bash
    111 
    112   $ ./mach run --debug --debugger-args "-ex 'show args'"
    113 
    114 Alternatively, you can run gdb directly against Firefox. However, you
    115 won't get some of the more useful capabilities this way. For example,
    116 mach sets an environment variable (see below) to stop the JS engine from
    117 generating synthetic segfaults to support the slower script dialoging
    118 mechanism.
    119 
    120 .. code::
    121 
    122   (gdb) $OBJDIR/dist/bin/firefox
    123 
    124 How to debug a Firefox in the field (not compiled on the host)
    125 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    126 
    127 If you need to attach to a Firefox process live on a machine, and this Firefox
    128 was built by Mozilla, or by certain Linux distros, it's possible to get symbols
    129 and sources using the Mozilla symbol server, see :ref:`this section <Downloading
    130 symbols on Linux / Mac OS X>` for setup instructions, it's just a matter of
    131 sourcing a python script in ``.gdbinit``.
    132 
    133 Debugging then works as usual, except the build probably has a very high
    134 optimization level.
    135 
    136 How do I pass arguments in prun?
    137 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    138 
    139 Set the arguments in GDB before calling prun. Here's an example on how
    140 to do that:
    141 
    142 .. code::
    143 
    144   (gdb) set args https://www.mozilla.org
    145   (gdb) prun
    146 
    147 Why breakpoints seem to not be hit?
    148 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    149 
    150 The most likely cause is that `gdb` hasn't been attached to the process in which
    151 the code to diagnose is ran. Enabling the relevant `MOZ_LOG` modules can help,
    152 since by default it prints the process type and pid of all logging statements.
    153 
    154 `break list` will display a list of breakpoints, and whether or not they're
    155 enabled. C++ namespaces need to be specified entirely, and it's sometimes hard
    156 to break in lambda. Breaking by line number is an alternative strategy that
    157 often works in this case.
    158 
    159 How do I display an nsString?
    160 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    161 
    162 .. code::
    163 
    164   (gdb) p ToNewCString(string);
    165 
    166 This leaks a bit of memory but it doesn't really matter.
    167 
    168 How do I determine the concrete type of an object pointed to by an interface pointer?
    169 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    170 
    171 You can determine the concrete type of any object pointed to, by an
    172 XPCOM interface pointer, by looking at the mangled name of the symbol
    173 for the object's vtable:
    174 
    175 .. code::
    176 
    177   (gdb) p aKidFrame
    178   $1 = (nsIFrame *) 0x85058d4
    179   (gdb) x/wa *(void**)aKidFrame
    180   0x4210d380 <__vt_14nsRootBoxFrame>: 0x0
    181   (gdb) p *(nsRootBoxFrame*)aKidFrame
    182    [ all the member variables of aKidFrame ]
    183 
    184 Or use the gdb command ``set print object on``.
    185 
    186 How can I debug JavaScript from gdb?
    187 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    188 
    189 If you have JavaScript Engine code on the stack, you'll probably want a
    190 JS stack in addition to the C++ stack.
    191 
    192 .. code::
    193 
    194   (gdb) call DumpJSStack()
    195 
    196 Please note that if `gdb` has been attached to a process, the stack might be
    197 printed in the terminal window in which Firefox was started.
    198 
    199 See
    200 `this MDN page
    201 <https://developer.mozilla.org/en-US/docs/Mozilla/Debugging/Debugging_JavaScript>`__
    202 for more JS debugging tricks.
    203 
    204 How can I debug race conditions
    205 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    206 
    207 Try :ref:`rr <Debugging Firefox with rr>` first. If this doesn't work, good
    208 luck, maybe try :ref:`logging <Gecko Logging>` or sprinkling assertions.
    209 
    210 I keep getting a SIGSYS, or SIGSEGV in JS/JIT code under gdb even though there is no crash when gdb is not attached.  How do I fix it?
    211 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    212 
    213 Allow gdb to read mozilla-central's .gdbinit, located at `build/.gdbinit`. In
    214 your own `.gdbinit`, add the line:
    215 
    216  .. code::
    217 
    218     add-auto-load-safe-path /path/to/mozilla-central
    219 
    220 How do I get useful stack traces inside system libraries?
    221 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    222 
    223 Many Linux distributions provide separate packages with debugging
    224 information for system libraries, such as gdb, Valgrind, profiling
    225 tools, etc., to give useful stack traces via system libraries.
    226 
    227 The modern way to do this is to enable ``debuginfod``. This can be done by adding:
    228 
    229  .. code::
    230 
    231    set debuginfod enabled on
    232 
    233 in your ``.gdbinit``, but there might be distro-specific instructions.
    234 Alternatively, you can install the packages that contain the debug symbols for
    235 the libraries you want to debug.
    236 
    237 When using ``debuginfod``, the correct information will be downloaded
    238 automatically when needed (and subsequently cached).
    239 
    240 If you're not sure what to use, there's a federated debuginfod server that
    241 provides debug information for most mainstream distributions. You can use it
    242 by adding the following line to your ``.gdbinit`` file:
    243 
    244  .. code::
    245 
    246    set debuginfod urls "https://debuginfod.elfutils.org/"
    247 
    248 Keep in mind that it might take a while to download debug information the
    249 very first time. This queries all the servers of multiple distributions
    250 sequentially and debug information tends to be large. It will be cached for the
    251 next run though.
    252 
    253 Fedora
    254 ^^^^^^
    255 
    256 On Fedora, you need to enable the debuginfo repositories, as the
    257 packages are in separate repositories. Enable them permanently, so when
    258 you get updates you also get security updates for these packages. A way
    259 to do this is edit ``/etc/yum.repos.d/fedora.repo`` and
    260 ``fedora-updates.repo`` to change the ``enabled=0`` line in the
    261 debuginfo section to ``enabled=1``. This may then flag a conflict when
    262 upgrading to a new distribution version. You would the need to perform
    263 this edit again.
    264 
    265 You can finally install debuginfo packages with yum or other package
    266 management tools. The best way is install the ``yum-utils`` package, and
    267 then use the ``debuginfo-install`` command to install all the debuginfo:
    268 
    269 .. code:: bash
    270 
    271   $ yum install yum-utils
    272   $ debuginfo-install firefox
    273 
    274 This can be done manually using:
    275 
    276 .. code:: bash
    277 
    278    $ yum install GConf2-debuginfo ORBit2-debuginfo atk-debuginfo \
    279    cairo-debuginfo dbus-debuginfo expat-debuginfo \
    280    fontconfig-debuginfo freetype-debuginfo gcc-debuginfo glib2-debuginfo \
    281    glibc-debuginfo gnome-vfs2-debuginfo gtk2-debuginfo gtk2-engines-debuginfo \
    282    hal-debuginfo libX11-debuginfo libXcursor-debuginfo libXext-debuginfo \
    283    libXfixes-debuginfo libXft-debuginfo libXi-debuginfo libXinerama-debuginfo \
    284    libXrender-debuginfo libbonobo-debuginfo libgnome-debuginfo \
    285    libselinux-debuginfo pango-debuginfo popt-debuginfo scim-bridge-debuginfo
    286 
    287 Disabling multiprocess
    288 ~~~~~~~~~~~~~~~~~~~~~~
    289 
    290 ``mach run`` and ``mach test`` both accept a ``--disable-e10s`` argument. Some
    291 debuggers can't catch child-process crashes without it. This is sometimes a
    292 viable alternative to attaching, but these days it changes enough thing that
    293 it's not always a usable option.
    294 
    295 See also
    296 ~~~~~~~~~
    297 
    298 
    299 -  `Mike Conley's blog post <https://mikeconley.ca/blog/2014/04/25/electrolysis-debugging-child-processes-of-content-for-make-benefit-glorious-browser-of-firefox>`__
    300 -  `Performance tools <https://wiki.mozilla.org/Performance:Tools>`__
    301 -  `Fun with
    302   gdb <https://blog.mozilla.com/sfink/2011/02/22/fun-with-gdb/>`__ by
    303   Steve Fink