|
1 This directory holds Python code to support debugging SpiderMonkey with |
|
2 GDB. It includes pretty-printers for common SpiderMonkey types like jsval, |
|
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=$jsval(1), strict=0) |
|
11 at /home/jimb/moz/archer/js/src/jsobj.cpp:4495 |
|
12 4495 JS_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=$jsval(1) |
|
28 We show the handle's referent, using the jsval's tag to print it in its |
|
29 JavaScript form. |
|
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, by |
|
41 auto-loading the 'js-gdb.py' file that js/src/shell/Makefile.in places in the |
|
42 same directory as the 'js' executable. You may need to add a command like the |
|
43 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 = $jsval((JSObject *) 0x7ffff151c0c0 [object Function "atan2"]) |
|
60 (gdb) print vp[1] |
|
61 $2 = $jsval((JSObject *) 0x7ffff150d0a0 [object Math]) |
|
62 (gdb) print vp[2] |
|
63 $3 = $jsval("Spleen") |
|
64 (gdb) print vp[3] |
|
65 $4 = $jsval(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 jschar * printer. Doesn't show address; chases null pointers. |
|
118 @ptr_pretty_printer('jschar') |
|
119 class jscharPtr(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 xrange(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 = jschar [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] LIBDIR [TESTS...] |
|
141 |
|
142 where LIBDIR is a directory containing a compiled SpiderMonkey library, |
|
143 libmozjs.so; TESTS are names of selected tests to run (if omitted, we run |
|
144 them all); and OPTIONS 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 LIBDIR/libmozjs.so in SRCDIR. Without |
|
152 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 LIBDIR. |
|
165 |
|
166 (It is safe to use relative paths for LIBDIR, 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/prolog.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 |