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 #include "byte-code.h"
17 #include "debugger.h"
18 #include "ecma-array-object.h"
19 #include "ecma-builtin-helpers.h"
20 #include "ecma-conversion.h"
21 #include "ecma-eval.h"
22 #include "ecma-function-object.h"
23 #include "ecma-objects.h"
24 #include "jcontext.h"
25 #include "jerryscript-port.h"
26 #include "lit-char-helpers.h"
27 #if defined (__APPLE__)
28 #include <time.h>
29 #endif
30
31 #if ENABLED (JERRY_DEBUGGER)
32
33 /**
34 * Incoming message: next message of string data.
35 */
36 typedef struct
37 {
38 uint8_t type; /**< type of the message */
39 } jerry_debugger_receive_uint8_data_part_t;
40
41 /**
42 * The number of message types in the debugger should reflect the
43 * debugger versioning.
44 */
45 JERRY_STATIC_ASSERT (JERRY_DEBUGGER_MESSAGES_OUT_MAX_COUNT == 33
46 && JERRY_DEBUGGER_MESSAGES_IN_MAX_COUNT == 21
47 && JERRY_DEBUGGER_VERSION == 9,
48 debugger_version_correlates_to_message_type_count);
49
50 /**
51 * Waiting for data from the client.
52 */
53 #define JERRY_DEBUGGER_RECEIVE_DATA_MODE \
54 (JERRY_DEBUGGER_BREAKPOINT_MODE | JERRY_DEBUGGER_CLIENT_SOURCE_MODE)
55
56 /**
57 * Type cast the debugger send buffer into a specific type.
58 */
59 #define JERRY_DEBUGGER_SEND_BUFFER_AS(type, name_p) \
60 type *name_p = (type *) (JERRY_CONTEXT (debugger_send_buffer_payload_p))
61
62 /**
63 * Type cast the debugger receive buffer into a specific type.
64 */
65 #define JERRY_DEBUGGER_RECEIVE_BUFFER_AS(type, name_p) \
66 type *name_p = ((type *) recv_buffer_p)
67
68 /**
69 * Free all unreferenced byte code structures which
70 * were not acknowledged by the debugger client.
71 */
72 void
jerry_debugger_free_unreferenced_byte_code(void)73 jerry_debugger_free_unreferenced_byte_code (void)
74 {
75 jerry_debugger_byte_code_free_t *byte_code_free_p;
76
77 byte_code_free_p = JMEM_CP_GET_POINTER (jerry_debugger_byte_code_free_t,
78 JERRY_CONTEXT (debugger_byte_code_free_tail));
79
80 while (byte_code_free_p != NULL)
81 {
82 jerry_debugger_byte_code_free_t *prev_byte_code_free_p;
83 prev_byte_code_free_p = JMEM_CP_GET_POINTER (jerry_debugger_byte_code_free_t,
84 byte_code_free_p->prev_cp);
85
86 jmem_heap_free_block (byte_code_free_p,
87 ((size_t) byte_code_free_p->size) << JMEM_ALIGNMENT_LOG);
88
89 byte_code_free_p = prev_byte_code_free_p;
90 }
91 } /* jerry_debugger_free_unreferenced_byte_code */
92
93 /**
94 * Send data over an active connection.
95 *
96 * @return true - if the data was sent successfully
97 * false - otherwise
98 */
99 static bool
jerry_debugger_send(size_t message_length)100 jerry_debugger_send (size_t message_length) /**< message length in bytes */
101 {
102 #ifdef ACE_DEBUGGER_CUSTOM
103 if (!((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_TRANSPORT_STARTED))) {
104 return false; // do not send any debugger data before the hand shake done
105 }
106 #endif
107
108 JERRY_ASSERT (message_length <= JERRY_CONTEXT (debugger_max_send_size));
109
110 jerry_debugger_transport_header_t *header_p = JERRY_CONTEXT (debugger_transport_header_p);
111 uint8_t *payload_p = JERRY_CONTEXT (debugger_send_buffer_payload_p);
112
113 return header_p->send (header_p, payload_p, message_length);
114 } /* jerry_debugger_send */
115
116 /**
117 * Send backtrace.
118 */
119 static void
jerry_debugger_send_backtrace(const uint8_t * recv_buffer_p)120 jerry_debugger_send_backtrace (const uint8_t *recv_buffer_p) /**< pointer to the received data */
121 {
122 JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_get_backtrace_t, get_backtrace_p);
123
124 uint32_t min_depth;
125 memcpy (&min_depth, get_backtrace_p->min_depth, sizeof (uint32_t));
126 uint32_t max_depth;
127 memcpy (&max_depth, get_backtrace_p->max_depth, sizeof (uint32_t));
128
129 if (max_depth == 0)
130 {
131 max_depth = UINT32_MAX;
132 }
133
134 if (get_backtrace_p->get_total_frame_count != 0)
135 {
136 JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_backtrace_total_t, backtrace_total_p);
137 backtrace_total_p->type = JERRY_DEBUGGER_BACKTRACE_TOTAL;
138
139 vm_frame_ctx_t *iter_frame_ctx_p = JERRY_CONTEXT (vm_top_context_p);
140 uint32_t frame_count = 0;
141 while (iter_frame_ctx_p != NULL)
142 {
143 if (!(iter_frame_ctx_p->bytecode_header_p->status_flags & (CBC_CODE_FLAGS_STATIC_FUNCTION)))
144 {
145 frame_count++;
146 }
147 iter_frame_ctx_p = iter_frame_ctx_p->prev_context_p;
148 }
149 memcpy (backtrace_total_p->frame_count, &frame_count, sizeof (frame_count));
150
151 jerry_debugger_send (sizeof (jerry_debugger_send_type_t) + sizeof (frame_count));
152 }
153
154 JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_backtrace_t, backtrace_p);
155
156 backtrace_p->type = JERRY_DEBUGGER_BACKTRACE;
157
158 vm_frame_ctx_t *frame_ctx_p = JERRY_CONTEXT (vm_top_context_p);
159
160 size_t current_frame = 0;
161 const size_t max_frame_count = JERRY_DEBUGGER_SEND_MAX (jerry_debugger_frame_t);
162 const size_t max_message_size = JERRY_DEBUGGER_SEND_SIZE (max_frame_count, jerry_debugger_frame_t);
163
164 if (min_depth <= max_depth)
165 {
166 uint32_t min_depth_offset = 0;
167
168 while (frame_ctx_p != NULL && min_depth_offset < min_depth)
169 {
170 frame_ctx_p = frame_ctx_p->prev_context_p;
171 min_depth_offset++;
172 }
173
174 while (frame_ctx_p != NULL && min_depth_offset++ < max_depth)
175 {
176 if (frame_ctx_p->bytecode_header_p->status_flags
177 & (CBC_CODE_FLAGS_DEBUGGER_IGNORE | CBC_CODE_FLAGS_STATIC_FUNCTION))
178 {
179 frame_ctx_p = frame_ctx_p->prev_context_p;
180 continue;
181 }
182
183 if (current_frame >= max_frame_count)
184 {
185 if (!jerry_debugger_send (max_message_size))
186 {
187 return;
188 }
189 current_frame = 0;
190 }
191
192 jerry_debugger_frame_t *frame_p = backtrace_p->frames + current_frame;
193
194 jmem_cpointer_t byte_code_cp;
195 JMEM_CP_SET_NON_NULL_POINTER (byte_code_cp, frame_ctx_p->bytecode_header_p);
196 memcpy (frame_p->byte_code_cp, &byte_code_cp, sizeof (jmem_cpointer_t));
197
198 uint32_t offset = (uint32_t) (frame_ctx_p->byte_code_p - (uint8_t *) frame_ctx_p->bytecode_header_p);
199 memcpy (frame_p->offset, &offset, sizeof (uint32_t));
200
201 frame_ctx_p = frame_ctx_p->prev_context_p;
202 current_frame++;
203 }
204 }
205
206 size_t message_size = current_frame * sizeof (jerry_debugger_frame_t);
207
208 backtrace_p->type = JERRY_DEBUGGER_BACKTRACE_END;
209
210 jerry_debugger_send (sizeof (jerry_debugger_send_type_t) + message_size);
211 } /* jerry_debugger_send_backtrace */
212
213 /**
214 * Send the scope chain types.
215 */
216 static void
jerry_debugger_send_scope_chain(void)217 jerry_debugger_send_scope_chain (void)
218 {
219 vm_frame_ctx_t *iter_frame_ctx_p = JERRY_CONTEXT (vm_top_context_p);
220
221 const size_t max_byte_count = JERRY_DEBUGGER_SEND_MAX (uint8_t);
222 const size_t max_message_size = JERRY_DEBUGGER_SEND_SIZE (max_byte_count, uint8_t);
223
224 JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_string_t, message_type_p);
225 message_type_p->type = JERRY_DEBUGGER_SCOPE_CHAIN;
226
227 size_t buffer_pos = 0;
228 bool next_func_is_local = true;
229 ecma_object_t *lex_env_p = iter_frame_ctx_p->lex_env_p;
230
231 while (true)
232 {
233 JERRY_ASSERT (ecma_is_lexical_environment (lex_env_p));
234
235 if (buffer_pos == max_byte_count)
236 {
237 if (!jerry_debugger_send (max_message_size))
238 {
239 return;
240 }
241
242 buffer_pos = 0;
243 }
244
245 if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
246 {
247 if ((lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK) != 0)
248 {
249 message_type_p->string[buffer_pos++] = JERRY_DEBUGGER_SCOPE_NON_CLOSURE;
250 }
251 else if (next_func_is_local)
252 {
253 message_type_p->string[buffer_pos++] = JERRY_DEBUGGER_SCOPE_LOCAL;
254 next_func_is_local = false;
255 }
256 else
257 {
258 message_type_p->string[buffer_pos++] = JERRY_DEBUGGER_SCOPE_CLOSURE;
259 }
260 }
261 else if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND)
262 {
263 if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL)
264 {
265 message_type_p->string[buffer_pos++] = JERRY_DEBUGGER_SCOPE_GLOBAL;
266 break;
267 }
268 else
269 {
270 message_type_p->string[buffer_pos++] = JERRY_DEBUGGER_SCOPE_WITH;
271 }
272 }
273
274 JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
275 lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
276 }
277
278 message_type_p->type = JERRY_DEBUGGER_SCOPE_CHAIN_END;
279
280 jerry_debugger_send (sizeof (jerry_debugger_send_type_t) + buffer_pos);
281 } /* jerry_debugger_send_scope_chain */
282
283 /**
284 * Get type of the scope variable property.
285 * @return (jerry_debugger_scope_variable_type_t)
286 */
287 static uint8_t
jerry_debugger_get_variable_type(ecma_value_t value)288 jerry_debugger_get_variable_type (ecma_value_t value) /**< input ecma value */
289 {
290 uint8_t ret_value = JERRY_DEBUGGER_VALUE_NONE;
291
292 if (ecma_is_value_undefined (value))
293 {
294 ret_value = JERRY_DEBUGGER_VALUE_UNDEFINED;
295 }
296 else if (ecma_is_value_null (value))
297 {
298 ret_value = JERRY_DEBUGGER_VALUE_NULL;
299 }
300 else if (ecma_is_value_boolean (value))
301 {
302 ret_value = JERRY_DEBUGGER_VALUE_BOOLEAN;
303 }
304 else if (ecma_is_value_number (value))
305 {
306 ret_value = JERRY_DEBUGGER_VALUE_NUMBER;
307 }
308 else if (ecma_is_value_string (value))
309 {
310 ret_value = JERRY_DEBUGGER_VALUE_STRING;
311 }
312 else
313 {
314 JERRY_ASSERT (ecma_is_value_object (value));
315
316 if (ecma_get_object_type (ecma_get_object_from_value (value)) == ECMA_OBJECT_TYPE_ARRAY)
317 {
318 ret_value = JERRY_DEBUGGER_VALUE_ARRAY;
319 }
320 else
321 {
322 ret_value = ecma_op_is_callable (value) ? JERRY_DEBUGGER_VALUE_FUNCTION : JERRY_DEBUGGER_VALUE_OBJECT;
323 }
324 }
325
326 JERRY_ASSERT (ret_value != JERRY_DEBUGGER_VALUE_NONE);
327
328 return ret_value;
329 } /* jerry_debugger_get_variable_type */
330
331 /**
332 * Helper function for jerry_debugger_send_scope_variables.
333 *
334 * It will copies the given scope values type, length and value into the outgoing message string.
335 *
336 * @param variable_type type (jerry_debugger_scope_variable_type_t)
337 * @return true - if the copy was successfully
338 * false - otherwise
339 */
340 static bool
jerry_debugger_copy_variables_to_string_message(uint8_t variable_type,ecma_string_t * value_str,jerry_debugger_send_string_t * message_string_p,size_t * buffer_pos)341 jerry_debugger_copy_variables_to_string_message (uint8_t variable_type, /**< type */
342 ecma_string_t *value_str, /**< property name or value string */
343 jerry_debugger_send_string_t *message_string_p, /**< msg pointer */
344 size_t *buffer_pos) /**< string data position of the message */
345 {
346 const size_t max_byte_count = JERRY_DEBUGGER_SEND_MAX (uint8_t);
347 const size_t max_message_size = JERRY_DEBUGGER_SEND_SIZE (max_byte_count, uint8_t);
348
349 ECMA_STRING_TO_UTF8_STRING (value_str, str_buff, str_buff_size);
350
351 size_t str_size = 0;
352 size_t str_limit = 255;
353 bool result = true;
354
355 bool type_processed = false;
356
357 while (true)
358 {
359 if (*buffer_pos == max_byte_count)
360 {
361 if (!jerry_debugger_send (max_message_size))
362 {
363 result = false;
364 break;
365 }
366
367 *buffer_pos = 0;
368 }
369
370 if (!type_processed)
371 {
372 if (variable_type != JERRY_DEBUGGER_VALUE_NONE)
373 {
374 message_string_p->string[*buffer_pos] = variable_type;
375 *buffer_pos += 1;
376 }
377 type_processed = true;
378 continue;
379 }
380
381 if (variable_type == JERRY_DEBUGGER_VALUE_FUNCTION)
382 {
383 str_size = 0; // do not copy function values
384 }
385 else
386 {
387 str_size = (str_buff_size > str_limit) ? str_limit : str_buff_size;
388 }
389
390 message_string_p->string[*buffer_pos] = (uint8_t) str_size;
391 *buffer_pos += 1;
392 break;
393 }
394
395 if (result)
396 {
397 size_t free_bytes = max_byte_count - *buffer_pos;
398 const uint8_t *string_p = str_buff;
399
400 while (str_size > free_bytes)
401 {
402 memcpy (message_string_p->string + *buffer_pos, string_p, free_bytes);
403
404 if (!jerry_debugger_send (max_message_size))
405 {
406 result = false;
407 break;
408 }
409
410 string_p += free_bytes;
411 str_size -= free_bytes;
412 free_bytes = max_byte_count;
413 *buffer_pos = 0;
414 }
415
416 if (result)
417 {
418 memcpy (message_string_p->string + *buffer_pos, string_p, str_size);
419 *buffer_pos += str_size;
420 }
421 }
422
423 ECMA_FINALIZE_UTF8_STRING (str_buff, str_buff_size);
424
425 return result;
426 } /* jerry_debugger_copy_variables_to_string_message */
427
428 /**
429 * Send variables of the given scope chain level.
430 */
431 static void
jerry_debugger_send_scope_variables(const uint8_t * recv_buffer_p)432 jerry_debugger_send_scope_variables (const uint8_t *recv_buffer_p) /**< pointer to the received data */
433 {
434 JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_get_scope_variables_t, get_scope_variables_p);
435
436 uint32_t chain_index;
437 memcpy (&chain_index, get_scope_variables_p->chain_index, sizeof (uint32_t));
438
439 vm_frame_ctx_t *iter_frame_ctx_p = JERRY_CONTEXT (vm_top_context_p);
440 ecma_object_t *lex_env_p = iter_frame_ctx_p->lex_env_p;
441
442 while (chain_index != 0)
443 {
444 if (JERRY_UNLIKELY (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL))
445 {
446 jerry_debugger_send_type (JERRY_DEBUGGER_SCOPE_VARIABLES_END);
447 return;
448 }
449
450 lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
451
452 if ((ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND)
453 || (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE))
454 {
455 chain_index--;
456 }
457 }
458
459 jmem_cpointer_t prop_iter_cp;
460
461 if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
462 {
463 prop_iter_cp = lex_env_p->u1.property_list_cp;
464 }
465 else
466 {
467 JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
468 ecma_object_t *binding_obj_p = ecma_get_lex_env_binding_object (lex_env_p);
469
470 if (JERRY_UNLIKELY (ecma_op_object_is_fast_array (binding_obj_p)))
471 {
472 ecma_fast_array_convert_to_normal (binding_obj_p);
473 }
474
475 prop_iter_cp = binding_obj_p->u1.property_list_cp;
476 }
477
478 JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_string_t, message_string_p);
479 message_string_p->type = JERRY_DEBUGGER_SCOPE_VARIABLES;
480
481 size_t buffer_pos = 0;
482
483 while (prop_iter_cp != JMEM_CP_NULL)
484 {
485 ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp);
486 JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));
487
488 ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p;
489
490 for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
491 {
492 if (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[i]))
493 {
494 if (ECMA_PROPERTY_GET_NAME_TYPE (prop_iter_p->types[i]) == ECMA_DIRECT_STRING_MAGIC
495 && prop_pair_p->names_cp[i] >= LIT_NON_INTERNAL_MAGIC_STRING__COUNT)
496 {
497 continue;
498 }
499
500 ecma_string_t *prop_name = ecma_string_from_property_name (prop_iter_p->types[i],
501 prop_pair_p->names_cp[i]);
502
503 if (!jerry_debugger_copy_variables_to_string_message (JERRY_DEBUGGER_VALUE_NONE,
504 prop_name,
505 message_string_p,
506 &buffer_pos))
507 {
508 ecma_deref_ecma_string (prop_name);
509 return;
510 }
511
512 ecma_deref_ecma_string (prop_name);
513
514 ecma_property_value_t prop_value_p = prop_pair_p->values[i];
515
516 uint8_t variable_type = jerry_debugger_get_variable_type (prop_value_p.value);
517
518 ecma_string_t *str_p = ecma_op_to_string (prop_value_p.value);
519 JERRY_ASSERT (str_p != NULL);
520
521 if (!jerry_debugger_copy_variables_to_string_message (variable_type,
522 str_p,
523 message_string_p,
524 &buffer_pos))
525 {
526 ecma_deref_ecma_string (str_p);
527 return;
528 }
529
530 ecma_deref_ecma_string (str_p);
531 }
532 }
533
534 prop_iter_cp = prop_iter_p->next_property_cp;
535 }
536
537 message_string_p->type = JERRY_DEBUGGER_SCOPE_VARIABLES_END;
538 jerry_debugger_send (sizeof (jerry_debugger_send_type_t) + buffer_pos);
539 } /* jerry_debugger_send_scope_variables */
540
541 /**
542 * Send result of evaluated expression or throw an error.
543 *
544 * @return true - if execution should be resumed
545 * false - otherwise
546 */
547 static bool
jerry_debugger_send_eval(const lit_utf8_byte_t * eval_string_p,size_t eval_string_size)548 jerry_debugger_send_eval (const lit_utf8_byte_t *eval_string_p, /**< evaluated string */
549 size_t eval_string_size) /**< evaluated string size */
550 {
551 JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
552 JERRY_ASSERT (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_VM_IGNORE));
553
554 JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_IGNORE);
555
556 uint32_t chain_index;
557 memcpy (&chain_index, eval_string_p, sizeof (uint32_t));
558 uint32_t parse_opts = ECMA_PARSE_DIRECT_EVAL | (chain_index << ECMA_PARSE_CHAIN_INDEX_SHIFT);
559
560 ecma_value_t result = ecma_op_eval_chars_buffer (eval_string_p + 5, eval_string_size - 5, parse_opts);
561
562 if (!ECMA_IS_VALUE_ERROR (result))
563 {
564 if (eval_string_p[4] != JERRY_DEBUGGER_EVAL_EVAL)
565 {
566 JERRY_ASSERT (eval_string_p[4] == JERRY_DEBUGGER_EVAL_THROW || eval_string_p[4] == JERRY_DEBUGGER_EVAL_ABORT);
567 JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_EXCEPTION_THROWN);
568
569 /* Stop where the error is caught. */
570 JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP);
571 JERRY_CONTEXT (debugger_stop_context) = NULL;
572
573 jcontext_raise_exception (result);
574 jcontext_set_abort_flag (eval_string_p[4] == JERRY_DEBUGGER_EVAL_ABORT);
575
576 JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_IGNORE);
577 return true;
578 }
579
580 if (!ecma_is_value_string (result))
581 {
582 ecma_string_t *str_p = ecma_op_to_string (result);
583 ecma_value_t to_string_value = ecma_make_string_value (str_p);
584 ecma_free_value (result);
585 result = to_string_value;
586 }
587 }
588
589 ecma_value_t message = result;
590 uint8_t type = JERRY_DEBUGGER_EVAL_OK;
591
592 if (ECMA_IS_VALUE_ERROR (result))
593 {
594 type = JERRY_DEBUGGER_EVAL_ERROR;
595 result = JERRY_CONTEXT (error_value);
596
597 if (ecma_is_value_object (result))
598 {
599 message = ecma_op_object_find (ecma_get_object_from_value (result),
600 ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE));
601
602 if (!ecma_is_value_string (message)
603 || ecma_string_is_empty (ecma_get_string_from_value (message)))
604 {
605 ecma_free_value (message);
606 lit_magic_string_id_t id = ecma_object_get_class_name (ecma_get_object_from_value (result));
607 ecma_free_value (result);
608
609 const lit_utf8_byte_t *string_p = lit_get_magic_string_utf8 (id);
610 jerry_debugger_send_string (JERRY_DEBUGGER_EVAL_RESULT,
611 type,
612 string_p,
613 strlen ((const char *) string_p));
614 JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_IGNORE);
615 return false;
616 }
617 }
618 else
619 {
620 /* Primitive type. */
621 ecma_string_t *str_p = ecma_op_to_string (result);
622 JERRY_ASSERT (str_p != NULL);
623
624 message = ecma_make_string_value (str_p);
625 }
626
627 ecma_free_value (result);
628 }
629
630 ecma_string_t *string_p = ecma_get_string_from_value (message);
631
632 ECMA_STRING_TO_UTF8_STRING (string_p, buffer_p, buffer_size);
633 jerry_debugger_send_string (JERRY_DEBUGGER_EVAL_RESULT, type, buffer_p, buffer_size);
634 ECMA_FINALIZE_UTF8_STRING (buffer_p, buffer_size);
635
636 ecma_free_value (message);
637
638 JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_IGNORE);
639 return false;
640 } /* jerry_debugger_send_eval */
641
642 /**
643 * Check received packet size.
644 */
645 #define JERRY_DEBUGGER_CHECK_PACKET_SIZE(type) \
646 if (message_size != sizeof (type)) \
647 { \
648 JERRY_ERROR_MSG ("Invalid message size\n"); \
649 jerry_debugger_transport_close (); \
650 return false; \
651 }
652
653 #ifdef ACE_DEBUGGER_CUSTOM
654 #define ENUM_TYPE_TO_STRING_CASE(x) case x: return(#x);
jerry_debugger_package_type_string(jerry_debugger_header_type_t type)655 static inline const char *jerry_debugger_package_type_string(jerry_debugger_header_type_t type)
656 {
657 switch (type)
658 {
659 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_FREE_BYTE_CODE_CP)
660 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_UPDATE_BREAKPOINT)
661 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_EXCEPTION_CONFIG)
662 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_PARSER_CONFIG)
663 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_MEMSTATS)
664 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_STOP)
665 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_PARSER_RESUME)
666 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_CLIENT_SOURCE)
667 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_CLIENT_SOURCE_PART)
668 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_NO_MORE_SOURCES)
669 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_CONTEXT_RESET)
670 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_CONTINUE)
671 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_STEP)
672 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_NEXT)
673 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_FINISH)
674 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_GET_BACKTRACE)
675 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_EVAL)
676 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_EVAL_PART)
677 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_GET_SCOPE_CHAIN)
678 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_GET_SCOPE_VARIABLES)
679 ENUM_TYPE_TO_STRING_CASE(JERRY_DEBUGGER_MESSAGES_IN_MAX_COUNT)
680 default:
681 return "Unsupported jerry_debugger request from client";
682 }
683 return "Unsupported jerry_debugger request from client";
684 }
685 #endif
686
687 /**
688 * Receive message from the client.
689 *
690 * @return true - if message is processed successfully
691 * false - otherwise
692 */
693 static inline bool JERRY_ATTR_ALWAYS_INLINE
jerry_debugger_process_message(const uint8_t * recv_buffer_p,uint32_t message_size,bool * resume_exec_p,uint8_t * expected_message_type_p,jerry_debugger_uint8_data_t ** message_data_p)694 jerry_debugger_process_message (const uint8_t *recv_buffer_p, /**< pointer to the received data */
695 uint32_t message_size, /**< message size */
696 bool *resume_exec_p, /**< pointer to the resume exec flag */
697 uint8_t *expected_message_type_p, /**< message type */
698 jerry_debugger_uint8_data_t **message_data_p) /**< custom message data */
699 {
700 /* Process the received message. */
701
702 if (recv_buffer_p[0] >= JERRY_DEBUGGER_CONTINUE
703 && !(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_BREAKPOINT_MODE))
704 {
705 JERRY_ERROR_MSG ("Message requires breakpoint mode\n");
706 jerry_debugger_transport_close ();
707 return false;
708 }
709
710 #ifdef ACE_DEBUGGER_CUSTOM
711 JERRY_DEBUG_MSG("debugger server: received [%s] from client\n", jerry_debugger_package_type_string(recv_buffer_p[0]));
712 #endif
713
714 if (*expected_message_type_p != 0)
715 {
716 JERRY_ASSERT (*expected_message_type_p == JERRY_DEBUGGER_EVAL_PART
717 || *expected_message_type_p == JERRY_DEBUGGER_CLIENT_SOURCE_PART);
718
719 jerry_debugger_uint8_data_t *uint8_data_p = (jerry_debugger_uint8_data_t *) *message_data_p;
720
721 if (recv_buffer_p[0] != *expected_message_type_p)
722 {
723 jmem_heap_free_block (uint8_data_p, uint8_data_p->uint8_size + sizeof (jerry_debugger_uint8_data_t));
724 JERRY_ERROR_MSG ("Unexpected message\n");
725 jerry_debugger_transport_close ();
726 return false;
727 }
728
729 JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_uint8_data_part_t, uint8_data_part_p);
730
731 if (message_size < sizeof (jerry_debugger_receive_uint8_data_part_t) + 1)
732 {
733 jmem_heap_free_block (uint8_data_p, uint8_data_p->uint8_size + sizeof (jerry_debugger_uint8_data_t));
734 JERRY_ERROR_MSG ("Invalid message size\n");
735 jerry_debugger_transport_close ();
736 return false;
737 }
738
739 uint32_t expected_data = uint8_data_p->uint8_size - uint8_data_p->uint8_offset;
740
741 message_size -= (uint32_t) sizeof (jerry_debugger_receive_uint8_data_part_t);
742
743 if (message_size > expected_data)
744 {
745 jmem_heap_free_block (uint8_data_p, uint8_data_p->uint8_size + sizeof (jerry_debugger_uint8_data_t));
746 JERRY_ERROR_MSG ("Invalid message size\n");
747 jerry_debugger_transport_close ();
748 return false;
749 }
750
751 lit_utf8_byte_t *string_p = (lit_utf8_byte_t *) (uint8_data_p + 1);
752 memcpy (string_p + uint8_data_p->uint8_offset,
753 (lit_utf8_byte_t *) (uint8_data_part_p + 1),
754 message_size);
755
756 if (message_size < expected_data)
757 {
758 uint8_data_p->uint8_offset += message_size;
759 return true;
760 }
761
762 bool result;
763
764 if (*expected_message_type_p == JERRY_DEBUGGER_EVAL_PART)
765 {
766 if (jerry_debugger_send_eval (string_p, uint8_data_p->uint8_size))
767 {
768 *resume_exec_p = true;
769 }
770 result = (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) != 0;
771 }
772 else
773 {
774 result = true;
775 JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_CLIENT_SOURCE_MODE);
776 *resume_exec_p = true;
777 }
778
779 *expected_message_type_p = 0;
780 return result;
781 }
782
783 switch (recv_buffer_p[0])
784 {
785 case JERRY_DEBUGGER_FREE_BYTE_CODE_CP:
786 {
787 JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_byte_code_cp_t);
788
789 JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_byte_code_cp_t, byte_code_p);
790
791 jmem_cpointer_t byte_code_free_cp;
792 memcpy (&byte_code_free_cp, byte_code_p->byte_code_cp, sizeof (jmem_cpointer_t));
793
794 if (byte_code_free_cp != JERRY_CONTEXT (debugger_byte_code_free_tail))
795 {
796 JERRY_ERROR_MSG ("Invalid byte code free order\n");
797 jerry_debugger_transport_close ();
798 return false;
799 }
800
801 jerry_debugger_byte_code_free_t *byte_code_free_p;
802 byte_code_free_p = JMEM_CP_GET_NON_NULL_POINTER (jerry_debugger_byte_code_free_t,
803 byte_code_free_cp);
804
805 if (byte_code_free_p->prev_cp != ECMA_NULL_POINTER)
806 {
807 JERRY_CONTEXT (debugger_byte_code_free_tail) = byte_code_free_p->prev_cp;
808 }
809 else
810 {
811 JERRY_CONTEXT (debugger_byte_code_free_head) = ECMA_NULL_POINTER;
812 JERRY_CONTEXT (debugger_byte_code_free_tail) = ECMA_NULL_POINTER;
813 }
814
815 #if ENABLED (JERRY_MEM_STATS)
816 jmem_stats_free_byte_code_bytes (((size_t) byte_code_free_p->size) << JMEM_ALIGNMENT_LOG);
817 #endif /* ENABLED (JERRY_MEM_STATS) */
818
819 jmem_heap_free_block (byte_code_free_p,
820 ((size_t) byte_code_free_p->size) << JMEM_ALIGNMENT_LOG);
821 return true;
822 }
823
824 case JERRY_DEBUGGER_UPDATE_BREAKPOINT:
825 {
826 JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_update_breakpoint_t);
827
828 JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_update_breakpoint_t, update_breakpoint_p);
829
830 jmem_cpointer_t byte_code_cp;
831 memcpy (&byte_code_cp, update_breakpoint_p->byte_code_cp, sizeof (jmem_cpointer_t));
832 uint8_t *byte_code_p = JMEM_CP_GET_NON_NULL_POINTER (uint8_t, byte_code_cp);
833
834 uint32_t offset;
835 memcpy (&offset, update_breakpoint_p->offset, sizeof (uint32_t));
836 byte_code_p += offset;
837
838 JERRY_ASSERT (*byte_code_p == CBC_BREAKPOINT_ENABLED || *byte_code_p == CBC_BREAKPOINT_DISABLED);
839
840 *byte_code_p = update_breakpoint_p->is_set_breakpoint ? CBC_BREAKPOINT_ENABLED : CBC_BREAKPOINT_DISABLED;
841 return true;
842 }
843
844 case JERRY_DEBUGGER_MEMSTATS:
845 {
846 JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t);
847
848 jerry_debugger_send_memstats ();
849 return true;
850 }
851
852 case JERRY_DEBUGGER_STOP:
853 {
854 JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t);
855
856 JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP);
857 JERRY_CONTEXT (debugger_stop_context) = NULL;
858 *resume_exec_p = false;
859 return true;
860 }
861
862 case JERRY_DEBUGGER_CONTINUE:
863 {
864 JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t);
865
866 JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_STOP);
867 JERRY_CONTEXT (debugger_stop_context) = NULL;
868 *resume_exec_p = true;
869 return true;
870 }
871
872 case JERRY_DEBUGGER_STEP:
873 {
874 JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t);
875
876 JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP);
877 JERRY_CONTEXT (debugger_stop_context) = NULL;
878 *resume_exec_p = true;
879 return true;
880 }
881
882 case JERRY_DEBUGGER_NEXT:
883 {
884 JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t);
885
886 JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP);
887 JERRY_CONTEXT (debugger_stop_context) = JERRY_CONTEXT (vm_top_context_p);
888 *resume_exec_p = true;
889 return true;
890 }
891
892 case JERRY_DEBUGGER_FINISH:
893 {
894 JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t);
895
896 JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP);
897
898 /* This will point to the current context's parent (where the function was called)
899 * and in case of NULL the result will the same as in case of STEP. */
900 JERRY_CONTEXT (debugger_stop_context) = JERRY_CONTEXT (vm_top_context_p->prev_context_p);
901 *resume_exec_p = true;
902 return true;
903 }
904
905 case JERRY_DEBUGGER_GET_BACKTRACE:
906 {
907 JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_get_backtrace_t);
908
909 jerry_debugger_send_backtrace (recv_buffer_p);
910 return true;
911 }
912
913 case JERRY_DEBUGGER_GET_SCOPE_CHAIN:
914 {
915 JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t);
916
917 jerry_debugger_send_scope_chain ();
918
919 return true;
920 }
921
922 case JERRY_DEBUGGER_GET_SCOPE_VARIABLES:
923 {
924 JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_get_scope_variables_t);
925
926 jerry_debugger_send_scope_variables (recv_buffer_p);
927
928 return true;
929 }
930
931 case JERRY_DEBUGGER_EXCEPTION_CONFIG:
932 {
933 JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_exception_config_t);
934 JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_exception_config_t, exception_config_p);
935
936 if (exception_config_p->enable == 0)
937 {
938 JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_IGNORE_EXCEPTION);
939 JERRY_DEBUG_MSG ("Stop at exception disabled\n");
940 }
941 else
942 {
943 JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_IGNORE_EXCEPTION);
944 JERRY_DEBUG_MSG ("Stop at exception enabled\n");
945 }
946
947 return true;
948 }
949
950 case JERRY_DEBUGGER_PARSER_CONFIG:
951 {
952 JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_parser_config_t);
953 JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_parser_config_t, parser_config_p);
954
955 if (parser_config_p->enable_wait != 0)
956 {
957 JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_PARSER_WAIT);
958 JERRY_DEBUG_MSG ("Waiting after parsing enabled\n");
959 }
960 else
961 {
962 JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_PARSER_WAIT);
963 JERRY_DEBUG_MSG ("Waiting after parsing disabled\n");
964 }
965
966 return true;
967 }
968
969 case JERRY_DEBUGGER_PARSER_RESUME:
970 {
971 JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t);
972
973 if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_PARSER_WAIT_MODE))
974 {
975 JERRY_ERROR_MSG ("Not in parser wait mode\n");
976 jerry_debugger_transport_close ();
977 return false;
978 }
979
980 JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_PARSER_WAIT_MODE);
981 return true;
982 }
983
984 case JERRY_DEBUGGER_EVAL:
985 {
986 if (message_size < sizeof (jerry_debugger_receive_eval_first_t) + 5)
987 {
988 JERRY_ERROR_MSG ("Invalid message size\n");
989 jerry_debugger_transport_close ();
990 return false;
991 }
992
993 JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_eval_first_t, eval_first_p);
994
995 uint32_t eval_size;
996 memcpy (&eval_size, eval_first_p->eval_size, sizeof (uint32_t));
997
998 if (eval_size <= JERRY_CONTEXT (debugger_max_receive_size) - sizeof (jerry_debugger_receive_eval_first_t))
999 {
1000 if (eval_size != message_size - sizeof (jerry_debugger_receive_eval_first_t))
1001 {
1002 JERRY_ERROR_MSG ("Invalid message size\n");
1003 jerry_debugger_transport_close ();
1004 return false;
1005 }
1006
1007 if (jerry_debugger_send_eval ((lit_utf8_byte_t *) (eval_first_p + 1), eval_size))
1008 {
1009 *resume_exec_p = true;
1010 }
1011
1012 return (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) != 0;
1013 }
1014
1015 jerry_debugger_uint8_data_t *eval_uint8_data_p;
1016 size_t eval_data_size = sizeof (jerry_debugger_uint8_data_t) + eval_size;
1017
1018 eval_uint8_data_p = (jerry_debugger_uint8_data_t *) jmem_heap_alloc_block (eval_data_size);
1019
1020 eval_uint8_data_p->uint8_size = eval_size;
1021 eval_uint8_data_p->uint8_offset = (uint32_t) (message_size - sizeof (jerry_debugger_receive_eval_first_t));
1022
1023 lit_utf8_byte_t *eval_string_p = (lit_utf8_byte_t *) (eval_uint8_data_p + 1);
1024 memcpy (eval_string_p,
1025 (lit_utf8_byte_t *) (eval_first_p + 1),
1026 message_size - sizeof (jerry_debugger_receive_eval_first_t));
1027
1028 *message_data_p = eval_uint8_data_p;
1029 *expected_message_type_p = JERRY_DEBUGGER_EVAL_PART;
1030
1031 return true;
1032 }
1033
1034 case JERRY_DEBUGGER_CLIENT_SOURCE:
1035 {
1036 if (message_size <= sizeof (jerry_debugger_receive_client_source_first_t))
1037 {
1038 JERRY_ERROR_MSG ("Invalid message size\n");
1039 jerry_debugger_transport_close ();
1040 return false;
1041 }
1042
1043 if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CLIENT_SOURCE_MODE))
1044 {
1045 JERRY_ERROR_MSG ("Not in client source mode\n");
1046 jerry_debugger_transport_close ();
1047 return false;
1048 }
1049
1050 JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_client_source_first_t, client_source_first_p);
1051
1052 uint32_t client_source_size;
1053 memcpy (&client_source_size, client_source_first_p->code_size, sizeof (uint32_t));
1054
1055 uint32_t header_size = sizeof (jerry_debugger_receive_client_source_first_t);
1056
1057 if (client_source_size <= JERRY_CONTEXT (debugger_max_receive_size) - header_size
1058 && client_source_size != message_size - header_size)
1059 {
1060 JERRY_ERROR_MSG ("Invalid message size\n");
1061 jerry_debugger_transport_close ();
1062 return false;
1063 }
1064
1065 jerry_debugger_uint8_data_t *client_source_data_p;
1066 size_t client_source_data_size = sizeof (jerry_debugger_uint8_data_t) + client_source_size;
1067
1068 client_source_data_p = (jerry_debugger_uint8_data_t *) jmem_heap_alloc_block (client_source_data_size);
1069
1070 client_source_data_p->uint8_size = client_source_size;
1071 client_source_data_p->uint8_offset = (uint32_t) (message_size
1072 - sizeof (jerry_debugger_receive_client_source_first_t));
1073
1074 lit_utf8_byte_t *client_source_string_p = (lit_utf8_byte_t *) (client_source_data_p + 1);
1075 memcpy (client_source_string_p,
1076 (lit_utf8_byte_t *) (client_source_first_p + 1),
1077 message_size - sizeof (jerry_debugger_receive_client_source_first_t));
1078
1079 *message_data_p = client_source_data_p;
1080
1081 if (client_source_data_p->uint8_size != client_source_data_p->uint8_offset)
1082 {
1083 *expected_message_type_p = JERRY_DEBUGGER_CLIENT_SOURCE_PART;
1084 }
1085 else
1086 {
1087 JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_CLIENT_SOURCE_MODE);
1088 *resume_exec_p = true;
1089 }
1090 return true;
1091 }
1092
1093 case JERRY_DEBUGGER_NO_MORE_SOURCES:
1094 {
1095 if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CLIENT_SOURCE_MODE))
1096 {
1097 JERRY_ERROR_MSG ("Not in client source mode\n");
1098 jerry_debugger_transport_close ();
1099 return false;
1100 }
1101
1102 JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t);
1103
1104 JERRY_DEBUGGER_UPDATE_FLAGS (JERRY_DEBUGGER_CLIENT_NO_SOURCE, JERRY_DEBUGGER_CLIENT_SOURCE_MODE);
1105
1106 *resume_exec_p = true;
1107
1108 return true;
1109 }
1110
1111 case JERRY_DEBUGGER_CONTEXT_RESET:
1112 {
1113 if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CLIENT_SOURCE_MODE))
1114 {
1115 JERRY_ERROR_MSG ("Not in client source mode\n");
1116 jerry_debugger_transport_close ();
1117 return false;
1118 }
1119
1120 JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t);
1121
1122 JERRY_DEBUGGER_UPDATE_FLAGS (JERRY_DEBUGGER_CONTEXT_RESET_MODE, JERRY_DEBUGGER_CLIENT_SOURCE_MODE);
1123
1124 *resume_exec_p = true;
1125
1126 return true;
1127 }
1128
1129 default:
1130 {
1131 JERRY_ERROR_MSG ("Unexpected message.");
1132 jerry_debugger_transport_close ();
1133 return false;
1134 }
1135 }
1136 } /* jerry_debugger_process_message */
1137
1138 /**
1139 * Receive message from the client.
1140 *
1141 * Note:
1142 * If the function returns with true, the value of
1143 * JERRY_DEBUGGER_VM_STOP flag should be ignored.
1144 *
1145 * @return true - if execution should be resumed,
1146 * false - otherwise
1147 */
1148 bool
jerry_debugger_receive(jerry_debugger_uint8_data_t ** message_data_p)1149 jerry_debugger_receive (jerry_debugger_uint8_data_t **message_data_p) /**< [out] data received from client */
1150 {
1151 JERRY_ASSERT (jerry_debugger_transport_is_connected ());
1152
1153 JERRY_ASSERT (message_data_p != NULL ? !!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_RECEIVE_DATA_MODE)
1154 : !(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_RECEIVE_DATA_MODE));
1155
1156 JERRY_CONTEXT (debugger_message_delay) = JERRY_DEBUGGER_MESSAGE_FREQUENCY;
1157
1158 bool resume_exec = false;
1159 uint8_t expected_message_type = 0;
1160
1161 while (true)
1162 {
1163 #if defined (__APPLE__)
1164 // wait at here for 0.5ms
1165 usleep(500);
1166 #endif /* __APPLE__ */
1167
1168 jerry_debugger_transport_receive_context_t context;
1169 if (!jerry_debugger_transport_receive (&context))
1170 {
1171 JERRY_ASSERT (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED));
1172 return true;
1173 }
1174
1175 if (context.message_p == NULL)
1176 {
1177 JERRY_CONTEXT (debugger_received_length) = (uint16_t) context.received_length;
1178
1179 if (expected_message_type != 0)
1180 {
1181 jerry_debugger_transport_sleep ();
1182 continue;
1183 }
1184
1185 return resume_exec;
1186 }
1187
1188 /* Only datagram packets are supported. */
1189 JERRY_ASSERT (context.message_total_length > 0);
1190
1191 /* The jerry_debugger_process_message function is inlined
1192 * so passing these arguments is essentially free. */
1193 if (!jerry_debugger_process_message (context.message_p,
1194 (uint32_t) context.message_length,
1195 &resume_exec,
1196 &expected_message_type,
1197 message_data_p))
1198 {
1199 JERRY_ASSERT (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED));
1200 return true;
1201 }
1202
1203 jerry_debugger_transport_receive_completed (&context);
1204 }
1205 } /* jerry_debugger_receive */
1206
1207 #undef JERRY_DEBUGGER_CHECK_PACKET_SIZE
1208
1209 /**
1210 * Tell the client that a breakpoint has been hit and wait for further debugger commands.
1211 */
1212 void
jerry_debugger_breakpoint_hit(uint8_t message_type)1213 jerry_debugger_breakpoint_hit (uint8_t message_type) /**< message type */
1214 {
1215 JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
1216
1217 JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_breakpoint_hit_t, breakpoint_hit_p);
1218
1219 breakpoint_hit_p->type = message_type;
1220
1221 vm_frame_ctx_t *frame_ctx_p = JERRY_CONTEXT (vm_top_context_p);
1222
1223 jmem_cpointer_t byte_code_header_cp;
1224 JMEM_CP_SET_NON_NULL_POINTER (byte_code_header_cp, frame_ctx_p->bytecode_header_p);
1225 memcpy (breakpoint_hit_p->byte_code_cp, &byte_code_header_cp, sizeof (jmem_cpointer_t));
1226
1227 uint32_t offset = (uint32_t) (frame_ctx_p->byte_code_p - (uint8_t *) frame_ctx_p->bytecode_header_p);
1228 memcpy (breakpoint_hit_p->offset, &offset, sizeof (uint32_t));
1229
1230 if (!jerry_debugger_send (sizeof (jerry_debugger_send_breakpoint_hit_t)))
1231 {
1232 return;
1233 }
1234
1235 JERRY_DEBUGGER_UPDATE_FLAGS (JERRY_DEBUGGER_BREAKPOINT_MODE, JERRY_DEBUGGER_VM_EXCEPTION_THROWN);
1236
1237 jerry_debugger_uint8_data_t *uint8_data = NULL;
1238
1239 while (!jerry_debugger_receive (&uint8_data))
1240 {
1241 jerry_debugger_transport_sleep ();
1242 }
1243
1244 if (uint8_data != NULL)
1245 {
1246 jmem_heap_free_block (uint8_data,
1247 uint8_data->uint8_size + sizeof (jerry_debugger_uint8_data_t));
1248 }
1249
1250 JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_BREAKPOINT_MODE);
1251
1252 JERRY_CONTEXT (debugger_message_delay) = JERRY_DEBUGGER_MESSAGE_FREQUENCY;
1253 } /* jerry_debugger_breakpoint_hit */
1254
1255 /**
1256 * Send the type signal to the client.
1257 */
1258 void
jerry_debugger_send_type(jerry_debugger_header_type_t type)1259 jerry_debugger_send_type (jerry_debugger_header_type_t type) /**< message type */
1260 {
1261 JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
1262
1263 JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_type_t, message_type_p);
1264
1265 message_type_p->type = (uint8_t) type;
1266
1267 jerry_debugger_send (sizeof (jerry_debugger_send_type_t));
1268 } /* jerry_debugger_send_type */
1269
1270 /**
1271 * Send the type signal to the client.
1272 *
1273 * @return true - if the data sent successfully to the debugger client,
1274 * false - otherwise
1275 */
1276 bool
jerry_debugger_send_configuration(uint8_t max_message_size)1277 jerry_debugger_send_configuration (uint8_t max_message_size) /**< maximum message size */
1278 {
1279 JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_configuration_t, configuration_p);
1280
1281 /* Helper structure for endianness check. */
1282 union
1283 {
1284 uint16_t uint16_value; /**< a 16-bit value */
1285 uint8_t uint8_value[2]; /**< lower and upper byte of a 16-bit value */
1286 } endian_data;
1287
1288 endian_data.uint16_value = 1;
1289
1290 configuration_p->type = JERRY_DEBUGGER_CONFIGURATION;
1291 configuration_p->configuration = 0;
1292
1293 if (endian_data.uint8_value[0] == 1)
1294 {
1295 configuration_p->configuration |= (uint8_t) JERRY_DEBUGGER_LITTLE_ENDIAN;
1296 }
1297
1298 uint32_t version = JERRY_DEBUGGER_VERSION;
1299 memcpy (configuration_p->version, &version, sizeof (uint32_t));
1300
1301 configuration_p->max_message_size = max_message_size;
1302 configuration_p->cpointer_size = sizeof (jmem_cpointer_t);
1303
1304 return jerry_debugger_send (sizeof (jerry_debugger_send_configuration_t));
1305 } /* jerry_debugger_send_configuration */
1306
1307 /**
1308 * Send raw data to the debugger client.
1309 */
1310 void
jerry_debugger_send_data(jerry_debugger_header_type_t type,const void * data,size_t size)1311 jerry_debugger_send_data (jerry_debugger_header_type_t type, /**< message type */
1312 const void *data, /**< raw data */
1313 size_t size) /**< size of data */
1314 {
1315 JERRY_ASSERT (size <= JERRY_DEBUGGER_SEND_MAX (uint8_t));
1316
1317 JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_type_t, message_type_p);
1318
1319 message_type_p->type = (uint8_t) type;
1320 memcpy (message_type_p + 1, data, size);
1321
1322 jerry_debugger_send (sizeof (jerry_debugger_send_type_t) + size);
1323 } /* jerry_debugger_send_data */
1324
1325 /**
1326 * Send string to the debugger client.
1327 *
1328 * @return true - if the data sent successfully to the debugger client,
1329 * false - otherwise
1330 */
1331 bool
jerry_debugger_send_string(uint8_t message_type,uint8_t sub_type,const uint8_t * string_p,size_t string_length)1332 jerry_debugger_send_string (uint8_t message_type, /**< message type */
1333 uint8_t sub_type, /**< subtype of the string */
1334 const uint8_t *string_p, /**< string data */
1335 size_t string_length) /**< length of string */
1336 {
1337 JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
1338
1339 const size_t max_byte_count = JERRY_DEBUGGER_SEND_MAX (uint8_t);
1340 const size_t max_message_size = JERRY_DEBUGGER_SEND_SIZE (max_byte_count, uint8_t);
1341
1342 JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_string_t, message_string_p);
1343
1344 message_string_p->type = message_type;
1345
1346 if (sub_type != JERRY_DEBUGGER_NO_SUBTYPE)
1347 {
1348 string_length += 1;
1349 }
1350
1351 while (string_length > max_byte_count)
1352 {
1353 memcpy (message_string_p->string, string_p, max_byte_count);
1354
1355 if (!jerry_debugger_send (max_message_size))
1356 {
1357 return false;
1358 }
1359
1360 string_length -= max_byte_count;
1361 string_p += max_byte_count;
1362 }
1363
1364 message_string_p->type = (uint8_t) (message_type + 1);
1365
1366 if (sub_type != JERRY_DEBUGGER_NO_SUBTYPE)
1367 {
1368 memcpy (message_string_p->string, string_p, string_length - 1);
1369 message_string_p->string[string_length - 1] = sub_type;
1370 }
1371 else
1372 {
1373 memcpy (message_string_p->string, string_p, string_length);
1374 }
1375
1376 return jerry_debugger_send (sizeof (jerry_debugger_send_type_t) + string_length);
1377 } /* jerry_debugger_send_string */
1378
1379 /**
1380 * Send the function compressed pointer to the debugger client.
1381 *
1382 * @return true - if the data was sent successfully to the debugger client,
1383 * false - otherwise
1384 */
1385 bool
jerry_debugger_send_function_cp(jerry_debugger_header_type_t type,ecma_compiled_code_t * compiled_code_p)1386 jerry_debugger_send_function_cp (jerry_debugger_header_type_t type, /**< message type */
1387 ecma_compiled_code_t *compiled_code_p) /**< byte code pointer */
1388 {
1389 JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
1390
1391 JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_byte_code_cp_t, byte_code_cp_p);
1392
1393 byte_code_cp_p->type = (uint8_t) type;
1394
1395 jmem_cpointer_t compiled_code_cp;
1396 JMEM_CP_SET_NON_NULL_POINTER (compiled_code_cp, compiled_code_p);
1397 memcpy (byte_code_cp_p->byte_code_cp, &compiled_code_cp, sizeof (jmem_cpointer_t));
1398
1399 return jerry_debugger_send (sizeof (jerry_debugger_send_byte_code_cp_t));
1400 } /* jerry_debugger_send_function_cp */
1401
1402 /**
1403 * Send function data to the debugger client.
1404 *
1405 * @return true - if the data sent successfully to the debugger client,
1406 * false - otherwise
1407 */
1408 bool
jerry_debugger_send_parse_function(uint32_t line,uint32_t column)1409 jerry_debugger_send_parse_function (uint32_t line, /**< line */
1410 uint32_t column) /**< column */
1411 {
1412 JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
1413
1414 JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_parse_function_t, message_parse_function_p);
1415
1416 message_parse_function_p->type = JERRY_DEBUGGER_PARSE_FUNCTION;
1417 memcpy (message_parse_function_p->line, &line, sizeof (uint32_t));
1418 memcpy (message_parse_function_p->column, &column, sizeof (uint32_t));
1419
1420 return jerry_debugger_send (sizeof (jerry_debugger_send_parse_function_t));
1421 } /* jerry_debugger_send_parse_function */
1422
1423 /**
1424 * Send memory statistics to the debugger client.
1425 */
1426 void
jerry_debugger_send_memstats(void)1427 jerry_debugger_send_memstats (void)
1428 {
1429 JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
1430
1431 JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_memstats_t, memstats_p);
1432
1433 memstats_p->type = JERRY_DEBUGGER_MEMSTATS_RECEIVE;
1434
1435 #if ENABLED (JERRY_MEM_STATS) /* if memory statistics feature is enabled */
1436 jmem_heap_stats_t *heap_stats = &JERRY_CONTEXT (jmem_heap_stats);
1437
1438 uint32_t allocated_bytes = (uint32_t) heap_stats->allocated_bytes;
1439 memcpy (memstats_p->allocated_bytes, &allocated_bytes, sizeof (uint32_t));
1440 uint32_t byte_code_bytes = (uint32_t) heap_stats->byte_code_bytes;
1441 memcpy (memstats_p->byte_code_bytes, &byte_code_bytes, sizeof (uint32_t));
1442 uint32_t string_bytes = (uint32_t) heap_stats->string_bytes;
1443 memcpy (memstats_p->string_bytes, &string_bytes, sizeof (uint32_t));
1444 uint32_t object_bytes = (uint32_t) heap_stats->object_bytes;
1445 memcpy (memstats_p->object_bytes, &object_bytes, sizeof (uint32_t));
1446 uint32_t property_bytes = (uint32_t) heap_stats->property_bytes;
1447 memcpy (memstats_p->property_bytes, &property_bytes, sizeof (uint32_t));
1448 #else /* !ENABLED (JERRY_MEM_STATS) if not, just put zeros */
1449 memset (memstats_p->allocated_bytes, 0, sizeof (uint32_t));
1450 memset (memstats_p->byte_code_bytes, 0, sizeof (uint32_t));
1451 memset (memstats_p->string_bytes, 0, sizeof (uint32_t));
1452 memset (memstats_p->object_bytes, 0, sizeof (uint32_t));
1453 memset (memstats_p->property_bytes, 0, sizeof (uint32_t));
1454 #endif /* ENABLED (JERRY_MEM_STATS) */
1455
1456 jerry_debugger_send (sizeof (jerry_debugger_send_memstats_t));
1457 } /* jerry_debugger_send_memstats */
1458
1459 /*
1460 * Converts an standard error into a string.
1461 *
1462 * @return standard error string
1463 */
1464 static ecma_string_t *
jerry_debugger_exception_object_to_string(ecma_value_t exception_obj_value)1465 jerry_debugger_exception_object_to_string (ecma_value_t exception_obj_value) /**< exception object */
1466 {
1467 ecma_object_t *object_p = ecma_get_object_from_value (exception_obj_value);
1468
1469 jmem_cpointer_t prototype_cp = object_p->u2.prototype_cp;
1470
1471 if (prototype_cp == JMEM_CP_NULL)
1472 {
1473 return NULL;
1474 }
1475
1476 ecma_object_t *prototype_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, prototype_cp);
1477
1478 if (ecma_get_object_type (prototype_p) != ECMA_OBJECT_TYPE_GENERAL
1479 || !ecma_get_object_is_builtin (prototype_p))
1480 {
1481 return NULL;
1482 }
1483
1484 lit_magic_string_id_t string_id;
1485
1486 switch (((ecma_extended_object_t *) prototype_p)->u.built_in.id)
1487 {
1488 #if ENABLED (JERRY_BUILTIN_ERRORS)
1489 case ECMA_BUILTIN_ID_EVAL_ERROR_PROTOTYPE:
1490 {
1491 string_id = LIT_MAGIC_STRING_EVAL_ERROR_UL;
1492 break;
1493 }
1494 case ECMA_BUILTIN_ID_RANGE_ERROR_PROTOTYPE:
1495 {
1496 string_id = LIT_MAGIC_STRING_RANGE_ERROR_UL;
1497 break;
1498 }
1499 case ECMA_BUILTIN_ID_REFERENCE_ERROR_PROTOTYPE:
1500 {
1501 string_id = LIT_MAGIC_STRING_REFERENCE_ERROR_UL;
1502 break;
1503 }
1504 case ECMA_BUILTIN_ID_SYNTAX_ERROR_PROTOTYPE:
1505 {
1506 string_id = LIT_MAGIC_STRING_SYNTAX_ERROR_UL;
1507 break;
1508 }
1509 case ECMA_BUILTIN_ID_TYPE_ERROR_PROTOTYPE:
1510 {
1511 string_id = LIT_MAGIC_STRING_TYPE_ERROR_UL;
1512 break;
1513 }
1514 case ECMA_BUILTIN_ID_URI_ERROR_PROTOTYPE:
1515 {
1516 string_id = LIT_MAGIC_STRING_URI_ERROR_UL;
1517 break;
1518 }
1519 #endif /* ENABLED (JERRY_BUILTIN_ERRORS) */
1520 case ECMA_BUILTIN_ID_ERROR_PROTOTYPE:
1521 {
1522 string_id = LIT_MAGIC_STRING_ERROR_UL;
1523 break;
1524 }
1525 default:
1526 {
1527 return NULL;
1528 }
1529 }
1530
1531 ecma_stringbuilder_t builder = ecma_stringbuilder_create ();
1532
1533 ecma_stringbuilder_append_magic (&builder, string_id);
1534
1535 ecma_property_t *property_p;
1536 property_p = ecma_find_named_property (ecma_get_object_from_value (exception_obj_value),
1537 ecma_get_magic_string (LIT_MAGIC_STRING_MESSAGE));
1538
1539 if (property_p == NULL
1540 || ECMA_PROPERTY_GET_TYPE (*property_p) != ECMA_PROPERTY_TYPE_NAMEDDATA)
1541 {
1542 return ecma_stringbuilder_finalize (&builder);
1543 }
1544
1545 ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (property_p);
1546
1547 if (!ecma_is_value_string (prop_value_p->value))
1548 {
1549 return ecma_stringbuilder_finalize (&builder);
1550 }
1551
1552 ecma_stringbuilder_append_byte (&builder, LIT_CHAR_COLON);
1553 ecma_stringbuilder_append_byte (&builder, LIT_CHAR_SP);
1554 ecma_stringbuilder_append (&builder, ecma_get_string_from_value (prop_value_p->value));
1555
1556 return ecma_stringbuilder_finalize (&builder);
1557 } /* jerry_debugger_exception_object_to_string */
1558
1559 /**
1560 * Send string representation of exception to the client.
1561 *
1562 * @return true - if the data sent successfully to the debugger client,
1563 * false - otherwise
1564 */
1565 bool
jerry_debugger_send_exception_string(ecma_value_t exception_value)1566 jerry_debugger_send_exception_string (ecma_value_t exception_value)
1567 {
1568 JERRY_ASSERT (jcontext_has_pending_exception ());
1569 ecma_string_t *string_p = NULL;
1570
1571 if (ecma_is_value_object (exception_value))
1572 {
1573 string_p = jerry_debugger_exception_object_to_string (exception_value);
1574
1575 if (string_p == NULL)
1576 {
1577 string_p = ecma_get_string_from_value (ecma_builtin_helper_object_to_string (exception_value));
1578 }
1579 }
1580 else if (ecma_is_value_string (exception_value))
1581 {
1582 string_p = ecma_get_string_from_value (exception_value);
1583 ecma_ref_ecma_string (string_p);
1584 }
1585 else
1586 {
1587 string_p = ecma_op_to_string (exception_value);
1588 }
1589
1590 ECMA_STRING_TO_UTF8_STRING (string_p, string_data_p, string_size);
1591
1592 bool result = jerry_debugger_send_string (JERRY_DEBUGGER_EXCEPTION_STR,
1593 JERRY_DEBUGGER_NO_SUBTYPE,
1594 string_data_p,
1595 string_size);
1596
1597 ECMA_FINALIZE_UTF8_STRING (string_data_p, string_size);
1598
1599 ecma_deref_ecma_string (string_p);
1600 return result;
1601 } /* jerry_debugger_send_exception_string */
1602
1603 #endif /* ENABLED (JERRY_DEBUGGER) */
1604