summaryrefslogtreecommitdiffstats
path: root/docs/contributing/debugging/debugging_firefox_with_gdb.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/contributing/debugging/debugging_firefox_with_gdb.rst')
-rw-r--r--docs/contributing/debugging/debugging_firefox_with_gdb.rst303
1 files changed, 303 insertions, 0 deletions
diff --git a/docs/contributing/debugging/debugging_firefox_with_gdb.rst b/docs/contributing/debugging/debugging_firefox_with_gdb.rst
new file mode 100644
index 0000000000..9572ce8e18
--- /dev/null
+++ b/docs/contributing/debugging/debugging_firefox_with_gdb.rst
@@ -0,0 +1,303 @@
+Debugging Firefox with GDB
+==========================
+
+This page details how you can more easily debug Firefox with gdb. :ref:`rr
+<Debugging Firefox with rr>` is most often a better choice to debug a problem,
+but sometimes it isn't possible to use it, such as attempting to reproduce a
+race condition or when performance is important to reproduce an issue. ``rr``
+chaos mode allows reproducing a lot of issues though, and should be tried.
+
+Where can I find general gdb documentation?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Using GDB is beyond the scope of this document. Documentation is likely
+available on your system if you have GDB installed, in the form of
+**info,** **man** pages, or the gnome help browser. Additionally, you
+can use a graphical front-end to GDB like
+`ddd <https://www.gnu.org/software/ddd/>`__ or
+`insight <https://sourceware.org/insight/>`__. For more information see
+https://sourceware.org/gdb/current/onlinedocs/gdb/
+
+How to debug Firefox with gdb?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Firefox is a multiprocess application, with a parent process, and several child
+processes, each specialized and sandboxed differently.
+
+.. code:: bash
+
+ $ ./mach run --debugger=gdb
+
+allows running Firefox in gdb, and debug the parent process. You can substitute
+``run`` with another action, such as ``test``, ``mochitest``, ``xpcshell-test``,
+etc.
+
+Debugging child processes can be done by attaching the debugger.
+
+.. code:: bash
+
+ $ gdb --pid <pid>
+
+There's a number of ways to find the PID of a process: hovering over a tab for a
+content process, opening ``about:processes``, using ``ps ... | grep firefox`` on
+the command line, etc.
+
+Sometimes, it is desirable to attach to a child process at startup, to diagnose
+something very close to the start of the process. Setting the environment
+variable ``MOZ_DEBUG_CHILD_PROCESS=10`` will make each new process print an few
+informative lines, including the process type and its PID. The process with then
+sleep for a number of seconds equal to the value of the environment variable,
+allowing to attach a debugger.
+
+.. code:: bash
+
+ $ MOZ_DEBUG_CHILD_PROCESS=10 ./mach run
+ ...
+ ...
+ ...
+
+ CHILDCHILDCHILDCHILD (process type tab)
+ debug me @ 65230
+
+ ...
+ ...
+ ...
+
+Attaching gdb to Firefox might fail on Linux distributions that enable common
+kernel hardening features such as the Yama security module. If you encounter the
+following error when attaching:
+
+.. code:: bash
+
+ $ gdb --pid <pid>
+ ...
+ ...
+
+ Attaching to process <pid>
+ ptrace: Operation not permitted.
+
+Check the contents of `/proc/sys/kernel/yama/ptrace_scope`. If it set to `1`
+you won't be able to attach to processes, set it to `0` from a root shell:
+
+.. code:: bash
+
+ \# echo 0 > /proc/sys/kernel/yama/ptrace_scope
+
+If you still can't attach check your setup carefully. Do not, under any
+circumstances, run gdb as root. Since gdb can execute arbitrary code and spawn
+shells it can be extremely dangerous to use it with root permissions.
+
+
+Advanced gdb configuration
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The preferred method, is using the
+:ref:`mach` command-line tool to run the
+debugger, which can bypass several optional defaults. Use "mach help
+run" to get more details. If inside the source directory, you would use
+"./mach". Please note that
+:ref:`mach is aware of mozconfigs <Configuring Build Options>`.
+
+.. code:: bash
+
+ $ ./mach run --debug [arguments to pass to firefox]
+
+If you need to direct arguments to gdb, you can use '--debugger-args'
+options via the command line parser, taking care to adhere to shell
+splitting rules. For example, if you wanted to run the command 'show
+args' when gdb starts, you would use:
+
+.. code:: bash
+
+ $ ./mach run --debug --debugger-args "-ex 'show args'"
+
+Alternatively, you can run gdb directly against Firefox. However, you
+won't get some of the more useful capabilities this way. For example,
+mach sets an environment variable (see below) to stop the JS engine from
+generating synthetic segfaults to support the slower script dialoging
+mechanism.
+
+.. code::
+
+ (gdb) $OBJDIR/dist/bin/firefox
+
+How to debug a Firefox in the field (not compiled on the host)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you need to attach to a Firefox process live on a machine, and this Firefox
+was built by Mozilla, or by certain Linux distros, it's possible to get symbols
+and sources using the Mozilla symbol server, see :ref:`this section <Downloading
+symbols on Linux / Mac OS X>` for setup instructions, it's just a matter of
+sourcing a python script in ``.gdbinit``.
+
+Debugging then works as usual, except the build probably has a very high
+optimization level.
+
+How do I pass arguments in prun?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Set the arguments in GDB before calling prun. Here's an example on how
+to do that:
+
+.. code::
+
+ (gdb) set args https://www.mozilla.org
+ (gdb) prun
+
+Why breakpoints seem to not be hit?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The most likely cause is that `gdb` hasn't been attached to the process in which
+the code to diagnose is ran. Enabling the relevant `MOZ_LOG` modules can help,
+since by default it prints the process type and pid of all logging statements.
+
+`break list` will display a list of breakpoints, and whether or not they're
+enabled. C++ namespaces need to be specified entirely, and it's sometimes hard
+to break in lambda. Breaking by line number is an alternative strategy that
+often works in this case.
+
+How do I display an nsString?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code::
+
+ (gdb) p ToNewCString(string);
+
+This leaks a bit of memory but it doesn't really matter.
+
+How do I determine the concrete type of an object pointed to by an interface pointer?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can determine the concrete type of any object pointed to, by an
+XPCOM interface pointer, by looking at the mangled name of the symbol
+for the object's vtable:
+
+.. code::
+
+ (gdb) p aKidFrame
+ $1 = (nsIFrame *) 0x85058d4
+ (gdb) x/wa *(void**)aKidFrame
+ 0x4210d380 <__vt_14nsRootBoxFrame>: 0x0
+ (gdb) p *(nsRootBoxFrame*)aKidFrame
+ [ all the member variables of aKidFrame ]
+
+Or use the gdb command ``set print object on``.
+
+How can I debug JavaScript from gdb?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you have JavaScript Engine code on the stack, you'll probably want a
+JS stack in addition to the C++ stack.
+
+.. code::
+
+ (gdb) call DumpJSStack()
+
+Please note that if `gdb` has been attached to a process, the stack might be
+printed in the terminal window in which Firefox was started.
+
+See
+`this MDN page
+<https://developer.mozilla.org/en-US/docs/Mozilla/Debugging/Debugging_JavaScript>`__
+for more JS debugging tricks.
+
+How can I debug race conditions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Try :ref:`rr <Debugging Firefox with rr>` first. If this doesn't work, good
+luck, maybe try :ref:`logging <Gecko Logging>` or sprinkling assertions.
+
+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?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Allow gdb to read mozilla-central's .gdbinit, located at `build/.gdbinit`. In
+your own `.gdbinit`, add the line:
+
+ .. code::
+
+ add-auto-load-safe-path /path/to/mozilla-central
+
+How do I get useful stack traces inside system libraries?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Many Linux distributions provide separate packages with debugging
+information for system libraries, such as gdb, Valgrind, profiling
+tools, etc., to give useful stack traces via system libraries.
+
+The modern way to do this is to enable ``debuginfod``. This can be done by adding:
+
+ .. code::
+
+ set debuginfod enabled on
+
+in your ``.gdbinit``, but there might be distro-specific instructions.
+Alternatively, you can install the packages that contain the debug symbols for
+the libraries you want to debug.
+
+When using ``debuginfod``, the correct information will be downloaded
+automatically when needed (and subsequently cached).
+
+If you're not sure what to use, there's a federated debuginfod server that
+provides debug information for most mainstream distributions. You can use it
+by adding the following line to your ``.gdbinit`` file:
+
+ .. code::
+
+ set debuginfod urls "https://debuginfod.elfutils.org/"
+
+Keep in mind that it might take a while to download debug information the
+very first time. This queries all the servers of multiple distributions
+sequentially and debug information tends to be large. It will be cached for the
+next run though.
+
+Fedora
+^^^^^^
+
+On Fedora, you need to enable the debuginfo repositories, as the
+packages are in separate repositories. Enable them permanently, so when
+you get updates you also get security updates for these packages. A way
+to do this is edit ``/etc/yum.repos.d/fedora.repo`` and
+``fedora-updates.repo`` to change the ``enabled=0`` line in the
+debuginfo section to ``enabled=1``. This may then flag a conflict when
+upgrading to a new distribution version. You would the need to perform
+this edit again.
+
+You can finally install debuginfo packages with yum or other package
+management tools. The best way is install the ``yum-utils`` package, and
+then use the ``debuginfo-install`` command to install all the debuginfo:
+
+.. code:: bash
+
+ $ yum install yum-utils
+ $ debuginfo-install firefox
+
+This can be done manually using:
+
+.. code:: bash
+
+ $ yum install GConf2-debuginfo ORBit2-debuginfo atk-debuginfo \
+ cairo-debuginfo dbus-debuginfo expat-debuginfo \
+ fontconfig-debuginfo freetype-debuginfo gcc-debuginfo glib2-debuginfo \
+ glibc-debuginfo gnome-vfs2-debuginfo gtk2-debuginfo gtk2-engines-debuginfo \
+ hal-debuginfo libX11-debuginfo libXcursor-debuginfo libXext-debuginfo \
+ libXfixes-debuginfo libXft-debuginfo libXi-debuginfo libXinerama-debuginfo \
+ libXrender-debuginfo libbonobo-debuginfo libgnome-debuginfo \
+ libselinux-debuginfo pango-debuginfo popt-debuginfo scim-bridge-debuginfo
+
+Disabling multiprocess
+~~~~~~~~~~~~~~~~~~~~~~
+
+``mach run`` and ``mach test`` both accept a ``--disable-e10s`` argument. Some
+debuggers can't catch child-process crashes without it. This is sometimes a
+viable alternative to attaching, but these days it changes enough thing that
+it's not always a usable option.
+
+See also
+~~~~~~~~~
+
+
+- `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>`__
+- `Performance tools <https://wiki.mozilla.org/Performance:Tools>`__
+- `Fun with
+ gdb <https://blog.mozilla.com/sfink/2011/02/22/fun-with-gdb/>`__ by
+ Steve Fink