js/src/gdb/README

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/gdb/README	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,198 @@
     1.4 +This directory holds Python code to support debugging SpiderMonkey with
     1.5 +GDB. It includes pretty-printers for common SpiderMonkey types like jsval,
     1.6 +jsid, and JSObject, and makes GDB "see through" the SpiderMonkey rooting
     1.7 +types like js::Rooted and JS::Handle. For example:
     1.8 +
     1.9 +    (gdb) frame
    1.10 +    #0  js::baseops::SetPropertyHelper (cx=0xbf3460,
    1.11 +        obj=(JSObject * const) 0x7ffff150b060 [object global] delegate,
    1.12 +        receiver=(JSObject * const) 0x7ffff150b060 [object global] delegate,
    1.13 +        id=$jsid("x"), defineHow=4, vp=$jsval(1), strict=0)
    1.14 +        at /home/jimb/moz/archer/js/src/jsobj.cpp:4495
    1.15 +    4495	    JS_ASSERT((defineHow & ~(DNP_CACHE_RESULT | DNP_UNQUALIFIED)) == 0);
    1.16 +    (gdb)
    1.17 +
    1.18 +Things to note here:
    1.19 +
    1.20 +- obj, a JS::HandleObject, prints as:
    1.21 +      obj=(JSObject * const) 0x7ffff150b060 [object global] delegate,
    1.22 +  This immediately shows the handle's referent, along with a JavaScript-like summary
    1.23 +  of the object.
    1.24 +
    1.25 +- id, a JS::HandleId, prints as:
    1.26 +      id=$jsid("x"),
    1.27 +  We show the handle's referent, and print the identifier as a string.
    1.28 +
    1.29 +- vp, a JS::MutableHandleValue, prints as:
    1.30 +      vp=$jsval(1)
    1.31 +  We show the handle's referent, using the jsval's tag to print it in its
    1.32 +  JavaScript form.
    1.33 +
    1.34 +You can still see the raw form of a value with 'print/r':
    1.35 +
    1.36 +    (gdb) p/r obj
    1.37 +    $1 = {<js::HandleBase<JSObject*>> = {<No data fields>}, ptr = 0x7fffffffca60}
    1.38 +    (gdb)
    1.39 +
    1.40 +You can also use GDB's 'disable pretty-printer' command to turn off
    1.41 +individual pretty-printers; try 'info pretty-printer' first.
    1.42 +
    1.43 +GDB should pick these extensions up automatically when you debug the shell, by
    1.44 +auto-loading the 'js-gdb.py' file that js/src/shell/Makefile.in places in the
    1.45 +same directory as the 'js' executable. You may need to add a command like the
    1.46 +following to your '$HOME/.gdbinit' file:
    1.47 +
    1.48 +    # Tell GDB to trust auto-load files found under ~/moz.
    1.49 +    add-auto-load-safe-path ~/moz
    1.50 +
    1.51 +If you do need this, GDB will tell you.
    1.52 +
    1.53 +In general, pretty-printers for pointer types include a summary of the
    1.54 +pointer's referent:
    1.55 +
    1.56 +    (gdb) b math_atan2
    1.57 +    Breakpoint 1 at 0x542e0a: file /home/jimb/moz/archer/js/src/jsmath.cpp, line 214.
    1.58 +    (gdb) run
    1.59 +    js> Math.atan2('Spleen', 42)
    1.60 +    Breakpoint 1, math_atan2 (cx=0xbf3440, argc=2, vp=0x7ffff172f0a0)
    1.61 +    (gdb) print vp[0]
    1.62 +    $1 = $jsval((JSObject *) 0x7ffff151c0c0 [object Function "atan2"])
    1.63 +    (gdb) print vp[1]
    1.64 +    $2 = $jsval((JSObject *) 0x7ffff150d0a0 [object Math])
    1.65 +    (gdb) print vp[2]
    1.66 +    $3 = $jsval("Spleen")
    1.67 +    (gdb) print vp[3]
    1.68 +    $4 = $jsval(42)
    1.69 +    (gdb)
    1.70 +
    1.71 +We used to also have pretty-printers for the actual contents of a JSString
    1.72 +struct, that knew which union branches were live and which were dead. These were
    1.73 +more fragile than the summary pretty-printers, and harder to test, so I've
    1.74 +removed them until we can see how to do better.
    1.75 +
    1.76 +There are unit tests; see 'Running the unit tests', below.
    1.77 +
    1.78 +I'd love for others to pitch in. GDB's Python API is documented in the GDB
    1.79 +manual.
    1.80 +
    1.81 +I've recently rewritten the printers. The new code is simpler, and more
    1.82 +robust; unit tests are easier to write; and the new test harness can run
    1.83 +the tests in parallel. If a printer you'd contributed to in the past was
    1.84 +dropped in the process, I apologize; I felt we should have good test
    1.85 +coverage for any printer landed in-tree. You may also be interested in
    1.86 +'Personal pretty-printers', below.
    1.87 +
    1.88 +Directory layout
    1.89 +----------------
    1.90 +
    1.91 +- js/src/gdb/mozilla: The actual SpiderMonkey support code. GDB auto-loads this
    1.92 +  when you debug an executable or shared library that contains SpiderMonkey.
    1.93 +- js/src/gdb/tests: Unit tests for the above.
    1.94 +  - Each '.py' file is a unit test, to be run by js/src/gdb/run-tests.py.
    1.95 +  - Each '.cpp' file contains C++ code fragments for some unit test to use.
    1.96 +- js/src/gdb/lib-for-tests: Python modules used by the unit tests.
    1.97 +
    1.98 +In js/src/gdb:
    1.99 +
   1.100 +- run-tests.py: test harness for GDB SpiderMonkey support unit tests. See
   1.101 +  'Running the unit tests', below.
   1.102 +- taskpool.py, progressbar.py: Python modules used by run-tests.py.
   1.103 +- gdb-tests.cpp, gdb-tests.h: Driver program for C++ code fragments.
   1.104 +- gdb-tests-gdb.py.in: Template for GDB autoload file for gdb-tests.
   1.105 +
   1.106 +Personal pretty-printers
   1.107 +------------------------
   1.108 +
   1.109 +If you'd like to write your own pretty-printers, you can put them in a
   1.110 +module named 'my_mozilla_printers' in a directory somewhere on your Python
   1.111 +module search path. Our autoload code tries to import 'my_mozilla_printers'
   1.112 +after importing our other SpiderMonkey support modules. For example:
   1.113 +
   1.114 +    $ echo $PYTHONPATH
   1.115 +    /home/jimb/python
   1.116 +    $ cat ~/python/my_mozilla_printers.py
   1.117 +    import gdb
   1.118 +    from mozilla.prettyprinters import ptr_pretty_printer
   1.119 +
   1.120 +    # Simple jschar * printer. Doesn't show address; chases null pointers.
   1.121 +    @ptr_pretty_printer('jschar')
   1.122 +    class jscharPtr(object):
   1.123 +        def __init__(self, value, cache): self.value = value
   1.124 +        def display_hint(self): return 'string'
   1.125 +        def to_string(self):
   1.126 +            c = u''
   1.127 +            for i in xrange(50):
   1.128 +                if self.value[i] == 0: break
   1.129 +                c += unichr(self.value[i])
   1.130 +            return c
   1.131 +    $
   1.132 +    ...
   1.133 +    (gdb) whatis sample
   1.134 +    type = jschar [4]
   1.135 +    (gdb) print &sample[0]
   1.136 +    $1 = "Hi!"
   1.137 +
   1.138 +Running the unit tests
   1.139 +----------------------
   1.140 +
   1.141 +These extensions have unit tests, invoked as follows:
   1.142 +
   1.143 +$ python run-tests.py [OPTIONS] LIBDIR [TESTS...]
   1.144 +
   1.145 +where LIBDIR is a directory containing a compiled SpiderMonkey library,
   1.146 +libmozjs.so; TESTS are names of selected tests to run (if omitted, we run
   1.147 +them all); and OPTIONS are drawn from the list below.
   1.148 +
   1.149 +--gdb=EXECUTABLE
   1.150 +  Instead of running whatever 'gdb' we find in our search path, use
   1.151 +  EXECUTABLE to run the tests.
   1.152 +
   1.153 +--srcdir=SRCDIR
   1.154 +  Find the sources corresponding to LIBDIR/libmozjs.so in SRCDIR. Without
   1.155 +  this option, we use the parent of the directory containing
   1.156 +  'run-tests.py'. Note that SRCDIR must be a complete SpiderMonkey source
   1.157 +  directory, as our tests #include internal SpiderMonkey header files (to
   1.158 +  test pretty-printers for internal types, like parse nodes.)
   1.159 +
   1.160 +--testdir=TESTDIR
   1.161 +  Search for Python scripts and any accompanying C++ source code in
   1.162 +  TESTDIR. If omitted, we use the 'tests' directory in the directory
   1.163 +  containing 'run-tests.py'.
   1.164 +
   1.165 +--builddir=BUILDDIR
   1.166 +  Build the C++ executable that GDB debugs to run the tests in BUILDDIR.
   1.167 +  If omitted, create a 'gdb-tests' subdirectory of LIBDIR.
   1.168 +
   1.169 +(It is safe to use relative paths for LIBDIR, SRCDIR, and so on. They are
   1.170 +always interpreted relative to the directory that was current when
   1.171 +run-tests.py was started.)
   1.172 +
   1.173 +For example, since I build in a subdirectory 'obj~' of the 'js/src'
   1.174 +directory, I use this command from 'js/src' to run the pretty-printer unit
   1.175 +tests:
   1.176 +
   1.177 +  $ python gdb/run-tests.py obj~
   1.178 +
   1.179 +Writing new unit tests
   1.180 +----------------------
   1.181 +
   1.182 +Each unit test consists of a Python script, possibly with some accompanying
   1.183 +C++ code. Running tests works like this:
   1.184 +
   1.185 +- The run-tests.py script calls 'make' in 'BUILDDIR/gdb' to build
   1.186 +  'gdb-tests'.
   1.187 +
   1.188 +- Then, for each '.py' test script in js/src/gdb/tests, the harness starts
   1.189 +  GDB on the 'gdb-tests' executable, and then has GDB run
   1.190 +  js/src/gdb/lib-for-tests/prolog.py, passing it the test script's path as
   1.191 +  its first command-line argument.
   1.192 +
   1.193 +Thanks To:
   1.194 +----------
   1.195 +
   1.196 +- David Anderson
   1.197 +- Steve Fink
   1.198 +- Chris Leary
   1.199 +- Josh Matthews
   1.200 +- Jason Orendorff
   1.201 +- Andrew Sutherland

mercurial