summaryrefslogtreecommitdiffstats
path: root/js/src/gdb/README
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /js/src/gdb/README
parentInitial commit. (diff)
downloadfirefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz
firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/gdb/README')
-rw-r--r--js/src/gdb/README198
1 files changed, 198 insertions, 0 deletions
diff --git a/js/src/gdb/README b/js/src/gdb/README
new file mode 100644
index 0000000000..9c98e192b5
--- /dev/null
+++ b/js/src/gdb/README
@@ -0,0 +1,198 @@
+This directory holds Python code to support debugging SpiderMonkey with
+GDB. It includes pretty-printers for common SpiderMonkey types like JS::Value,
+jsid, and JSObject, and makes GDB "see through" the SpiderMonkey rooting
+types like js::Rooted and JS::Handle. For example:
+
+ (gdb) frame
+ #0 js::baseops::SetPropertyHelper (cx=0xbf3460,
+ obj=(JSObject * const) 0x7ffff150b060 [object global] delegate,
+ receiver=(JSObject * const) 0x7ffff150b060 [object global] delegate,
+ id=$jsid("x"), defineHow=4, vp=$JS::Int32Value(1), strict=0)
+ at /home/jimb/moz/archer/js/src/jsobj.cpp:4495
+ 4495 MOZ_ASSERT((defineHow & ~(DNP_CACHE_RESULT | DNP_UNQUALIFIED)) == 0);
+ (gdb)
+
+Things to note here:
+
+- obj, a JS::HandleObject, prints as:
+ obj=(JSObject * const) 0x7ffff150b060 [object global] delegate,
+ This immediately shows the handle's referent, along with a JavaScript-like summary
+ of the object.
+
+- id, a JS::HandleId, prints as:
+ id=$jsid("x"),
+ We show the handle's referent, and print the identifier as a string.
+
+- vp, a JS::MutableHandleValue, prints as:
+ vp=$JS::Int32Value(1)
+ We show the handle's referent, using the JS::Value's tag to print it noting
+ its particular internal type and value.
+
+You can still see the raw form of a value with 'print/r':
+
+ (gdb) p/r obj
+ $1 = {<js::HandleBase<JSObject*>> = {<No data fields>}, ptr = 0x7fffffffca60}
+ (gdb)
+
+You can also use GDB's 'disable pretty-printer' command to turn off
+individual pretty-printers; try 'info pretty-printer' first.
+
+GDB should pick these extensions up automatically when you debug the shell or
+the browser, by auto-loading the 'js-gdb.py' file that the build system
+installs alongside the 'js' executable (or 'libxul.so-gdb.py' for the browser).
+You may need to add a command like the following to your '$HOME/.gdbinit' file:
+
+ # Tell GDB to trust auto-load files found under ~/moz.
+ add-auto-load-safe-path ~/moz
+
+If you do need this, GDB will tell you.
+
+In general, pretty-printers for pointer types include a summary of the
+pointer's referent:
+
+ (gdb) b math_atan2
+ Breakpoint 1 at 0x542e0a: file /home/jimb/moz/archer/js/src/jsmath.cpp, line 214.
+ (gdb) run
+ js> Math.atan2('Spleen', 42)
+ Breakpoint 1, math_atan2 (cx=0xbf3440, argc=2, vp=0x7ffff172f0a0)
+ (gdb) print vp[0]
+ $1 = $JS::Value((JSObject *) 0x7ffff151c0c0 [object Function "atan2"])
+ (gdb) print vp[1]
+ $2 = $JS::Value((JSObject *) 0x7ffff150d0a0 [object Math])
+ (gdb) print vp[2]
+ $3 = $JS::Value("Spleen")
+ (gdb) print vp[3]
+ $4 = $JS::Int32Value(42)
+ (gdb)
+
+We used to also have pretty-printers for the actual contents of a JSString
+struct, that knew which union branches were live and which were dead. These were
+more fragile than the summary pretty-printers, and harder to test, so I've
+removed them until we can see how to do better.
+
+There are unit tests; see 'Running the unit tests', below.
+
+I'd love for others to pitch in. GDB's Python API is documented in the GDB
+manual.
+
+I've recently rewritten the printers. The new code is simpler, and more
+robust; unit tests are easier to write; and the new test harness can run
+the tests in parallel. If a printer you'd contributed to in the past was
+dropped in the process, I apologize; I felt we should have good test
+coverage for any printer landed in-tree. You may also be interested in
+'Personal pretty-printers', below.
+
+Directory layout
+----------------
+
+- js/src/gdb/mozilla: The actual SpiderMonkey support code. GDB auto-loads this
+ when you debug an executable or shared library that contains SpiderMonkey.
+- js/src/gdb/tests: Unit tests for the above.
+ - Each '.py' file is a unit test, to be run by js/src/gdb/run-tests.py.
+ - Each '.cpp' file contains C++ code fragments for some unit test to use.
+- js/src/gdb/lib-for-tests: Python modules used by the unit tests.
+
+In js/src/gdb:
+
+- run-tests.py: test harness for GDB SpiderMonkey support unit tests. See
+ 'Running the unit tests', below.
+- taskpool.py, progressbar.py: Python modules used by run-tests.py.
+- gdb-tests.cpp, gdb-tests.h: Driver program for C++ code fragments.
+- gdb-tests-gdb.py.in: Template for GDB autoload file for gdb-tests.
+
+Personal pretty-printers
+------------------------
+
+If you'd like to write your own pretty-printers, you can put them in a
+module named 'my_mozilla_printers' in a directory somewhere on your Python
+module search path. Our autoload code tries to import 'my_mozilla_printers'
+after importing our other SpiderMonkey support modules. For example:
+
+ $ echo $PYTHONPATH
+ /home/jimb/python
+ $ cat ~/python/my_mozilla_printers.py
+ import gdb
+ from mozilla.prettyprinters import ptr_pretty_printer
+
+ # Simple char16_t * printer. Doesn't show address; chases null pointers.
+ @ptr_pretty_printer('char16_t')
+ class char16Ptr(object):
+ def __init__(self, value, cache): self.value = value
+ def display_hint(self): return 'string'
+ def to_string(self):
+ c = u''
+ for i in range(50):
+ if self.value[i] == 0: break
+ c += unichr(self.value[i])
+ return c
+ $
+ ...
+ (gdb) whatis sample
+ type = char16_t [4]
+ (gdb) print &sample[0]
+ $1 = "Hi!"
+
+Running the unit tests
+----------------------
+
+These extensions have unit tests, invoked as follows:
+
+$ python run-tests.py [OPTIONS] OBJDIR [TESTS...]
+
+where OBJDIR is a directory containing a standalone SpiderMonkey build; TESTS
+are names of selected tests to run (if omitted, we run them all); and OPTIONS
+are drawn from the list below.
+
+--gdb=EXECUTABLE
+ Instead of running whatever 'gdb' we find in our search path, use
+ EXECUTABLE to run the tests.
+
+--srcdir=SRCDIR
+ Find the sources corresponding to OBJDIR/dist/bin/libmozjs.so in SRCDIR.
+ Without this option, we use the parent of the directory containing
+ 'run-tests.py'. Note that SRCDIR must be a complete SpiderMonkey source
+ directory, as our tests #include internal SpiderMonkey header files (to
+ test pretty-printers for internal types, like parse nodes.)
+
+--testdir=TESTDIR
+ Search for Python scripts and any accompanying C++ source code in
+ TESTDIR. If omitted, we use the 'tests' directory in the directory
+ containing 'run-tests.py'.
+
+--builddir=BUILDDIR
+ Build the C++ executable that GDB debugs to run the tests in BUILDDIR.
+ If omitted, create a 'gdb-tests' subdirectory of OBJDIR/js/src.
+
+(It is safe to use relative paths for OBJDIR, SRCDIR, and so on. They are
+always interpreted relative to the directory that was current when
+run-tests.py was started.)
+
+For example, since I build in a subdirectory 'obj~' of the 'js/src'
+directory, I use this command from 'js/src' to run the pretty-printer unit
+tests:
+
+ $ python gdb/run-tests.py obj~
+
+Writing new unit tests
+----------------------
+
+Each unit test consists of a Python script, possibly with some accompanying
+C++ code. Running tests works like this:
+
+- The run-tests.py script calls 'make' in 'BUILDDIR/gdb' to build
+ 'gdb-tests'.
+
+- Then, for each '.py' test script in js/src/gdb/tests, the harness starts
+ GDB on the 'gdb-tests' executable, and then has GDB run
+ js/src/gdb/lib-for-tests/prologue.py, passing it the test script's path as
+ its first command-line argument.
+
+Thanks To:
+----------
+
+- David Anderson
+- Steve Fink
+- Chris Leary
+- Josh Matthews
+- Jason Orendorff
+- Andrew Sutherland