forked from mirrors/gecko-dev
This can cause issues when Mach from sourcetree A fails when used in sourcetree B because an expected file is missing. Differential Revision: https://phabricator.services.mozilla.com/D133951
503 lines
19 KiB
ReStructuredText
503 lines
19 KiB
ReStructuredText
Debugging Firefox with GDB
|
|
==========================
|
|
|
|
+--------------------------------------------------------------------+
|
|
| This page is an import from MDN and the contents might be outdated |
|
|
+--------------------------------------------------------------------+
|
|
|
|
This page details how you can more easily debug Firefox and work around
|
|
some GDB problems.
|
|
|
|
Use GDB 5, or higher. A more recent version of GDB can be obtained from
|
|
`sourceware <https://sourceware.org/gdb/>`__ or your Linux distro repo.
|
|
If you are running less than 256 MB of RAM, be sure to see `Using gdb on
|
|
wimpy computers <https://developer.mozilla.org/en/Using_gdb_on_wimpy_computers>`__.
|
|
|
|
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 do I run Firefox under gdb?
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
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 <mach_and_mozconfigs>`.
|
|
|
|
.. 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 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
|
|
|
|
How do I set a breakpoint in a library that hasn't been loaded?
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
GDB 6.1 and above has support for "pending breakpoints". This is
|
|
controlled by the "``set breakpoint pending``" setting, and is enabled
|
|
by default. If a breakpoint cannot be immediately resolved, it will be
|
|
re-checked each time a shared library is loaded, by the process being
|
|
debugged. If your GDB is older than this, you should upgrade.
|
|
|
|
In older versions, there isn't a way to set breakpoints in a library
|
|
that has not yet been loaded. See more on `setting a breakpoint when a
|
|
component is
|
|
loaded <#How_do_I_set_a_breakpoint_when_a_component_is_loaded.3F>`__. If
|
|
you have to set a breakpoint you can set a breakpoint in ``_dl_open``.
|
|
This function is called when a new library is loaded, when you can
|
|
finally set your breakpoint.
|
|
|
|
How do I set a breakpoint when a component is loaded?
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
In Firefox Version 57 (and possibly earlier) XPCOM_BREAK_ON_LOAD does
|
|
not seem to exist.
|
|
|
|
There's a facility in XPCOM which allows you to set an environment
|
|
variable to drop into the debugger when loading a certain component. You
|
|
have to set ``XPCOM_BREAK_ON_LOAD`` variable before you run Firefox,
|
|
setting it to a string containing the names of libraries you want to
|
|
load. For example, if you wish to stop when a library named ``raptor``
|
|
or ``necko`` is loaded, you set the variable to ``raptor:necko``. Here's
|
|
an example:
|
|
|
|
.. code::
|
|
|
|
(gdb) set env XPCOM_BREAK_ON_LOAD raptor:necko
|
|
(gdb) prun
|
|
|
|
Why can't I set a breakpoint?
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
You probably can't set a breakpoint because its library hasn't been
|
|
loaded. Most Firefox functionality is in libraries loaded mid-way
|
|
through the ``main()``\ function. If you break on ``main(),``\ and step
|
|
through until the libraries are loaded, with a call to
|
|
``InitCOMGlue()``, you should be able to set breakpoints on many more
|
|
symbols, source files, and continue running.
|
|
|
|
.. code::
|
|
|
|
(gdb) break main
|
|
(gdb) run
|
|
Breakpoint 1, main(argc=4, argv=0x7fffffffde98, envp=0x7ffffffffdec0) .....
|
|
256 {
|
|
(gdb) next
|
|
...
|
|
293 nsresult rv = InitXPCOMGlue()
|
|
(gdb) next
|
|
|
|
If you still can't set the breakpoints, you need to confirm the library
|
|
has loaded. You can't proceed until the library loads. See more on
|
|
`loading shared libraries <#How_do_I_load_shared_libraries.3F>`__. If
|
|
you wish to break as soon as the library is loaded, see the section on
|
|
`breaking when a component is
|
|
loaded <#How_do_I_set_a_breakpoint_when_a_component_is_loaded.3F>`__ and
|
|
`breaking on a library
|
|
load <#How_do_I_set_a_breakpoint_when_a_component_is_loaded.3F>`__.
|
|
|
|
How do I display PRUnichar's?
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
One suggestion is this:
|
|
|
|
.. code::
|
|
|
|
(gdb) print ((PRUnichar*)uri.mBuffer)[0]@16
|
|
$47 = {114, 100, 102, 58, 110, 117, 108, 108, 0, 0, 8, 0, 0, 0, 37432,
|
|
16514}
|
|
|
|
|
|
|
|
.. code::
|
|
|
|
(gdb) print aURI
|
|
$1 = (const PRUnichar *) 0x855e6e0
|
|
(gdb) x/32ch aURI
|
|
0x855e6e0: 104 'h' 116 't' 116 't' 112 'p' 58 ':' 47 '/' 47 '/' 119 'w'
|
|
0x855e6f0: 119 'w' 119 'w' 46 '.' 109 'm' 111 'o' 122 'z' 105 'i' 108 'l'
|
|
0x855e700: 108 'l' 97 'a' 46 '.' 111 'o' 114 'r' 103 'g' 47 '/' 115 's'
|
|
0x855e710: 116 't' 97 'a' 114 'r' 116 't' 47 '/' 0 '\0' 25 '\031' 0 '\0'
|
|
(gdb)
|
|
|
|
- Define helper functions in your .gdbinit
|
|
|
|
.. code::
|
|
|
|
# Define a "pu" command to display PRUnichar * strings (100 chars max)
|
|
# Also allows an optional argument for how many chars to print as long as
|
|
# it's less than 100.
|
|
def pu
|
|
set $uni = $arg0
|
|
if $argc == 2
|
|
set $limit = $arg1
|
|
if $limit > 100
|
|
set $limit = 100
|
|
end
|
|
else
|
|
set $limit = 100
|
|
end
|
|
# scratch array with space for 100 chars plus null terminator. Make
|
|
# sure to not use ' ' as the char so this copy/pastes well.
|
|
set $scratch = "____________________________________________________________________________________________________"
|
|
set $i = 0
|
|
set $scratch_idx = 0
|
|
while (*$uni && $i++ < $limit)
|
|
if (*$uni < 0x80)
|
|
set $scratch[$scratch_idx++] = *(char*)$uni++
|
|
else
|
|
if ($scratch_idx > 0)
|
|
set $scratch[$scratch_idx] = '\0'
|
|
print $scratch
|
|
set $scratch_idx = 0
|
|
end
|
|
print /x *(short*)$uni++
|
|
end
|
|
end
|
|
if ($scratch_idx > 0)
|
|
set $scratch[$scratch_idx] = '\0'
|
|
print $scratch
|
|
end
|
|
end
|
|
|
|
# Define a "ps" command to display subclasses of nsAC?String. Note that
|
|
# this assumes strings as of Gecko 1.9 (well, and probably a few
|
|
# releases before that as well); going back far enough will get you
|
|
# to string classes that this function doesn't work for.
|
|
def ps
|
|
set $str = $arg0
|
|
if (sizeof(*$str.mData) == 1 && ($str.mFlags & 1) != 0)
|
|
print $str.mData
|
|
else
|
|
pu $str.mData $str.mLength
|
|
end
|
|
end
|
|
|
|
`This is hard. Give me a .gdbinit that already has the
|
|
functions. <#This_is_hard._Give_me_a_.gdbinit_that_works.>`__
|
|
|
|
- Define a small helper function "punichar" in #ifdef NS_DEBUG code
|
|
somewhere.
|
|
|
|
How do I display an nsString?
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
You can call the ToNewCString() method on the nsString. It leaks a
|
|
little memory but it shouldn't hurt anything if you only do it a few
|
|
times in one gdb session. (via akkana@netscape.com)
|
|
|
|
.. code::
|
|
|
|
(gdb) p string.ToNewCString()
|
|
|
|
Another method (via bent) is the following (replace ``n`` with: the
|
|
returned length of your string):
|
|
|
|
.. code::
|
|
|
|
(gdb) p string.Length()
|
|
$1 = n
|
|
(gdb) x/ns string.BeginReading()
|
|
|
|
You can of course use any of the above unichar-printing routines instead
|
|
of x/s.
|
|
|
|
This is hard. Give me a .gdbinit that works.
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
See `Boris Zbarsky's
|
|
.gdbinit <http://web.mit.edu/bzbarsky/www/gdbinit>`__. It contained
|
|
several function definitions including:
|
|
|
|
- "prun" to start the browser and disable library loading.
|
|
- "pu" which will display a (PRUnichar \*) string.
|
|
- "ps" which will display a nsString.
|
|
|
|
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 ]
|
|
|
|
If you're using gcc 3.x, the output is slightly different from the gcc
|
|
2.9x output above. Pay particular attention to the vtable symbol, in
|
|
this case ``__vt_14nsRootBoxFrame``. You won't get anything useful if
|
|
the shared library containing the object is not loaded. See `How do I
|
|
load shared libraries? <#How_do_I_load_shared_libraries.3F>`__ and `How
|
|
do I see what libraries I already have
|
|
loaded? <#How_do_I_see_what_libraries_I_already_have_loaded.3F>`__
|
|
|
|
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()
|
|
|
|
See `https://developer.mozilla.org/en-US/docs/Mozilla/Debugging/Debugging_JavaScript <https://developer.mozilla.org/en-US/docs/Mozilla/Debugging/Debugging_JavaScript>`__
|
|
for more JS debugging tricks.
|
|
|
|
How can I debug race conditions and/or how can I make something different happen at NS_ASSERTION time?
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
| [submitted by Dan Mosedale]
|
|
| As Linux is unable to generate useful core files for multi-threaded
|
|
applications, tracking down race-conditions which don't show up under
|
|
the debugger can be a bit tricky. Unless you've given the
|
|
``--enable-crash-on-assert`` switch to ``configure``, you can now
|
|
change the behavior of ``NS_ASSERTION`` (nsDebug::Break) using the
|
|
``XPCOM_DEBUG_BREAK`` environment variable.
|
|
|
|
How do I run the debugger in emacs/xemacs?
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Emacs and XEmacs contain modes for doing visual debugging. However, you
|
|
might want to set up environment variables, specifying the loading of
|
|
symbols and components. The easiest way to set up these is to use the
|
|
``run-mozilla.sh`` script, located in the dist/bin directory of your
|
|
build. This script sets up the environment to run the editor, shell,
|
|
debugger, or defining a preferred setup and running any commands you
|
|
wish. For example:
|
|
|
|
.. code:: bash
|
|
|
|
$ ./run-mozilla.sh /bin/bash
|
|
MOZILLA_FIVE_HOME=/home/USER/src/mozilla/build/dist/bin
|
|
LD_LIBRARY_PATH=/home/USER/src/mozilla/build/dist/bin
|
|
LIBRARY_PATH=/home/USER/src/mozilla/build/dist/bin
|
|
SHLIB_PATH=/home/USER/src/mozilla/build/dist/bin
|
|
LIBPATH=/home/USER/src/mozilla/build/dist/bin
|
|
ADDON_PATH=/home/USER/src/mozilla/build/dist/bin
|
|
MOZ_PROGRAM=/bin/bash
|
|
MOZ_TOOLKIT=
|
|
moz_debug=0
|
|
moz_debugger=
|
|
|
|
GDB 5 used to work for me, but now Firefox won't start. What can I do?
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
A recent threading change (see `bug
|
|
57051 <https://bugzilla.mozilla.org/show_bug.cgi?id=57051>`__ for
|
|
details) caused a problem on some systems. Firefox would get part-way
|
|
through its initialization, then stop before showing a window. A recent
|
|
change to gdb has fixed this. Download and build `the latest version of
|
|
Insight <https://sources.redhat.com/insight/>`__, or if you don't want a
|
|
GUI, `the latest version of gdb <https://sources.redhat.com/gdb/>`__.
|
|
|
|
"run" or "prun" in GDB fails with "error in loading shared libraries."
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Running mozilla-bin inside GDB fails with an error message like:
|
|
|
|
.. code::
|
|
|
|
Starting program:
|
|
/u/dmose/s/mozilla/mozilla-all/mozilla/dist/bin/./mozilla-bin
|
|
/u/dmose/s/mozilla/mozilla-all/mozilla/dist/bin/./mozilla-bin: error
|
|
in loading shared libraries: libraptorgfx.so: cannot open shared
|
|
object file: No such file or directory
|
|
|
|
Your LD_LIBRARY_PATH is probably being reset by your .cshrc or .profile.
|
|
From the GDB manual:
|
|
|
|
*\*Warning:\* GDB runs your program using the shell indicated by your
|
|
'SHELL' environment variable if it exists (or '/bin/sh' if not). If your
|
|
'SHELL' variable names a shell that runs an initialization file -- such
|
|
as '.cshrc' for C-shell, or '.bashrc' for BASH--any variables you set in
|
|
that file affect your program. You may wish to move the setting of
|
|
environment variables to files that are only run when you sign on, such
|
|
as '.login' or '.profile'.*
|
|
|
|
Debian's GDB doesn't work. What do I do?
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Debian's unstable distribution currently uses glibc 2.1 and GDB 4.18.
|
|
However, there is no package of GDB for Debian with the appropriate
|
|
threads patches that will work with glibc 2.1. I was able to get this to
|
|
work by getting the GDB 4.18 RPM from Red Hat's rawhide server and
|
|
installing that. It has all of the patches necessary for debugging
|
|
threaded software. These fixes are expected to be merged into GDB, which
|
|
will fix the problem for Debian Linux. (via `Bruce
|
|
Mitchener <mailto:bruce@cybersight.com>`__)
|
|
|
|
Firefox is aborting. Where do I set a breakpoint to find out where it is exiting?
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
On Linux there are two possible symbols that are causing this:
|
|
``PR_ASSERT()`` and ``NS_ASSERTION()``. To see where it's asserting you
|
|
can stop at two places:
|
|
|
|
.. code::
|
|
|
|
(gdb) b abort
|
|
(gdb) b exit
|
|
|
|
I keep getting a SIGSEGV in JS/JIT code under gdb even though there is no crash when gdb is not attached. How do I fix it?
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
Set the JS_DISABLE_SLOW_SCRIPT_SIGNALS environment variable (in FF33,
|
|
the shorter and easier-to-remember JS_NO_SIGNALS). For an explanation,
|
|
read `Jan's blog
|
|
post <https://www.jandemooij.nl/blog/2014/02/18/using-segfaults-to-interrupt-jit-code/>`__.
|
|
|
|
I keep getting a SIG32 in the debugger. How do I fix it?
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
If you are getting a SIG32 while trying to debug Firefox you might have
|
|
turned off shared library loading before the pthreads library was
|
|
loaded. For example, ``set auto-solib-add 0`` in your ``.gdbinit`` file.
|
|
In this case, you can either:
|
|
|
|
- Remove it and use the method explained in the section about `GDB's
|
|
memory
|
|
usage <#The_debugger_uses_a_lot_of_memory._How_do_I_fix_it.3F>`__
|
|
- Use ``handle SIG32 noprint`` either in gdb or in your ``.gdbinit``
|
|
file
|
|
|
|
Alternatively, the problem might lie in your pthread library. If this
|
|
library has its symbols stripped, then GDB can't hook into thread
|
|
events, and you end up with SIG32 signals. You can check if your
|
|
libpthread is stripped in ``file /lib/libpthread*`` and looking for
|
|
``'stripped'.``\ To fix this problem on Gentoo Linux, you can re-emerge
|
|
glibc after adding ``"nostrip"`` to your ``FEATURES`` in
|
|
``/etc/make.conf``.
|
|
|
|
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.
|
|
|
|
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 dbus-glib-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
|
|
|
|
Debugging electrolysis (e10s)
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
``mach run`` and ``mach test`` both accept a ``--disable-e10s``
|
|
argument. Some debuggers can't catch child-process crashes without it.
|
|
|
|
You can find some (outdated) information on
|
|
https://wiki.mozilla.org/Electrolysis/Debugging. You may also like to
|
|
read
|
|
https://mikeconley.ca/blog/2014/04/25/electrolysis-debugging-child-processes-of-content-for-make-benefit-glorious-browser-of-firefox
|
|
for a more up-to-date blog post.
|
|
|
|
To get the child process id use:
|
|
|
|
.. code::
|
|
|
|
MOZ_DEBUG_CHILD_PROCESS=1 mach run
|
|
|
|
See also
|
|
~~~~~~~~~
|
|
|
|
- `Debugging <https://developer.mozilla.org/En/Debugging>`__
|
|
- `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
|
|
- `Archer pretty printers for
|
|
SpiderMonkey <https://hg.mozilla.org/users/jblandy_mozilla.com/archer-mozilla>`__
|
|
(`blog
|
|
post <https://itcouldbesomuchbetter.wordpress.com/2010/12/20/debugging-spidermonkey-with-archer-2/>`__)
|
|
- `More pretty
|
|
printers <https://hg.mozilla.org/users/josh_joshmatthews.net/archer-mozilla/>`__
|
|
for Gecko internals (`blog
|
|
post <https://www.joshmatthews.net/blog/2011/06/nscomptr-has-never-been-so-pretty/>`__)
|
|
|
|
.. container:: originaldocinfo
|
|
|
|
.. rubric:: Original Document Information
|
|
:name: Original_Document_Information
|
|
|
|
- `History <http://bonsai-www.mozilla.org/cvslog.cgi?file=mozilla-org/html/unix/debugging-faq.html&rev=&root=/www/>`__
|
|
- Copyright Information: © 1998-2008 by individual mozilla.org
|
|
contributors; content available under a `Creative Commons
|
|
license <https://www.mozilla.org/foundation/licensing/website-content.html>`__
|
|
|
|
|