tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

README (7421B)


      1 This directory holds Python code to support debugging SpiderMonkey with
      2 GDB. It includes pretty-printers for common SpiderMonkey types like JS::Value,
      3 jsid, and JSObject, and makes GDB "see through" the SpiderMonkey rooting
      4 types like js::Rooted and JS::Handle. For example:
      5 
      6     (gdb) frame
      7     #0  js::baseops::SetPropertyHelper (cx=0xbf3460,
      8         obj=(JSObject * const) 0x7ffff150b060 [object global] delegate,
      9         receiver=(JSObject * const) 0x7ffff150b060 [object global] delegate,
     10         id=$jsid("x"), defineHow=4, vp=$JS::Int32Value(1), strict=0)
     11         at /home/jimb/moz/archer/js/src/jsobj.cpp:4495
     12     4495	    MOZ_ASSERT((defineHow & ~(DNP_CACHE_RESULT | DNP_UNQUALIFIED)) == 0);
     13     (gdb)
     14 
     15 Things to note here:
     16 
     17 - obj, a JS::HandleObject, prints as:
     18       obj=(JSObject * const) 0x7ffff150b060 [object global] delegate,
     19   This immediately shows the handle's referent, along with a JavaScript-like summary
     20   of the object.
     21 
     22 - id, a JS::HandleId, prints as:
     23       id=$jsid("x"),
     24   We show the handle's referent, and print the identifier as a string.
     25 
     26 - vp, a JS::MutableHandleValue, prints as:
     27       vp=$JS::Int32Value(1)
     28   We show the handle's referent, using the JS::Value's tag to print it noting
     29   its particular internal type and value.
     30 
     31 You can still see the raw form of a value with 'print/r':
     32 
     33     (gdb) p/r obj
     34     $1 = {<js::HandleBase<JSObject*>> = {<No data fields>}, ptr = 0x7fffffffca60}
     35     (gdb)
     36 
     37 You can also use GDB's 'disable pretty-printer' command to turn off
     38 individual pretty-printers; try 'info pretty-printer' first.
     39 
     40 GDB should pick these extensions up automatically when you debug the shell or
     41 the browser, by auto-loading the 'js-gdb.py' file that the build system
     42 installs alongside the 'js' executable (or 'libxul.so-gdb.py' for the browser).
     43 You may need to add a command like the following to your '$HOME/.gdbinit' file:
     44 
     45     # Tell GDB to trust auto-load files found under ~/moz.
     46     add-auto-load-safe-path ~/moz
     47 
     48 If you do need this, GDB will tell you.
     49 
     50 In general, pretty-printers for pointer types include a summary of the
     51 pointer's referent:
     52 
     53     (gdb) b math_atan2
     54     Breakpoint 1 at 0x542e0a: file /home/jimb/moz/archer/js/src/jsmath.cpp, line 214.
     55     (gdb) run
     56     js> Math.atan2('Spleen', 42)
     57     Breakpoint 1, math_atan2 (cx=0xbf3440, argc=2, vp=0x7ffff172f0a0)
     58     (gdb) print vp[0]
     59     $1 = $JS::Value((JSObject *) 0x7ffff151c0c0 [object Function "atan2"])
     60     (gdb) print vp[1]
     61     $2 = $JS::Value((JSObject *) 0x7ffff150d0a0 [object Math])
     62     (gdb) print vp[2]
     63     $3 = $JS::Value("Spleen")
     64     (gdb) print vp[3]
     65     $4 = $JS::Int32Value(42)
     66     (gdb)
     67 
     68 We used to also have pretty-printers for the actual contents of a JSString
     69 struct, that knew which union branches were live and which were dead. These were
     70 more fragile than the summary pretty-printers, and harder to test, so I've
     71 removed them until we can see how to do better.
     72 
     73 There are unit tests; see 'Running the unit tests', below.
     74 
     75 I'd love for others to pitch in. GDB's Python API is documented in the GDB
     76 manual.
     77 
     78 I've recently rewritten the printers. The new code is simpler, and more
     79 robust; unit tests are easier to write; and the new test harness can run
     80 the tests in parallel. If a printer you'd contributed to in the past was
     81 dropped in the process, I apologize; I felt we should have good test
     82 coverage for any printer landed in-tree. You may also be interested in
     83 'Personal pretty-printers', below.
     84 
     85 Directory layout
     86 ----------------
     87 
     88 - js/src/gdb/mozilla: The actual SpiderMonkey support code. GDB auto-loads this
     89   when you debug an executable or shared library that contains SpiderMonkey.
     90 - js/src/gdb/tests: Unit tests for the above.
     91   - Each '.py' file is a unit test, to be run by js/src/gdb/run-tests.py.
     92   - Each '.cpp' file contains C++ code fragments for some unit test to use.
     93 - js/src/gdb/lib-for-tests: Python modules used by the unit tests.
     94 
     95 In js/src/gdb:
     96 
     97 - run-tests.py: test harness for GDB SpiderMonkey support unit tests. See
     98   'Running the unit tests', below.
     99 - taskpool.py, progressbar.py: Python modules used by run-tests.py.
    100 - gdb-tests.cpp, gdb-tests.h: Driver program for C++ code fragments.
    101 - gdb-tests-gdb.py.in: Template for GDB autoload file for gdb-tests.
    102 
    103 Personal pretty-printers
    104 ------------------------
    105 
    106 If you'd like to write your own pretty-printers, you can put them in a
    107 module named 'my_mozilla_printers' in a directory somewhere on your Python
    108 module search path. Our autoload code tries to import 'my_mozilla_printers'
    109 after importing our other SpiderMonkey support modules. For example:
    110 
    111     $ echo $PYTHONPATH
    112     /home/jimb/python
    113     $ cat ~/python/my_mozilla_printers.py
    114     import gdb
    115     from mozilla.prettyprinters import ptr_pretty_printer
    116 
    117     # Simple char16_t * printer. Doesn't show address; chases null pointers.
    118     @ptr_pretty_printer('char16_t')
    119     class char16Ptr(object):
    120         def __init__(self, value, cache): self.value = value
    121         def display_hint(self): return 'string'
    122         def to_string(self):
    123             c = u''
    124             for i in range(50):
    125                 if self.value[i] == 0: break
    126                 c += unichr(self.value[i])
    127             return c
    128     $
    129     ...
    130     (gdb) whatis sample
    131     type = char16_t [4]
    132     (gdb) print &sample[0]
    133     $1 = "Hi!"
    134 
    135 Running the unit tests
    136 ----------------------
    137 
    138 These extensions have unit tests, invoked as follows:
    139 
    140 $ python run-tests.py [OPTIONS] OBJDIR [TESTS...]
    141 
    142 where OBJDIR is a directory containing a standalone SpiderMonkey build; TESTS
    143 are names of selected tests to run (if omitted, we run them all); and OPTIONS
    144 are drawn from the list below.
    145 
    146 --gdb=EXECUTABLE
    147   Instead of running whatever 'gdb' we find in our search path, use
    148   EXECUTABLE to run the tests.
    149 
    150 --srcdir=SRCDIR
    151   Find the sources corresponding to OBJDIR/dist/bin/libmozjs.so in SRCDIR.
    152   Without this option, we use the parent of the directory containing
    153   'run-tests.py'. Note that SRCDIR must be a complete SpiderMonkey source
    154   directory, as our tests #include internal SpiderMonkey header files (to
    155   test pretty-printers for internal types, like parse nodes.)
    156 
    157 --testdir=TESTDIR
    158   Search for Python scripts and any accompanying C++ source code in
    159   TESTDIR. If omitted, we use the 'tests' directory in the directory
    160   containing 'run-tests.py'.
    161 
    162 --builddir=BUILDDIR
    163   Build the C++ executable that GDB debugs to run the tests in BUILDDIR.
    164   If omitted, create a 'gdb-tests' subdirectory of OBJDIR/js/src.
    165 
    166 (It is safe to use relative paths for OBJDIR, SRCDIR, and so on. They are
    167 always interpreted relative to the directory that was current when
    168 run-tests.py was started.)
    169 
    170 For example, since I build in a subdirectory 'obj~' of the 'js/src'
    171 directory, I use this command from 'js/src' to run the pretty-printer unit
    172 tests:
    173 
    174   $ python gdb/run-tests.py obj~
    175 
    176 Writing new unit tests
    177 ----------------------
    178 
    179 Each unit test consists of a Python script, possibly with some accompanying
    180 C++ code. Running tests works like this:
    181 
    182 - The run-tests.py script calls 'make' in 'BUILDDIR/gdb' to build
    183   'gdb-tests'.
    184 
    185 - Then, for each '.py' test script in js/src/gdb/tests, the harness starts
    186   GDB on the 'gdb-tests' executable, and then has GDB run
    187   js/src/gdb/lib-for-tests/prologue.py, passing it the test script's path as
    188   its first command-line argument.
    189 
    190 Thanks To:
    191 ----------
    192 
    193 - David Anderson
    194 - Steve Fink
    195 - Chris Leary
    196 - Josh Matthews
    197 - Jason Orendorff
    198 - Andrew Sutherland