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