]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | ========================================= |
2 | Duktape debug client and JSON debug proxy | |
3 | ========================================= | |
4 | ||
5 | Overview | |
6 | ======== | |
7 | ||
8 | Debugger web UI which connects to the Duktape command line tool or any other | |
9 | target supporting the example TCP transport (``examples/debug-trans-socket``). | |
10 | ||
11 | Also provides a JSON debug proxy with a JSON mapping for the Duktape debug | |
12 | protocol. | |
13 | ||
14 | For detailed documentation of the debugger internals, see `debugger.rst`__. | |
15 | ||
16 | __ https://github.com/svaarala/duktape/blob/master/doc/debugger.rst | |
17 | ||
18 | Using the debugger web UI | |
19 | ========================= | |
20 | ||
21 | Some prerequisites: | |
22 | ||
23 | * You'll need Node.js v0.10.x or newer. Older Node.js versions don't support | |
24 | the required packages. | |
25 | ||
26 | Compile Duktape command line tool with debugger support (for further options | |
27 | see ``doc/feature-options.rst``): | |
28 | ||
29 | * ``DUK_OPT_DEBUGGER_SUPPORT`` | |
30 | ||
31 | * ``DUK_OPT_INTERRUPT_COUNTER`` | |
32 | ||
33 | * ``DUK_CMDLINE_DEBUGGER_SUPPORT`` | |
34 | ||
35 | The source distributable contains a Makefile to build a "duk" command with | |
36 | debugger support:: | |
37 | ||
38 | $ cd <duktape dist directory> | |
39 | $ make -f Makefile.dukdebug | |
40 | ||
41 | The Duktape Git repo "duk" target has debugger support enabled by default:: | |
42 | ||
43 | $ make clean duk | |
44 | ||
45 | Start Duktape command line tool so that it waits for a debugger connection:: | |
46 | ||
47 | # For now we need to be in the directory containing the source files | |
48 | # executed so that the 'fileName' properties of functions will match | |
49 | # that on the debug client. | |
50 | ||
51 | # Using source distributable | |
52 | $ cd <duktape dist directory> | |
53 | $ ./duk --debugger mandel.js | |
54 | ||
55 | # Using Duktape Git repo | |
56 | $ cd <duktape checkout>/tests/ecmascript/ | |
57 | $ ../../duk --debugger test-dev-mandel2-func.js | |
58 | ||
59 | Start the web UI:: | |
60 | ||
61 | # Must be in 'debugger' directory. | |
62 | ||
63 | $ cd debugger/ | |
64 | $ make # runs 'node duk_debug.js' | |
65 | ||
66 | Once the required packages are installed, the NodeJS debug client will be | |
67 | up and running. Open the following in your browser and start debugging: | |
68 | ||
69 | * http://localhost:9092/ | |
70 | ||
71 | The debug client automatically attaches to the debug target on startup. | |
72 | If you start the debug target later, you'll need to click "Attach" in the | |
73 | web UI. | |
74 | ||
75 | Using the JSON debug proxy | |
76 | ========================== | |
77 | ||
78 | A JSON debug proxy is also provided by ``duk_debug.js``:: | |
79 | ||
80 | # Same prerequisites as above | |
81 | $ make runproxy | |
82 | ||
83 | Start Duktape command line (or whatever your target is):: | |
84 | ||
85 | $ cd <duktape checkout>/tests/ecmascript/ | |
86 | $ ../../duk --debugger test-dev-mandel2-func.js | |
87 | ||
88 | You can then connect to localhost:9093 and interact with the proxy. | |
89 | Here's an example session using telnet and manually typed in commands | |
90 | The ``-->`` (send) and ``<--`` (receiver) markers have been added for | |
91 | readability and are not part of the stream:: | |
92 | ||
93 | $ telnet localhost 9093 | |
94 | Trying 127.0.0.1... | |
95 | Connected to localhost. | |
96 | Escape character is '^]'. | |
97 | <-- {"notify":"_Connected","args":["1 10199 v1.1.0-275-gbd4d610-dirty duk command built from Duktape repo"]} | |
98 | <-- {"notify":"Status","command":1,"args":[1,"test-dev-mandel2-func.js","global",58,0]} | |
99 | --> {"request":"BasicInfo"} | |
100 | <-- {"reply":true,"args":[10199,"v1.1.0-275-gbd4d610-dirty","duk command built from Duktape repo",1]} | |
101 | --> {"request":"Eval", "args":[ "print(Math.PI)" ]} | |
102 | <-- {"notify":"Print","command":2,"args":["3.141592653589793\n"]} | |
103 | <-- {"reply":true,"args":[0,{"type":"undefined"}]} | |
104 | --> {"request":"Resume"} | |
105 | <-- {"reply":true,"args":[]} | |
106 | <-- {"notify":"Status","command":1,"args":[0,"test-dev-mandel2-func.js","global",58,0]} | |
107 | <-- {"notify":"Status","command":1,"args":[0,"test-dev-mandel2-func.js","global",58,0]} | |
108 | <-- {"notify":"Print","command":2,"args":["................................................................................\n"]} | |
109 | <-- {"notify":"Print","command":2,"args":["................................................................................\n"]} | |
110 | <-- {"notify":"Print","command":2,"args":["................................................................................\n"]} | |
111 | [...] | |
112 | <-- {"notify":"_Disconnecting"} | |
113 | ||
114 | A telnet connection allows you to experiment with debug commands by simply | |
115 | copy-pasting debug commands to the telnet session. This is useful even if | |
116 | you decide to implement the binary protocol directly. | |
117 | ||
118 | The debug target used by the proxy can be configured with ``duk_debug.js`` | |
119 | command line options. | |
120 | ||
121 | Source search path | |
122 | ================== | |
123 | ||
124 | The NodeJS debug client needs to be able to find source code files matching | |
125 | code running on the target ("duk" command line). **The filenames used on the | |
126 | target and on the debug client must match exactly**, because e.g. breakpoints | |
127 | are targeted based on the 'fileName' property of Function objects. | |
128 | ||
129 | The search path can be set using the ``--source-dirs`` option given to | |
130 | ``duk_debug.js``, with the default search paths including only | |
131 | ``../tests/ecmascript/``. | |
132 | ||
133 | The default search path means that if a function on the target has fileName | |
134 | ``foo/bar.js`` it would be loaded from (relative to the duk_debug.js working | |
135 | directory, ``debugger/``):: | |
136 | ||
137 | ../tests/ecmascript/foo/bar.js | |
138 | ||
139 | Similarly, if the filesystem contained:: | |
140 | ||
141 | ../tests/ecmascript/baz/quux.js | |
142 | ||
143 | the web UI dropdown would show ``baz/quux.js``. If you selected that file | |
144 | and added a breakpoint, the breakpoint fileName sent to the debug target | |
145 | would be ``baz/quux.js``. | |
146 | ||
147 | .. note:: There's much to improve in the search path. For instance, it'd | |
148 | be nice to add a certain path to search but exclude files based | |
149 | on paths and patterns, etc. | |
150 | ||
151 | Architecture | |
152 | ============ | |
153 | ||
154 | :: | |
155 | ||
156 | +-------------------+ | |
157 | | Web browser | [debug UI] | |
158 | +-------------------+ | |
159 | | | |
160 | | http (port 9092) | |
161 | | socket.io | |
162 | v | |
163 | +-------------------+ | |
164 | | duk_debug.js | [debug client] | |
165 | +-------------------+ | |
166 | | /\ | |
167 | | || | |
168 | +----------||---- [example tcp transport] (port 9091) | |
169 | | || (application provides concrete transport) | |
170 | | || | |
171 | | ||---- [debug protocol stream] | |
172 | | || (between debug client and Duktape) | |
173 | | || | |
174 | + - - | - - - - -|| - - + | |
175 | : v || : | |
176 | : +-------------||-+ : [target] | |
177 | : | application || | : | |
178 | : +-------------||-+ : | |
179 | : ^ || : | |
180 | : | || : [debug API] | |
181 | : +----------||-------- debug transport callbacks | |
182 | : | || : (read, write, peek, read/write flush) | |
183 | : | || : implemented by application | |
184 | : | \/ : | |
185 | : +----------------+ : | |
186 | : | Duktape | : | |
187 | : +----------------+ : | |
188 | + - - - - - - - - - - - + | |
189 | ||
190 | The debug transport is application specific: | |
191 | ||
192 | * Duktape command line ("duk") and this debug client use an **example** TCP | |
193 | transport as a concrete example. | |
194 | ||
195 | * It is entirely up to the application to come up with the most suitable | |
196 | transport for its environment. Different mechanisms will be needed for | |
197 | Wi-Fi, serial, etc. | |
198 | ||
199 | The debug protocol running inside the transport is transport independent: | |
200 | ||
201 | * The debug protocol is documented in ``doc/debugger.rst``. | |
202 | ||
203 | * This debug client provides further concrete examples and clarifications | |
204 | on how the protocol can be used. | |
205 | ||
206 | Using a custom transport | |
207 | ======================== | |
208 | ||
209 | Quite possibly your target device cannot use the example TCP transport and | |
210 | you need to implement your own transport. You'll need to implement your | |
211 | custom transport both for the target device and for the debug client. | |
212 | ||
213 | Target device | |
214 | ------------- | |
215 | ||
216 | Implement the debug transport callbacks needed by ``duk_debugger_attach()``. | |
217 | ||
218 | See ``doc/debugger.rst`` for details and ``examples/debug-trans-socket`` | |
219 | for example running code for a TCP transport. | |
220 | ||
221 | Debug client alternative 1: duk_debug.js + custom TCP proxy | |
222 | ----------------------------------------------------------- | |
223 | ||
224 | If you don't want to change ``duk_debug.js`` you can implement a TCP proxy | |
225 | which accepts a TCP connection from ``duk_debug.js`` and then uses your | |
226 | custom transport to talk to the target:: | |
227 | ||
228 | +--------------+ TCP +-------+ custom +--------+ | |
229 | | duk_debug.js | ------> | proxy | ---------> | target | | |
230 | +--------------+ +-------+ +--------+ | |
231 | ||
232 | This is a straightforward option and a proxy can be used with other debug | |
233 | clients too (perhaps custom scripts talking to the target etc). | |
234 | ||
235 | You could also use netcat and implement your proxy so that it talks to | |
236 | ``duk_debug.js`` using stdin/stdout. | |
237 | ||
238 | Debug client alternative 2: duk_debug.js + custom NodeJS stream | |
239 | --------------------------------------------------------------- | |
240 | ||
241 | To make ``duk_debug.js`` use a custom transport you need to: | |
242 | ||
243 | * Implement your own transport as NodeJS stream. You can add it directly to | |
244 | ``duk_debug.js`` but it's probably easiest to use a separate module so that | |
245 | the diff to ``duk_debug.js`` stays minimal. | |
246 | ||
247 | * Change ``duk_debug.js`` to use the custom transport instead of a TCP | |
248 | stream. Search for "CUSTOMTRANSPORT" in ``duk_debug.js``. | |
249 | ||
250 | See: | |
251 | ||
252 | * http://nodejs.org/api/stream.html | |
253 | ||
254 | * https://github.com/substack/stream-handbook | |
255 | ||
256 | Debug client alternative 3: custom debug client | |
257 | ----------------------------------------------- | |
258 | ||
259 | You can also implement your own debug client and debug UI with support for | |
260 | your custom transport. | |
261 | ||
262 | You'll also need to implement the client part of the Duktape debugger | |
263 | protocol. See ``doc/debugger.rst`` for the specification and ``duk_debug.js`` | |
264 | for example running code which should illustrate the protocol in more detail. | |
265 | ||
266 | The JSON debug proxy allows you to implement a debug client without needing | |
267 | to implement the Duktape binary debug protocol. The JSON protocol provides | |
268 | a roughly 1:1 mapping to the binary protocol but with an easier syntax. |