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 */
85typedef 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} jerry_debugger_flags_t;
99
100/**
101 * Set debugger flags.
102 */
103#define JERRY_DEBUGGER_SET_FLAGS(flags) \
104 JERRY_CONTEXT (debugger_flags) = (JERRY_CONTEXT (debugger_flags) | (uint32_t) (flags))
105
106/**
107 * Clear debugger flags.
108 */
109#define JERRY_DEBUGGER_CLEAR_FLAGS(flags) \
110 JERRY_CONTEXT (debugger_flags) = (JERRY_CONTEXT (debugger_flags) & (uint32_t) ~(flags))
111
112/**
113 * Set and clear debugger flags.
114 */
115#define JERRY_DEBUGGER_UPDATE_FLAGS(flags_to_set, flags_to_clear) \
116 JERRY_CONTEXT (debugger_flags) = ((JERRY_CONTEXT (debugger_flags) | (uint32_t) (flags_to_set)) \
117 & (uint32_t) ~(flags_to_clear))
118
119/**
120 * Types for the package.
121 */
122typedef enum
123{
124 /* Messages sent by the server to client. */
125 /* This is a handshake message, sent once during initialization. */
126 JERRY_DEBUGGER_CONFIGURATION = 1, /**< debugger configuration */
127 /* These messages are sent by the parser. */
128 JERRY_DEBUGGER_PARSE_ERROR = 2, /**< parse error */
129 JERRY_DEBUGGER_BYTE_CODE_CP = 3, /**< byte code compressed pointer */
130 JERRY_DEBUGGER_PARSE_FUNCTION = 4, /**< parsing a new function */
131 JERRY_DEBUGGER_BREAKPOINT_LIST = 5, /**< list of line offsets */
132 JERRY_DEBUGGER_BREAKPOINT_OFFSET_LIST = 6, /**< list of byte code offsets */
133 JERRY_DEBUGGER_SOURCE_CODE = 7, /**< source code fragment */
134 JERRY_DEBUGGER_SOURCE_CODE_END = 8, /**< source code last fragment */
135 JERRY_DEBUGGER_SOURCE_CODE_NAME = 9, /**< source code name fragment */
136 JERRY_DEBUGGER_SOURCE_CODE_NAME_END = 10, /**< source code name last fragment */
137 JERRY_DEBUGGER_FUNCTION_NAME = 11, /**< function name fragment */
138 JERRY_DEBUGGER_FUNCTION_NAME_END = 12, /**< function name last fragment */
139 JERRY_DEBUGGER_WAITING_AFTER_PARSE = 13, /**< engine waiting for a parser resume */
140 /* These messages are generic messages. */
141 JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 14, /**< invalidate byte code compressed pointer */
142 JERRY_DEBUGGER_MEMSTATS_RECEIVE = 15, /**< memstats sent to the client */
143 JERRY_DEBUGGER_BREAKPOINT_HIT = 16, /**< notify breakpoint hit */
144 JERRY_DEBUGGER_EXCEPTION_HIT = 17, /**< notify exception hit */
145 JERRY_DEBUGGER_EXCEPTION_STR = 18, /**< exception string fragment */
146 JERRY_DEBUGGER_EXCEPTION_STR_END = 19, /**< exception string last fragment */
147 JERRY_DEBUGGER_BACKTRACE_TOTAL = 20, /**< number of total frames */
148 JERRY_DEBUGGER_BACKTRACE = 21, /**< backtrace data */
149 JERRY_DEBUGGER_BACKTRACE_END = 22, /**< last backtrace data */
150 JERRY_DEBUGGER_EVAL_RESULT = 23, /**< eval result */
151 JERRY_DEBUGGER_EVAL_RESULT_END = 24, /**< last part of eval result */
152 JERRY_DEBUGGER_WAIT_FOR_SOURCE = 25, /**< engine waiting for source code */
153 JERRY_DEBUGGER_OUTPUT_RESULT = 26, /**< output sent by the program to the debugger */
154 JERRY_DEBUGGER_OUTPUT_RESULT_END = 27, /**< last output result data */
155 JERRY_DEBUGGER_SCOPE_CHAIN = 28, /**< scope chain */
156 JERRY_DEBUGGER_SCOPE_CHAIN_END = 29, /**< last output of scope chain */
157 JERRY_DEBUGGER_SCOPE_VARIABLES = 30, /**< scope variables */
158 JERRY_DEBUGGER_SCOPE_VARIABLES_END = 31, /**< last output of scope variables */
159 JERRY_DEBUGGER_CLOSE_CONNECTION = 32, /**< close connection with the client */
160 JERRY_DEBUGGER_MESSAGES_OUT_MAX_COUNT, /**< number of different type of output messages by the debugger */
161
162 /* Messages sent by the client to server. */
163
164 /* The following messages are accepted in both run and breakpoint modes. */
165 JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1, /**< free byte code compressed pointer */
166 JERRY_DEBUGGER_UPDATE_BREAKPOINT = 2, /**< update breakpoint status */
167 JERRY_DEBUGGER_EXCEPTION_CONFIG = 3, /**< exception handler config */
168 JERRY_DEBUGGER_PARSER_CONFIG = 4, /**< parser config */
169 JERRY_DEBUGGER_MEMSTATS = 5, /**< list memory statistics */
170 JERRY_DEBUGGER_STOP = 6, /**< stop execution */
171 /* The following message is only available in waiting after parse mode. */
172 JERRY_DEBUGGER_PARSER_RESUME = 7, /**< stop waiting after parse */
173 /* The following four messages are only available in client switch mode. */
174 JERRY_DEBUGGER_CLIENT_SOURCE = 8, /**< first message of client source */
175 JERRY_DEBUGGER_CLIENT_SOURCE_PART = 9, /**< next message of client source */
176 JERRY_DEBUGGER_NO_MORE_SOURCES = 10, /**< no more sources notification */
177 JERRY_DEBUGGER_CONTEXT_RESET = 11, /**< context reset request */
178 /* The following messages are only available in breakpoint
179 * mode and they switch the engine to run mode. */
180 JERRY_DEBUGGER_CONTINUE = 12, /**< continue execution */
181 JERRY_DEBUGGER_STEP = 13, /**< next breakpoint, step into functions */
182 JERRY_DEBUGGER_NEXT = 14, /**< next breakpoint in the same context */
183 JERRY_DEBUGGER_FINISH = 15, /**< Continue running just after the function in the current stack frame returns */
184 /* The following messages are only available in breakpoint
185 * mode and this mode is kept after the message is processed. */
186 JERRY_DEBUGGER_GET_BACKTRACE = 16, /**< get backtrace */
187 JERRY_DEBUGGER_EVAL = 17, /**< first message of evaluating a string */
188 JERRY_DEBUGGER_EVAL_PART = 18, /**< next message of evaluating a string */
189 JERRY_DEBUGGER_GET_SCOPE_CHAIN = 19, /**< get type names of the scope chain */
190 JERRY_DEBUGGER_GET_SCOPE_VARIABLES = 20, /**< get variables of a scope */
191 JERRY_DEBUGGER_MESSAGES_IN_MAX_COUNT, /**< number of different type of input messages */
192} jerry_debugger_header_type_t;
193
194/**
195 * Debugger option flags.
196 */
197typedef enum
198{
199 JERRY_DEBUGGER_LITTLE_ENDIAN = 1u << 0, /**< little endian */
200} jerry_debugger_configuration_flags_t;
201
202/**
203 * Subtypes of eval.
204 */
205typedef enum
206{
207 JERRY_DEBUGGER_EVAL_EVAL = 0, /**< evaluate expression */
208 JERRY_DEBUGGER_EVAL_THROW = 1, /**< evaluate expression and throw the result */
209 JERRY_DEBUGGER_EVAL_ABORT = 2, /**< evaluate expression and abrot with the result */
210} jerry_debugger_eval_type_t;
211
212/**
213 * Subtypes of eval_result.
214 */
215typedef enum
216{
217 JERRY_DEBUGGER_EVAL_OK = 1, /**< eval result, no error */
218 JERRY_DEBUGGER_EVAL_ERROR = 2, /**< eval result when an error has occurred */
219} jerry_debugger_eval_result_type_t;
220
221/**
222 * Subtypes of output_result.
223 *
224 * Note:
225 * This enum has to be kept in sync with jerry_log_level_t with an offset
226 * of +2.
227 */
228typedef enum
229{
230 JERRY_DEBUGGER_OUTPUT_OK = 1, /**< output result, no error */
231 JERRY_DEBUGGER_OUTPUT_ERROR = 2, /**< output result, error */
232 JERRY_DEBUGGER_OUTPUT_WARNING = 3, /**< output result, warning */
233 JERRY_DEBUGGER_OUTPUT_DEBUG = 4, /**< output result, debug */
234 JERRY_DEBUGGER_OUTPUT_TRACE = 5, /**< output result, trace */
235} jerry_debugger_output_subtype_t;
236
237/**
238 * Types of scopes.
239 */
240typedef enum
241{
242 JERRY_DEBUGGER_SCOPE_WITH = 1, /**< with */
243 JERRY_DEBUGGER_SCOPE_LOCAL = 2, /**< local */
244 JERRY_DEBUGGER_SCOPE_CLOSURE = 3, /**< closure */
245 JERRY_DEBUGGER_SCOPE_GLOBAL = 4, /**< global */
246 JERRY_DEBUGGER_SCOPE_NON_CLOSURE = 5 /**< non closure */
247} jerry_debugger_scope_chain_type_t;
248
249/**
250 * Type of scope variables.
251 */
252typedef enum
253{
254 JERRY_DEBUGGER_VALUE_NONE = 1,
255 JERRY_DEBUGGER_VALUE_UNDEFINED = 2,
256 JERRY_DEBUGGER_VALUE_NULL = 3,
257 JERRY_DEBUGGER_VALUE_BOOLEAN = 4,
258 JERRY_DEBUGGER_VALUE_NUMBER = 5,
259 JERRY_DEBUGGER_VALUE_STRING = 6,
260 JERRY_DEBUGGER_VALUE_FUNCTION = 7,
261 JERRY_DEBUGGER_VALUE_ARRAY = 8,
262 JERRY_DEBUGGER_VALUE_OBJECT = 9
263} jerry_debugger_scope_variable_type_t;
264
265/**
266 * Byte data for evaluating expressions and receiving client source.
267 */
268typedef struct
269{
270 uint32_t uint8_size; /**< total size of the client source */
271 uint32_t uint8_offset; /**< current offset in the client source */
272} jerry_debugger_uint8_data_t;
273
274/**
275 * Delayed free of byte code data.
276 */
277typedef struct
278{
279 uint16_t size; /**< size of the byte code header divided by JMEM_ALIGNMENT */
280 jmem_cpointer_t prev_cp; /**< previous byte code data to be freed */
281} jerry_debugger_byte_code_free_t;
282
283/**
284 * Outgoing message: JerryScript configuration.
285 */
286typedef struct
287{
288 uint8_t type; /**< type of the message */
289 uint8_t configuration; /**< configuration option bits */
290 uint8_t version[sizeof (uint32_t)]; /**< debugger version */
291 uint8_t max_message_size; /**< maximum incoming message size */
292 uint8_t cpointer_size; /**< size of compressed pointers */
293} jerry_debugger_send_configuration_t;
294
295/**
296 * Outgoing message: message without arguments.
297 */
298typedef struct
299{
300 uint8_t type; /**< type of the message */
301} jerry_debugger_send_type_t;
302
303/**
304 * Incoming message: message without arguments.
305 */
306typedef struct
307{
308 uint8_t type; /**< type of the message */
309} jerry_debugger_receive_type_t;
310
311/**
312 * Outgoing message: string (Source file name or function name).
313 */
314typedef struct
315{
316 uint8_t type; /**< type of the message */
317 uint8_t string[]; /**< string data */
318} jerry_debugger_send_string_t;
319
320/**
321 * Outgoing message: uint32 value.
322 */
323typedef struct
324{
325 uint8_t type; /**< type of the message */
326 uint8_t line[sizeof (uint32_t)]; /**< value data */
327 uint8_t column[sizeof (uint32_t)]; /**< value data */
328} jerry_debugger_send_parse_function_t;
329
330/**
331 * Outgoing message: byte code compressed pointer.
332 */
333typedef struct
334{
335 uint8_t type; /**< type of the message */
336 uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */
337} jerry_debugger_send_byte_code_cp_t;
338
339/**
340 * Incoming message: byte code compressed pointer.
341 */
342typedef struct
343{
344 uint8_t type; /**< type of the message */
345 uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */
346} jerry_debugger_receive_byte_code_cp_t;
347
348/**
349 * Incoming message: update (enable/disable) breakpoint status.
350 */
351typedef struct
352{
353 uint8_t type; /**< type of the message */
354 uint8_t is_set_breakpoint; /**< set or clear breakpoint */
355 uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */
356 uint8_t offset[sizeof (uint32_t)]; /**< breakpoint offset */
357} jerry_debugger_receive_update_breakpoint_t;
358
359/**
360 * Outgoing message: send memory statistics
361 */
362typedef struct
363{
364 uint8_t type; /**< type of the message */
365 uint8_t allocated_bytes[sizeof (uint32_t)]; /**< allocated bytes */
366 uint8_t byte_code_bytes[sizeof (uint32_t)]; /**< byte code bytes */
367 uint8_t string_bytes[sizeof (uint32_t)]; /**< string bytes */
368 uint8_t object_bytes[sizeof (uint32_t)]; /**< object bytes */
369 uint8_t property_bytes[sizeof (uint32_t)]; /**< property bytes */
370} jerry_debugger_send_memstats_t;
371
372/**
373 * Outgoing message: notify breakpoint hit.
374 */
375typedef struct
376{
377 uint8_t type; /**< type of the message */
378 uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */
379 uint8_t offset[sizeof (uint32_t)]; /**< breakpoint offset */
380} jerry_debugger_send_breakpoint_hit_t;
381
382/**
383 * Stack frame descriptor for sending backtrace information.
384 */
385typedef struct
386{
387 uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */
388 uint8_t offset[sizeof (uint32_t)]; /**< last breakpoint offset */
389} jerry_debugger_frame_t;
390
391/**
392 * Outgoing message: backtrace information.
393 */
394typedef struct
395{
396 uint8_t type; /**< type of the message */
397 jerry_debugger_frame_t frames[]; /**< frames */
398} jerry_debugger_send_backtrace_t;
399
400/**
401 * Outgoing message: scope chain.
402 */
403typedef struct
404{
405 uint8_t type; /**< type of the message */
406 uint8_t scope_types[]; /**< scope types */
407} jerry_debugger_send_scope_chain_t;
408
409/**
410 * Outgoing message: number of total frames in backtrace.
411 */
412typedef struct
413{
414 uint8_t type; /**< type of the message */
415 uint8_t frame_count[sizeof (uint32_t)]; /**< total number of frames */
416} jerry_debugger_send_backtrace_total_t;
417
418/**
419 * Incoming message: set behaviour when exception occures.
420 */
421typedef struct
422{
423 uint8_t type; /**< type of the message */
424 uint8_t enable; /**< non-zero: enable stop at exception */
425} jerry_debugger_receive_exception_config_t;
426
427/**
428 * Incoming message: set parser configuration.
429 */
430typedef struct
431{
432 uint8_t type; /**< type of the message */
433 uint8_t enable_wait; /**< non-zero: wait after parsing is completed */
434} jerry_debugger_receive_parser_config_t;
435
436/**
437 * Incoming message: get backtrace.
438 */
439typedef struct
440{
441 uint8_t type; /**< type of the message */
442 uint8_t min_depth[sizeof (uint32_t)]; /**< minimum depth*/
443 uint8_t max_depth[sizeof (uint32_t)]; /**< maximum depth (0 - unlimited) */
444 uint8_t get_total_frame_count; /**< non-zero: if total frame count is also requested */
445} jerry_debugger_receive_get_backtrace_t;
446
447/**
448 * Incoming message: first message of evaluating expression.
449 */
450typedef struct
451{
452 uint8_t type; /**< type of the message */
453 uint8_t eval_size[sizeof (uint32_t)]; /**< total size of the message */
454} jerry_debugger_receive_eval_first_t;
455
456/**
457 * Incoming message: get scope variables
458*/
459typedef struct
460{
461 uint8_t type; /**< type of the message */
462 uint8_t chain_index[sizeof (uint32_t)]; /**< index element of the scope */
463} jerry_debugger_receive_get_scope_variables_t;
464
465/**
466 * Incoming message: first message of client source.
467 */
468typedef struct
469{
470 uint8_t type; /**< type of the message */
471 uint8_t code_size[sizeof (uint32_t)]; /**< total size of the message */
472} jerry_debugger_receive_client_source_first_t;
473
474void jerry_debugger_free_unreferenced_byte_code (void);
475
476bool jerry_debugger_receive (jerry_debugger_uint8_data_t **message_data_p);
477
478void jerry_debugger_breakpoint_hit (uint8_t message_type);
479
480void jerry_debugger_send_type (jerry_debugger_header_type_t type);
481bool jerry_debugger_send_configuration (uint8_t max_message_size);
482void jerry_debugger_send_data (jerry_debugger_header_type_t type, const void *data, size_t size);
483bool jerry_debugger_send_string (uint8_t message_type, uint8_t sub_type, const uint8_t *string_p, size_t string_length);
484bool jerry_debugger_send_function_cp (jerry_debugger_header_type_t type, ecma_compiled_code_t *compiled_code_p);
485bool jerry_debugger_send_parse_function (uint32_t line, uint32_t column);
486void jerry_debugger_send_memstats (void);
487bool jerry_debugger_send_exception_string (ecma_value_t exception_value);
488
489#endif /* ENABLED (JERRY_DEBUGGER) */
490
491#endif /* !DEBUGGER_H */
492