js/src/gdb/README

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial