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 */
36typedef 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 */
45JERRY_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 */
72void
73jerry_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 */
99static bool
100jerry_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 */
119static void
120jerry_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 */
216static void
217jerry_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 */
287static uint8_t
288jerry_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 */
340static bool
341jerry_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 */
431static void
432jerry_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 */
547static bool
548jerry_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);
655static 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 */
693static inline bool JERRY_ATTR_ALWAYS_INLINE
694jerry_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 */
1148bool
1149jerry_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 */
1212void
1213jerry_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 */
1258void
1259jerry_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 */
1276bool
1277jerry_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 */
1310void
1311jerry_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 */
1331bool
1332jerry_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 */
1385bool
1386jerry_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 */
1408bool
1409jerry_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 */
1426void
1427jerry_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 */
1464static ecma_string_t *
1465jerry_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 */
1565bool
1566jerry_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