]> git.proxmox.com Git - ceph.git/blob - ceph/src/civetweb/src/third_party/duktape-1.8.0/debugger/README.rst
buildsys: switch source download to quincy
[ceph.git] / ceph / src / civetweb / src / third_party / duktape-1.8.0 / debugger / README.rst
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 on Unix and Windows.
11
12 Also provides a JSON debug proxy with a JSON mapping for the Duktape debug
13 protocol.
14
15 For detailed documentation of the debugger internals, see `debugger.rst`__.
16
17 __ https://github.com/svaarala/duktape/blob/master/doc/debugger.rst
18
19 Using the debugger web UI
20 =========================
21
22 Some prerequisites:
23
24 * You'll need Node.js v0.10.x or newer. Older Node.js versions don't support
25 the required packages.
26
27 Compile Duktape command line tool with debugger support (for further options
28 see http://wiki.duktape.org/FeatureOptions.html):
29
30 * ``DUK_OPT_DEBUGGER_SUPPORT``
31
32 * ``DUK_OPT_INTERRUPT_COUNTER``
33
34 * ``DUK_CMDLINE_DEBUGGER_SUPPORT``
35
36 The source distributable contains a Makefile to build a "duk" command with
37 debugger support::
38
39 $ cd <duktape dist directory>
40 $ make -f Makefile.dukdebug
41
42 The Duktape Git repo "duk" target has debugger support enabled by default::
43
44 $ make clean duk
45
46 Start Duktape command line tool so that it waits for a debugger connection::
47
48 # For now we need to be in the directory containing the source files
49 # executed so that the 'fileName' properties of functions will match
50 # that on the debug client.
51
52 # Using source distributable
53 $ cd <duktape dist directory>
54 $ ./duk --debugger mandel.js
55
56 # Using Duktape Git repo
57 $ cd <duktape checkout>/tests/ecmascript/
58 $ ../../duk --debugger test-dev-mandel2-func.js
59
60 Start the web UI::
61
62 # Must be in 'debugger' directory.
63
64 $ cd debugger/
65 $ make # runs 'node duk_debug.js'
66
67 Once the required packages are installed, the NodeJS debug client will be
68 up and running. Open the following in your browser and start debugging:
69
70 * http://localhost:9092/
71
72 The debug client automatically attaches to the debug target on startup.
73 If you start the debug target later, you'll need to click "Attach" in the
74 web UI.
75
76 Using the JSON debug proxy
77 ==========================
78
79 There are two JSON debug proxy implementations: one implemented in DukLuv
80 and another in Node.js.
81
82 DukLuv JSON proxy
83 -----------------
84
85 DukLuv (https://github.com/creationix/dukluv) is a small and portable event
86 loop based on LibUV and Duktape with MIT license (like Duktape). As such it's
87 easy to embed in a custom debug client: you just include the DukLuv executable
88 and the JSON proxy source file in your debug client.
89
90 Install DukLuv:
91
92 * Ensure ``cmake`` is installed
93
94 * ``git clone https://github.com/creationix/dukluv.git``
95
96 * ``git submodule init; git submodule update``
97
98 * ``make``
99
100 * Binary should appear in:
101
102 - ``./build/dukluv`` on Linux
103
104 - ``.\build\Debug\dukluv.exe`` on Windows
105
106 Run the proxy::
107
108 # Using Makefile; autogenerates duk_debug_meta.json
109 # (You may need to edit DUKLUV in Makefile to point to your DukLuv)
110 $ make runproxydukluv
111
112 # Manually: see "dukluv duk_debug_proxy.js --help" for help
113 $ .../path/to/dukluv duk_debug_proxy.js
114
115 Start Duktape command line (or whatever your target is)::
116
117 $ cd <duktape checkout>/tests/ecmascript/
118 $ ../../duk --debugger test-dev-mandel2-func.js
119
120 Now connect to the proxy using e.g. telnet::
121
122 $ telnet localhost 9093
123
124 The proxy will then connect to the target and you can start issuing commands::
125
126 $ telnet localhost 9093
127 Trying 127.0.0.1...
128 Connected to localhost.
129 Escape character is '^]'.
130 {"notify":"_TargetConnecting","args":["127.0.0.1",9091]}
131 {"notify":"_TargetConnected","args":["1 10499 v1.4.0-140-gc9a6c7c duk command built from Duktape repo"]}
132 {"notify":"Status","command":1,"args":[1,"test-dev-mandel2-func.js","global",58,0]}
133 {"request":"BasicInfo"}
134 {"reply":true,"args":[10499,"v1.4.0-140-gc9a6c7c","duk command built from Duktape repo",1]}
135 {"request":"Eval","args":["print('Hello world!'); 123;"]}
136 {"notify":"Print","command":2,"args":["Hello world!\n"]}
137 {"reply":true,"args":[0,{"type":"number","data":"405ec00000000000"}]}
138 [...]
139
140 The proxy log provides dumps both JSON and dvalue binary traffic which is
141 quite useful in development::
142
143 $ make runproxydukluv
144 Running Dukluv based debug proxy
145 "dukluv" duk_debug_proxy.js --log-level 2 --metadata duk_debug_meta.json
146 2016-02-17T13:59:42.308Z INF Proxy: Read proxy metadata from duk_debug_meta.json
147 2016-02-17T13:59:42.325Z INF Proxy: Listening for incoming JSON debug connection on 0.0.0.0:9093, target is 127.0.0.1:9091
148 2016-02-17T13:59:47.994Z INF Proxy: JSON proxy client connected
149 2016-02-17T13:59:47.994Z INF Proxy: Connecting to debug target at 127.0.0.1:9091
150 2016-02-17T13:59:47.994Z INF Proxy: PROXY --> CLIENT: {"notify":"_TargetConnecting","args":["127.0.0.1",9091]}
151 2016-02-17T13:59:47.994Z INF Proxy: Connected to debug target at 127.0.0.1:9091
152 2016-02-17T13:59:48.003Z INF Proxy: PROXY --> CLIENT: {"notify":"_TargetConnected","args":["1 10499 v1.4.0-140-gc9a6c7c duk command built from Duktape repo"]}
153 2016-02-17T13:59:48.003Z INF Proxy: Target handshake: {"line":"1 10499 v1.4.0-140-gc9a6c7c duk command built from Duktape repo","protocolVersion":1,"text":"10499 v1.4.0-140-gc9a6c7c duk command built from Duktape repo","dukVersion":"1","dukGitDescribe":"10499","targetString":"v1.4.0-140-gc9a6c7c"}
154 2016-02-17T13:59:48.151Z INF Proxy: PROXY <-- TARGET: |04|
155 2016-02-17T13:59:48.152Z INF Proxy: PROXY <-- TARGET: |81|
156 2016-02-17T13:59:48.152Z INF Proxy: PROXY <-- TARGET: |81|
157 2016-02-17T13:59:48.160Z INF Proxy: PROXY <-- TARGET: |78746573742d6465762d6d616e64656c322d66756e632e6a73|
158 2016-02-17T13:59:48.161Z INF Proxy: PROXY <-- TARGET: |66676c6f62616c|
159 2016-02-17T13:59:48.165Z INF Proxy: PROXY <-- TARGET: |ba|
160 2016-02-17T13:59:48.165Z INF Proxy: PROXY <-- TARGET: |80|
161 2016-02-17T13:59:48.165Z INF Proxy: PROXY <-- TARGET: |00|
162 2016-02-17T13:59:48.165Z INF Proxy: PROXY --> CLIENT: {"notify":"Status","command":1,"args":[1,"test-dev-mandel2-func.js","global",58,0]}
163 2016-02-17T13:59:51.289Z INF Proxy: PROXY <-- CLIENT: {"request":"BasicInfo"}
164 2016-02-17T13:59:51.289Z INF Proxy: PROXY --> TARGET: |01|
165 2016-02-17T13:59:51.289Z INF Proxy: PROXY --> TARGET: |90|
166 2016-02-17T13:59:51.289Z INF Proxy: PROXY --> TARGET: |00|
167 2016-02-17T13:59:51.291Z INF Proxy: PROXY <-- TARGET: |02|
168 2016-02-17T13:59:51.291Z INF Proxy: PROXY <-- TARGET: |e903|
169 2016-02-17T13:59:51.292Z INF Proxy: PROXY <-- TARGET: |7376312e342e302d3134302d6763396136633763|
170 2016-02-17T13:59:51.293Z INF Proxy: PROXY <-- TARGET: |12002364756b20636f6d6d616e64206275696c742066726f6d2044756b74617065207265706f|
171 2016-02-17T13:59:51.293Z INF Proxy: PROXY <-- TARGET: |81|
172 2016-02-17T13:59:51.293Z INF Proxy: PROXY <-- TARGET: |00|
173 2016-02-17T13:59:51.293Z INF Proxy: PROXY --> CLIENT: {"reply":true,"args":[10499,"v1.4.0-140-gc9a6c7c","duk command built from Duktape repo",1]}
174 2016-02-17T14:00:06.105Z INF Proxy: PROXY <-- CLIENT: {"request":"Eval","args":["print('Hello world!'); 123;"]}
175 2016-02-17T14:00:06.105Z INF Proxy: PROXY --> TARGET: |01|
176 2016-02-17T14:00:06.105Z INF Proxy: PROXY --> TARGET: |9e|
177 2016-02-17T14:00:06.105Z INF Proxy: PROXY --> TARGET: |7b7072696e74282748656c6c6f20776f726c642127293b203132333b|
178 2016-02-17T14:00:06.105Z INF Proxy: PROXY --> TARGET: |00|
179 2016-02-17T14:00:06.167Z INF Proxy: PROXY <-- TARGET: |04|
180 2016-02-17T14:00:06.167Z INF Proxy: PROXY <-- TARGET: |82|
181 2016-02-17T14:00:06.167Z INF Proxy: PROXY <-- TARGET: |6d48656c6c6f20776f726c64210a|
182 2016-02-17T14:00:06.168Z INF Proxy: PROXY <-- TARGET: |00|
183 2016-02-17T14:00:06.168Z INF Proxy: PROXY --> CLIENT: {"notify":"Print","command":2,"args":["Hello world!\n"]}
184 2016-02-17T14:00:06.171Z INF Proxy: PROXY <-- TARGET: |02|
185 2016-02-17T14:00:06.171Z INF Proxy: PROXY <-- TARGET: |80|
186 2016-02-17T14:00:06.173Z INF Proxy: PROXY <-- TARGET: |1a405ec00000000000|
187 2016-02-17T14:00:06.173Z INF Proxy: PROXY <-- TARGET: |00|
188 2016-02-17T14:00:06.174Z INF Proxy: PROXY --> CLIENT: {"reply":true,"args":[0,{"type":"number","data":"405ec00000000000"}]}
189 [...]
190
191 Node.js JSON proxy
192 ------------------
193
194 A Node.js-based JSON debug proxy is also provided by ``duk_debug.js``::
195
196 # Same prerequisites as for running the debug client
197 $ make runproxynodejs
198
199 Start Duktape command line (or whatever your target is)::
200
201 $ cd <duktape checkout>/tests/ecmascript/
202 $ ../../duk --debugger test-dev-mandel2-func.js
203
204 You can then connect to localhost:9093 and interact with the proxy.
205 Here's an example session using telnet and manually typed in commands
206 The ``-->`` (send) and ``<--`` (receiver) markers have been added for
207 readability and are not part of the stream::
208
209 $ telnet localhost 9093
210 Trying 127.0.0.1...
211 Connected to localhost.
212 Escape character is '^]'.
213 <-- {"notify":"_TargetConnected","args":["1 10199 v1.1.0-275-gbd4d610-dirty duk command built from Duktape repo"]}
214 <-- {"notify":"Status","command":1,"args":[1,"test-dev-mandel2-func.js","global",58,0]}
215 --> {"request":"BasicInfo"}
216 <-- {"reply":true,"args":[10199,"v1.1.0-275-gbd4d610-dirty","duk command built from Duktape repo",1]}
217 --> {"request":"Eval", "args":[ "print(Math.PI)" ]}
218 <-- {"notify":"Print","command":2,"args":["3.141592653589793\n"]}
219 <-- {"reply":true,"args":[0,{"type":"undefined"}]}
220 --> {"request":"Resume"}
221 <-- {"reply":true,"args":[]}
222 <-- {"notify":"Status","command":1,"args":[0,"test-dev-mandel2-func.js","global",58,0]}
223 <-- {"notify":"Status","command":1,"args":[0,"test-dev-mandel2-func.js","global",58,0]}
224 <-- {"notify":"Print","command":2,"args":["................................................................................\n"]}
225 <-- {"notify":"Print","command":2,"args":["................................................................................\n"]}
226 <-- {"notify":"Print","command":2,"args":["................................................................................\n"]}
227 [...]
228 <-- {"notify":"_Disconnecting"}
229
230 A telnet connection allows you to experiment with debug commands by simply
231 copy-pasting debug commands to the telnet session. This is useful even if
232 you decide to implement the binary protocol directly.
233
234 The debug target used by the proxy can be configured with ``duk_debug.js``
235 command line options.
236
237 Source search path
238 ==================
239
240 The NodeJS debug client needs to be able to find source code files matching
241 code running on the target ("duk" command line). **The filenames used on the
242 target and on the debug client must match exactly**, because e.g. breakpoints
243 are targeted based on the 'fileName' property of Function objects.
244
245 The search path can be set using the ``--source-dirs`` option given to
246 ``duk_debug.js``, with the default search paths including only
247 ``../tests/ecmascript/``.
248
249 The default search path means that if a function on the target has fileName
250 ``foo/bar.js`` it would be loaded from (relative to the duk_debug.js working
251 directory, ``debugger/``)::
252
253 ../tests/ecmascript/foo/bar.js
254
255 Similarly, if the filesystem contained::
256
257 ../tests/ecmascript/baz/quux.js
258
259 the web UI dropdown would show ``baz/quux.js``. If you selected that file
260 and added a breakpoint, the breakpoint fileName sent to the debug target
261 would be ``baz/quux.js``.
262
263 .. note:: There's much to improve in the search path. For instance, it'd
264 be nice to add a certain path to search but exclude files based
265 on paths and patterns, etc.
266
267 Architecture
268 ============
269
270 ::
271
272 +-------------------+
273 | Web browser | [debug UI]
274 +-------------------+
275 |
276 | http (port 9092)
277 | socket.io
278 v
279 +-------------------+
280 | duk_debug.js | [debug client]
281 +-------------------+
282 | /\
283 | ||
284 +----------||---- [example tcp transport] (port 9091)
285 | || (application provides concrete transport)
286 | ||
287 | ||---- [debug protocol stream]
288 | || (between debug client and Duktape)
289 | ||
290 + - - | - - - - -|| - - +
291 : v || :
292  : +-------------||-+ : [target]
293 : | application || | :
294 : +-------------||-+ :
295 : ^ || :
296 : | || : [debug API]
297 : +----------||-------- debug transport callbacks
298 : | || : (read, write, peek, read/write flush)
299 : | || : implemented by application
300 : | \/ :
301 : +----------------+ :
302 : | Duktape | :
303 : +----------------+ :
304 + - - - - - - - - - - - +
305
306 The debug transport is application specific:
307
308 * Duktape command line ("duk") and this debug client use an **example** TCP
309 transport as a concrete example.
310
311 * It is entirely up to the application to come up with the most suitable
312 transport for its environment. Different mechanisms will be needed for
313 Wi-Fi, serial, etc.
314
315 The debug protocol running inside the transport is transport independent:
316
317 * The debug protocol is documented in ``doc/debugger.rst``.
318
319 * This debug client provides further concrete examples and clarifications
320 on how the protocol can be used.
321
322 Using a custom transport
323 ========================
324
325 Quite possibly your target device cannot use the example TCP transport and
326 you need to implement your own transport. You'll need to implement your
327 custom transport both for the target device and for the debug client.
328
329 Target device
330 -------------
331
332 Implement the debug transport callbacks needed by ``duk_debugger_attach()``.
333
334 See ``doc/debugger.rst`` for details and ``examples/debug-trans-socket``
335 for example running code for a TCP transport.
336
337 Debug client alternative 1: duk_debug.js + custom TCP proxy
338 -----------------------------------------------------------
339
340 If you don't want to change ``duk_debug.js`` you can implement a TCP proxy
341 which accepts a TCP connection from ``duk_debug.js`` and then uses your
342 custom transport to talk to the target::
343
344 +--------------+ TCP +-------+ custom +--------+
345 | duk_debug.js | ------> | proxy | ---------> | target |
346 +--------------+ +-------+ +--------+
347
348 This is a straightforward option and a proxy can be used with other debug
349 clients too (perhaps custom scripts talking to the target etc).
350
351 You could also use netcat and implement your proxy so that it talks to
352 ``duk_debug.js`` using stdin/stdout.
353
354 Debug client alternative 2: duk_debug.js + custom NodeJS stream
355 ---------------------------------------------------------------
356
357 To make ``duk_debug.js`` use a custom transport you need to:
358
359 * Implement your own transport as NodeJS stream. You can add it directly to
360 ``duk_debug.js`` but it's probably easiest to use a separate module so that
361 the diff to ``duk_debug.js`` stays minimal.
362
363 * Change ``duk_debug.js`` to use the custom transport instead of a TCP
364 stream. Search for "CUSTOMTRANSPORT" in ``duk_debug.js``.
365
366 See:
367
368 * http://nodejs.org/api/stream.html
369
370 * https://github.com/substack/stream-handbook
371
372 Debug client alternative 3: custom debug client
373 -----------------------------------------------
374
375 You can also implement your own debug client and debug UI with support for
376 your custom transport.
377
378 You'll also need to implement the client part of the Duktape debugger
379 protocol. See ``doc/debugger.rst`` for the specification and ``duk_debug.js``
380 for example running code which should illustrate the protocol in more detail.
381
382 The JSON debug proxy allows you to implement a debug client without needing
383 to implement the Duktape binary debug protocol. The JSON protocol provides
384 a roughly 1:1 mapping to the binary protocol but with an easier syntax.