Good morning, folks. I'm about to land GDB pretty-printers for
SpiderMonkey types in the tree:

https://bugzilla.mozilla.org/show_bug.cgi?id=506717

The C++ code for the GDB support's unit tests is part of the standard
build (see js/src/gdb/Makefile.in), but that is simple code. Nothing
else should affect non-Linux platforms. The pretty-printer unit tests do
not run by default.

On Linux, GDB should pick up the pretty-printers automatically, perhaps
after telling you to add a 'add-auto-load-safe-path' command to your
.gdbinit file.

If you run into any problems, please find me (jimb), Steve Fink (sfink),
or Josh Matthews (jdm).

Here's js/src/gdb/README:

----

This directory holds Python code to support debugging SpiderMonkey with
GDB. It includes pretty-printers for common SpiderMonkey types like jsval,
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=$jsval(1), strict=0)
        at /home/jimb/moz/archer/js/src/jsobj.cpp:4495
    4495            JS_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=$jsval(1)
  We show the handle's referent, using the jsval's tag to print it in its
  JavaScript form.

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, by
auto-loading the 'js-gdb.py' file that js/src/shell/Makefile.in places
in the
same directory as the 'js' executable. 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 = $jsval((JSObject *) 0x7ffff151c0c0 [object Function "atan2"])
    (gdb) print vp[1]
    $2 = $jsval((JSObject *) 0x7ffff150d0a0 [object Math])
    (gdb) print vp[2]
    $3 = $jsval("Spleen")
    (gdb) print vp[3]
    $4 = $jsval(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 jschar * printer. Doesn't show address; chases null pointers.
    @ptr_pretty_printer('jschar')
    class jscharPtr(object):
        def __init__(self, value, cache): self.value = value
        def display_hint(self): return 'string'
        def to_string(self):
            c = u''
            for i in xrange(50):
                if self.value[i] == 0: break
                c += unichr(self.value[i])
            return c
    $
    ...
    (gdb) whatis sample
    type = jschar [4]
    (gdb) print &sample[0]
    $1 = "Hi!"

Running the unit tests
----------------------

These extensions have unit tests, invoked as follows:

$ python run-tests.py [OPTIONS] LIBDIR [TESTS...]

where LIBDIR is a directory containing a compiled SpiderMonkey library,
libmozjs.so; 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 LIBDIR/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 LIBDIR.

(If a path like LIBDIR or SRCDIR is relative, it is interpreted relative to
the directory that was current when run-tests.py was executed, regardless
of whatever changes to the current directory the test harness makes.)

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 --libdir=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' to compile all the '.cpp' files in
  js/src/gdb/tests, and then links them with js/src/gdb/gdb-tests.cpp and
  LIBDIR/libmozjs.so, producing a single executable file.

- Then, for each '.py' test script in js/src/gdb/tests, the harness starts
  GDB on the executable, and has it run js/src/gdb/lib-for-tests/prolog.py,
  and then the given test script.

Thanks To:
----------

- David Anderson
- Steve Fink
- Chris Leary
- Josh Matthews
- Jason Orendorff
- Andrew Sutherland
_______________________________________________
dev-tech-js-engine-internals mailing list
dev-tech-js-engine-internals@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-tech-js-engine-internals

Reply via email to