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