• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright JS Foundation and other contributors, http://js.foundation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef DEBUGGER_H
17 #define DEBUGGER_H
18 
19 #include "ecma-globals.h"
20 #include "jerryscript-debugger-transport.h"
21 
22 #if ENABLED (JERRY_DEBUGGER)
23 
24 /* JerryScript debugger protocol is a simplified version of RFC-6455 (WebSockets). */
25 
26 /**
27  * Frequency of calling jerry_debugger_receive() by the VM.
28  */
29 #define JERRY_DEBUGGER_MESSAGE_FREQUENCY 5
30 
31 /**
32  * This constant represents that the string to be sent has no subtype.
33  */
34 #define JERRY_DEBUGGER_NO_SUBTYPE 0
35 
36 /**
37  * Limited resources available for the engine, so it is important to
38  * check the maximum buffer size. It needs to be between 64 and 256 bytes.
39  */
40 #if JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE < 64 || JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE > 256
41 #error Please define the MAX_BUFFER_SIZE between 64 and 256 bytes.
42 #endif /* JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE < 64 || JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE > 256 */
43 
44 /**
45  * Calculate the maximum number of items for a given type
46  * which can be transmitted in one message.
47  */
48 #define JERRY_DEBUGGER_SEND_MAX(type) \
49   ((size_t) ((JERRY_CONTEXT (debugger_max_send_size) - sizeof (jerry_debugger_send_type_t)) / sizeof (type)))
50 
51 /**
52  * Calculate the size of a message when a count number of items transmitted.
53  */
54 #define JERRY_DEBUGGER_SEND_SIZE(count, type) \
55   ((size_t) ((count * sizeof (type)) + sizeof (jerry_debugger_send_type_t)))
56 
57 /**
58  * Debugger operation modes:
59  *
60  * The debugger has two operation modes: run mode and breakpoint mode.
61  *
62  * In run mode the debugger server accepts only a limited number of message
63  * types from the debugger client (e.g. stop execution, set breakpoint).
64  *
65  * In breakpoint mode the JavaScript execution is stopped at a breakpoint and
66  * more message types are accepted (e.g. get backtrace, evaluate expression).
67  *
68  * Switching between modes:
69  *
70  * When the JavaScript execution stops at a breakpoint the server sends a
71  * JERRY_DEBUGGER_BREAKPOINT_HIT message to the client. The client can only
72  * issue breakpoint mode commands after this message is received.
73  *
74  * Certain breakpoint mode commands (e.g. continue) resumes the JavaScript
75  * execution and the client must not send any breakpoint mode messages
76  * until the JERRY_DEBUGGER_BREAKPOINT_HIT is received again.
77  *
78  * The debugger server starts in run mode but stops at the first available
79  * breakpoint.
80  */
81 
82 /**
83  * Debugger option flags.
84  */
85 typedef enum
86 {
87   JERRY_DEBUGGER_CONNECTED = 1u << 0, /**< debugger is connected */
88   JERRY_DEBUGGER_BREAKPOINT_MODE = 1u << 1, /**< debugger waiting at a breakpoint */
89   JERRY_DEBUGGER_VM_STOP = 1u << 2, /**< stop at the next breakpoint even if disabled */
90   JERRY_DEBUGGER_VM_IGNORE = 1u << 3, /**< ignore all breakpoints */
91   JERRY_DEBUGGER_VM_IGNORE_EXCEPTION = 1u << 4, /**< debugger doesn't stop at any exception */
92   JERRY_DEBUGGER_VM_EXCEPTION_THROWN = 1u << 5, /**< no need to stop for this exception */
93   JERRY_DEBUGGER_PARSER_WAIT = 1u << 6, /**< debugger should wait after parsing is completed */
94   JERRY_DEBUGGER_PARSER_WAIT_MODE = 1u << 7, /**< debugger is waiting after parsing is completed */
95   JERRY_DEBUGGER_CLIENT_SOURCE_MODE = 1u << 8, /**< debugger waiting for client code */
96   JERRY_DEBUGGER_CLIENT_NO_SOURCE = 1u << 9, /**< debugger leaving the client source loop */
97   JERRY_DEBUGGER_CONTEXT_RESET_MODE = 1u << 10, /**< debugger and engine reinitialization mode */
98 #ifdef ACE_DEBUGGER_CUSTOM
99   JERRY_DEBUGGER_TRANSPORT_STARTED = 1u << 11, /**< only can send data to client after this flag set */
100 #endif
101 } jerry_debugger_flags_t;
102 
103 /**
104  * Set debugger flags.
105  */
106 #define JERRY_DEBUGGER_SET_FLAGS(flags) \
107   JERRY_CONTEXT (debugger_flags) = (JERRY_CONTEXT (debugger_flags) | (uint32_t) (flags))
108 
109 /**
110  * Clear debugger flags.
111  */
112 #define JERRY_DEBUGGER_CLEAR_FLAGS(flags) \
113   JERRY_CONTEXT (debugger_flags) = (JERRY_CONTEXT (debugger_flags) & (uint32_t) ~(flags))
114 
115 /**
116  * Set and clear debugger flags.
117  */
118 #define JERRY_DEBUGGER_UPDATE_FLAGS(flags_to_set, flags_to_clear) \
119   JERRY_CONTEXT (debugger_flags) = ((JERRY_CONTEXT (debugger_flags) | (uint32_t) (flags_to_set)) \
120                                     & (uint32_t) ~(flags_to_clear))
121 
122 /**
123  * Types for the package.
124  */
125 typedef enum
126 {
127   /* Messages sent by the server to client. */
128   /* This is a handshake message, sent once during initialization. */
129   JERRY_DEBUGGER_CONFIGURATION = 1, /**< debugger configuration */
130   /* These messages are sent by the parser. */
131   JERRY_DEBUGGER_PARSE_ERROR = 2, /**< parse error */
132   JERRY_DEBUGGER_BYTE_CODE_CP = 3, /**< byte code compressed pointer */
133   JERRY_DEBUGGER_PARSE_FUNCTION = 4, /**< parsing a new function */
134   JERRY_DEBUGGER_BREAKPOINT_LIST = 5, /**< list of line offsets */
135   JERRY_DEBUGGER_BREAKPOINT_OFFSET_LIST = 6, /**< list of byte code offsets */
136   JERRY_DEBUGGER_SOURCE_CODE = 7, /**< source code fragment */
137   JERRY_DEBUGGER_SOURCE_CODE_END = 8, /**< source code last fragment */
138   JERRY_DEBUGGER_SOURCE_CODE_NAME = 9, /**< source code name fragment */
139   JERRY_DEBUGGER_SOURCE_CODE_NAME_END = 10, /**< source code name last fragment */
140   JERRY_DEBUGGER_FUNCTION_NAME = 11, /**< function name fragment */
141   JERRY_DEBUGGER_FUNCTION_NAME_END = 12, /**< function name last fragment */
142   JERRY_DEBUGGER_WAITING_AFTER_PARSE = 13, /**< engine waiting for a parser resume */
143   /* These messages are generic messages. */
144   JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 14, /**< invalidate byte code compressed pointer */
145   JERRY_DEBUGGER_MEMSTATS_RECEIVE = 15, /**< memstats sent to the client */
146   JERRY_DEBUGGER_BREAKPOINT_HIT = 16, /**< notify breakpoint hit */
147   JERRY_DEBUGGER_EXCEPTION_HIT = 17, /**< notify exception hit */
148   JERRY_DEBUGGER_EXCEPTION_STR = 18, /**< exception string fragment */
149   JERRY_DEBUGGER_EXCEPTION_STR_END = 19, /**< exception string last fragment */
150   JERRY_DEBUGGER_BACKTRACE_TOTAL = 20, /**< number of total frames */
151   JERRY_DEBUGGER_BACKTRACE = 21, /**< backtrace data */
152   JERRY_DEBUGGER_BACKTRACE_END = 22, /**< last backtrace data */
153   JERRY_DEBUGGER_EVAL_RESULT = 23, /**< eval result */
154   JERRY_DEBUGGER_EVAL_RESULT_END = 24, /**< last part of eval result */
155   JERRY_DEBUGGER_WAIT_FOR_SOURCE = 25, /**< engine waiting for source code */
156   JERRY_DEBUGGER_OUTPUT_RESULT = 26, /**< output sent by the program to the debugger */
157   JERRY_DEBUGGER_OUTPUT_RESULT_END = 27, /**< last output result data */
158   JERRY_DEBUGGER_SCOPE_CHAIN = 28, /**< scope chain */
159   JERRY_DEBUGGER_SCOPE_CHAIN_END = 29, /**< last output of scope chain */
160   JERRY_DEBUGGER_SCOPE_VARIABLES = 30, /**< scope variables */
161   JERRY_DEBUGGER_SCOPE_VARIABLES_END = 31, /**< last output of scope variables */
162   JERRY_DEBUGGER_CLOSE_CONNECTION = 32, /**< close connection with the client */
163   JERRY_DEBUGGER_MESSAGES_OUT_MAX_COUNT, /**< number of different type of output messages by the debugger */
164 
165   /* Messages sent by the client to server. */
166 
167   /* The following messages are accepted in both run and breakpoint modes. */
168   JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1, /**< free byte code compressed pointer */
169   JERRY_DEBUGGER_UPDATE_BREAKPOINT = 2, /**< update breakpoint status */
170   JERRY_DEBUGGER_EXCEPTION_CONFIG = 3, /**< exception handler config */
171   JERRY_DEBUGGER_PARSER_CONFIG = 4, /**< parser config */
172   JERRY_DEBUGGER_MEMSTATS = 5, /**< list memory statistics */
173   JERRY_DEBUGGER_STOP = 6, /**< stop execution */
174   /* The following message is only available in waiting after parse mode. */
175   JERRY_DEBUGGER_PARSER_RESUME = 7, /**< stop waiting after parse */
176   /* The following four messages are only available in client switch mode. */
177   JERRY_DEBUGGER_CLIENT_SOURCE = 8, /**< first message of client source */
178   JERRY_DEBUGGER_CLIENT_SOURCE_PART = 9, /**< next message of client source */
179   JERRY_DEBUGGER_NO_MORE_SOURCES = 10, /**< no more sources notification */
180   JERRY_DEBUGGER_CONTEXT_RESET = 11, /**< context reset request */
181   /* The following messages are only available in breakpoint
182    * mode and they switch the engine to run mode. */
183   JERRY_DEBUGGER_CONTINUE = 12, /**< continue execution */
184   JERRY_DEBUGGER_STEP = 13, /**< next breakpoint, step into functions */
185   JERRY_DEBUGGER_NEXT = 14, /**< next breakpoint in the same context */
186   JERRY_DEBUGGER_FINISH = 15, /**< Continue running just after the function in the current stack frame returns */
187   /* The following messages are only available in breakpoint
188    * mode and this mode is kept after the message is processed. */
189   JERRY_DEBUGGER_GET_BACKTRACE = 16, /**< get backtrace */
190   JERRY_DEBUGGER_EVAL = 17, /**< first message of evaluating a string */
191   JERRY_DEBUGGER_EVAL_PART = 18, /**< next message of evaluating a string */
192   JERRY_DEBUGGER_GET_SCOPE_CHAIN = 19, /**< get type names of the scope chain */
193   JERRY_DEBUGGER_GET_SCOPE_VARIABLES = 20, /**< get variables of a scope */
194   JERRY_DEBUGGER_MESSAGES_IN_MAX_COUNT, /**< number of different type of input messages */
195 } jerry_debugger_header_type_t;
196 
197 /**
198  * Debugger option flags.
199  */
200 typedef enum
201 {
202   JERRY_DEBUGGER_LITTLE_ENDIAN = 1u << 0, /**< little endian */
203 } jerry_debugger_configuration_flags_t;
204 
205 /**
206  * Subtypes of eval.
207  */
208 typedef enum
209 {
210   JERRY_DEBUGGER_EVAL_EVAL = 0, /**< evaluate expression */
211   JERRY_DEBUGGER_EVAL_THROW = 1, /**< evaluate expression and throw the result */
212   JERRY_DEBUGGER_EVAL_ABORT = 2, /**< evaluate expression and abrot with the result */
213 } jerry_debugger_eval_type_t;
214 
215 /**
216  * Subtypes of eval_result.
217  */
218 typedef enum
219 {
220   JERRY_DEBUGGER_EVAL_OK = 1, /**< eval result, no error */
221   JERRY_DEBUGGER_EVAL_ERROR = 2, /**< eval result when an error has occurred */
222 } jerry_debugger_eval_result_type_t;
223 
224 /**
225  * Subtypes of output_result.
226  *
227  * Note:
228  *      This enum has to be kept in sync with jerry_log_level_t with an offset
229  *      of +2.
230  */
231 typedef enum
232 {
233   JERRY_DEBUGGER_OUTPUT_OK = 1, /**< output result, no error */
234   JERRY_DEBUGGER_OUTPUT_ERROR = 2, /**< output result, error */
235   JERRY_DEBUGGER_OUTPUT_WARNING = 3, /**< output result, warning */
236   JERRY_DEBUGGER_OUTPUT_DEBUG = 4, /**< output result, debug */
237   JERRY_DEBUGGER_OUTPUT_TRACE = 5, /**< output result, trace */
238 } jerry_debugger_output_subtype_t;
239 
240 /**
241  * Types of scopes.
242  */
243 typedef enum
244 {
245   JERRY_DEBUGGER_SCOPE_WITH = 1, /**< with */
246   JERRY_DEBUGGER_SCOPE_LOCAL = 2, /**< local */
247   JERRY_DEBUGGER_SCOPE_CLOSURE = 3, /**< closure */
248   JERRY_DEBUGGER_SCOPE_GLOBAL = 4, /**< global */
249   JERRY_DEBUGGER_SCOPE_NON_CLOSURE = 5 /**< non closure */
250 } jerry_debugger_scope_chain_type_t;
251 
252 /**
253  * Type of scope variables.
254  */
255 typedef enum
256 {
257   JERRY_DEBUGGER_VALUE_NONE = 1,
258   JERRY_DEBUGGER_VALUE_UNDEFINED = 2,
259   JERRY_DEBUGGER_VALUE_NULL = 3,
260   JERRY_DEBUGGER_VALUE_BOOLEAN = 4,
261   JERRY_DEBUGGER_VALUE_NUMBER = 5,
262   JERRY_DEBUGGER_VALUE_STRING = 6,
263   JERRY_DEBUGGER_VALUE_FUNCTION = 7,
264   JERRY_DEBUGGER_VALUE_ARRAY = 8,
265   JERRY_DEBUGGER_VALUE_OBJECT = 9
266 } jerry_debugger_scope_variable_type_t;
267 
268 /**
269  * Byte data for evaluating expressions and receiving client source.
270  */
271 typedef struct
272 {
273   uint32_t uint8_size; /**< total size of the client source */
274   uint32_t uint8_offset; /**< current offset in the client source */
275 } jerry_debugger_uint8_data_t;
276 
277 /**
278  * Delayed free of byte code data.
279  */
280 typedef struct
281 {
282   uint16_t size; /**< size of the byte code header divided by JMEM_ALIGNMENT */
283   jmem_cpointer_t prev_cp; /**< previous byte code data to be freed */
284 } jerry_debugger_byte_code_free_t;
285 
286 /**
287  * Outgoing message: JerryScript configuration.
288  */
289 typedef struct
290 {
291   uint8_t type; /**< type of the message */
292   uint8_t configuration; /**< configuration option bits */
293   uint8_t version[sizeof (uint32_t)]; /**< debugger version */
294   uint8_t max_message_size; /**< maximum incoming message size */
295   uint8_t cpointer_size; /**< size of compressed pointers */
296 } jerry_debugger_send_configuration_t;
297 
298 /**
299  * Outgoing message: message without arguments.
300  */
301 typedef struct
302 {
303   uint8_t type; /**< type of the message */
304 } jerry_debugger_send_type_t;
305 
306 /**
307  * Incoming message: message without arguments.
308  */
309 typedef struct
310 {
311   uint8_t type; /**< type of the message */
312 } jerry_debugger_receive_type_t;
313 
314 /**
315  * Outgoing message: string (Source file name or function name).
316  */
317 typedef struct
318 {
319   uint8_t type; /**< type of the message */
320   uint8_t string[]; /**< string data */
321 } jerry_debugger_send_string_t;
322 
323 /**
324  * Outgoing message: uint32 value.
325  */
326 typedef struct
327 {
328   uint8_t type; /**< type of the message */
329   uint8_t line[sizeof (uint32_t)]; /**< value data */
330   uint8_t column[sizeof (uint32_t)]; /**< value data */
331 } jerry_debugger_send_parse_function_t;
332 
333 /**
334  * Outgoing message: byte code compressed pointer.
335  */
336 typedef struct
337 {
338   uint8_t type; /**< type of the message */
339   uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */
340 } jerry_debugger_send_byte_code_cp_t;
341 
342 /**
343  * Incoming message: byte code compressed pointer.
344  */
345 typedef struct
346 {
347   uint8_t type; /**< type of the message */
348   uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */
349 } jerry_debugger_receive_byte_code_cp_t;
350 
351 /**
352  * Incoming message: update (enable/disable) breakpoint status.
353  */
354 typedef struct
355 {
356   uint8_t type; /**< type of the message */
357   uint8_t is_set_breakpoint; /**< set or clear breakpoint */
358   uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */
359   uint8_t offset[sizeof (uint32_t)]; /**< breakpoint offset */
360 } jerry_debugger_receive_update_breakpoint_t;
361 
362 /**
363  * Outgoing message: send memory statistics
364  */
365 typedef struct
366 {
367   uint8_t type; /**< type of the message */
368   uint8_t allocated_bytes[sizeof (uint32_t)]; /**< allocated bytes */
369   uint8_t byte_code_bytes[sizeof (uint32_t)]; /**< byte code bytes */
370   uint8_t string_bytes[sizeof (uint32_t)]; /**< string bytes */
371   uint8_t object_bytes[sizeof (uint32_t)]; /**< object bytes */
372   uint8_t property_bytes[sizeof (uint32_t)]; /**< property bytes */
373 } jerry_debugger_send_memstats_t;
374 
375 /**
376  * Outgoing message: notify breakpoint hit.
377  */
378 typedef struct
379 {
380   uint8_t type; /**< type of the message */
381   uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */
382   uint8_t offset[sizeof (uint32_t)]; /**< breakpoint offset */
383 } jerry_debugger_send_breakpoint_hit_t;
384 
385 /**
386  * Stack frame descriptor for sending backtrace information.
387  */
388 typedef struct
389 {
390   uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */
391   uint8_t offset[sizeof (uint32_t)]; /**< last breakpoint offset */
392 } jerry_debugger_frame_t;
393 
394 /**
395  * Outgoing message: backtrace information.
396  */
397 typedef struct
398 {
399   uint8_t type; /**< type of the message */
400   jerry_debugger_frame_t frames[]; /**< frames */
401 } jerry_debugger_send_backtrace_t;
402 
403 /**
404  * Outgoing message: scope chain.
405  */
406 typedef struct
407 {
408   uint8_t type; /**< type of the message */
409   uint8_t scope_types[]; /**< scope types */
410 } jerry_debugger_send_scope_chain_t;
411 
412 /**
413  * Outgoing message: number of total frames in backtrace.
414  */
415 typedef struct
416 {
417   uint8_t type; /**< type of the message */
418   uint8_t frame_count[sizeof (uint32_t)]; /**< total number of frames */
419 } jerry_debugger_send_backtrace_total_t;
420 
421 /**
422  * Incoming message: set behaviour when exception occures.
423  */
424 typedef struct
425 {
426   uint8_t type; /**< type of the message */
427   uint8_t enable; /**< non-zero: enable stop at exception */
428 } jerry_debugger_receive_exception_config_t;
429 
430 /**
431  * Incoming message: set parser configuration.
432  */
433 typedef struct
434 {
435   uint8_t type; /**< type of the message */
436   uint8_t enable_wait; /**< non-zero: wait after parsing is completed */
437 } jerry_debugger_receive_parser_config_t;
438 
439 /**
440  * Incoming message: get backtrace.
441  */
442 typedef struct
443 {
444   uint8_t type; /**< type of the message */
445   uint8_t min_depth[sizeof (uint32_t)]; /**< minimum depth*/
446   uint8_t max_depth[sizeof (uint32_t)]; /**< maximum depth (0 - unlimited) */
447   uint8_t get_total_frame_count; /**< non-zero: if total frame count is also requested */
448 } jerry_debugger_receive_get_backtrace_t;
449 
450 /**
451  * Incoming message: first message of evaluating expression.
452  */
453 typedef struct
454 {
455   uint8_t type; /**< type of the message */
456   uint8_t eval_size[sizeof (uint32_t)]; /**< total size of the message */
457 } jerry_debugger_receive_eval_first_t;
458 
459 /**
460  * Incoming message: get scope variables
461 */
462 typedef struct
463 {
464   uint8_t type; /**< type of the message */
465   uint8_t chain_index[sizeof (uint32_t)]; /**< index element of the scope */
466 } jerry_debugger_receive_get_scope_variables_t;
467 
468 /**
469  * Incoming message: first message of client source.
470  */
471 typedef struct
472 {
473   uint8_t type; /**< type of the message */
474   uint8_t code_size[sizeof (uint32_t)]; /**< total size of the message */
475 } jerry_debugger_receive_client_source_first_t;
476 
477 void jerry_debugger_free_unreferenced_byte_code (void);
478 
479 bool jerry_debugger_receive (jerry_debugger_uint8_data_t **message_data_p);
480 
481 void jerry_debugger_breakpoint_hit (uint8_t message_type);
482 
483 void jerry_debugger_send_type (jerry_debugger_header_type_t type);
484 bool jerry_debugger_send_configuration (uint8_t max_message_size);
485 void jerry_debugger_send_data (jerry_debugger_header_type_t type, const void *data, size_t size);
486 bool jerry_debugger_send_string (uint8_t message_type, uint8_t sub_type, const uint8_t *string_p, size_t string_length);
487 bool jerry_debugger_send_function_cp (jerry_debugger_header_type_t type, ecma_compiled_code_t *compiled_code_p);
488 bool jerry_debugger_send_parse_function (uint32_t line, uint32_t column);
489 void jerry_debugger_send_memstats (void);
490 bool jerry_debugger_send_exception_string (ecma_value_t exception_value);
491 
492 #endif /* ENABLED (JERRY_DEBUGGER) */
493 
494 #endif /* !DEBUGGER_H */
495