• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright JS Foundation and other contributors, http://js.foundation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #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