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