/** * Receive message from the client. * * @return true - if message is processed successfully * false - otherwise */ inline bool __attr_always_inline___ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer to the received data */ uint32_t message_size, /**< message size */ bool *resume_exec_p, /**< pointer to the resume exec flag */ uint8_t *expected_message_type_p, /**< message type */ jerry_debugger_uint8_data_t **message_data_p) /**< custom message data */ { /* Process the received message. */ if (recv_buffer_p[0] >= JERRY_DEBUGGER_CONTINUE && !(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_BREAKPOINT_MODE)) { JERRY_ERROR_MSG ("Message requires breakpoint mode\n"); jerry_debugger_close_connection (); return false; } if (*expected_message_type_p != 0) { JERRY_ASSERT (*expected_message_type_p == JERRY_DEBUGGER_EVAL_PART || *expected_message_type_p == JERRY_DEBUGGER_CLIENT_SOURCE_PART); jerry_debugger_uint8_data_t *uint8_data_p = (jerry_debugger_uint8_data_t *) *message_data_p; if (recv_buffer_p[0] != *expected_message_type_p) { jmem_heap_free_block (uint8_data_p, uint8_data_p->uint8_size + sizeof (jerry_debugger_uint8_data_t)); JERRY_ERROR_MSG ("Unexpected message\n"); jerry_debugger_close_connection (); return false; } JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_uint8_data_part_t, uint8_data_part_p); if (message_size < sizeof (jerry_debugger_receive_uint8_data_part_t) + 1) { jmem_heap_free_block (uint8_data_p, uint8_data_p->uint8_size + sizeof (jerry_debugger_uint8_data_t)); JERRY_ERROR_MSG ("Invalid message size\n"); jerry_debugger_close_connection (); return false; } uint32_t expected_data = uint8_data_p->uint8_size - uint8_data_p->uint8_offset; message_size -= (uint32_t) sizeof (jerry_debugger_receive_uint8_data_part_t); if (message_size > expected_data) { jmem_heap_free_block (uint8_data_p, uint8_data_p->uint8_size + sizeof (jerry_debugger_uint8_data_t)); JERRY_ERROR_MSG ("Invalid message size\n"); jerry_debugger_close_connection (); return false; } lit_utf8_byte_t *string_p = (lit_utf8_byte_t *) (uint8_data_p + 1); memcpy (string_p + uint8_data_p->uint8_offset, (lit_utf8_byte_t *) (uint8_data_part_p + 1), message_size); if (message_size < expected_data) { uint8_data_p->uint8_offset += message_size; return true; } bool result; if (*expected_message_type_p == JERRY_DEBUGGER_EVAL_PART) { if (jerry_debugger_send_eval (string_p, uint8_data_p->uint8_size)) { *resume_exec_p = true; } result = (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) != 0; } else { result = true; JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_CLIENT_SOURCE_MODE); *resume_exec_p = true; } *expected_message_type_p = 0; return result; } switch (recv_buffer_p[0]) { case JERRY_DEBUGGER_FREE_BYTE_CODE_CP: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_byte_code_cp_t); JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_byte_code_cp_t, byte_code_p); jmem_cpointer_t byte_code_free_cp; memcpy (&byte_code_free_cp, byte_code_p->byte_code_cp, sizeof (jmem_cpointer_t)); if (byte_code_free_cp != JERRY_CONTEXT (debugger_byte_code_free_tail)) { JERRY_ERROR_MSG ("Invalid byte code free order\n"); jerry_debugger_close_connection (); return false; } jerry_debugger_byte_code_free_t *byte_code_free_p; byte_code_free_p = JMEM_CP_GET_NON_NULL_POINTER (jerry_debugger_byte_code_free_t, byte_code_free_cp); if (byte_code_free_p->prev_cp != ECMA_NULL_POINTER) { JERRY_CONTEXT (debugger_byte_code_free_tail) = byte_code_free_p->prev_cp; } else { JERRY_CONTEXT (debugger_byte_code_free_head) = ECMA_NULL_POINTER; JERRY_CONTEXT (debugger_byte_code_free_tail) = ECMA_NULL_POINTER; } #ifdef JMEM_STATS jmem_stats_free_byte_code_bytes (((size_t) byte_code_free_p->size) << JMEM_ALIGNMENT_LOG); #endif /* JMEM_STATS */ jmem_heap_free_block (byte_code_free_p, ((size_t) byte_code_free_p->size) << JMEM_ALIGNMENT_LOG); return true; } case JERRY_DEBUGGER_UPDATE_BREAKPOINT: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_update_breakpoint_t); JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_update_breakpoint_t, update_breakpoint_p); jmem_cpointer_t byte_code_cp; memcpy (&byte_code_cp, update_breakpoint_p->byte_code_cp, sizeof (jmem_cpointer_t)); uint8_t *byte_code_p = JMEM_CP_GET_NON_NULL_POINTER (uint8_t, byte_code_cp); uint32_t offset; memcpy (&offset, update_breakpoint_p->offset, sizeof (uint32_t)); byte_code_p += offset; JERRY_ASSERT (*byte_code_p == CBC_BREAKPOINT_ENABLED || *byte_code_p == CBC_BREAKPOINT_DISABLED); *byte_code_p = update_breakpoint_p->is_set_breakpoint ? CBC_BREAKPOINT_ENABLED : CBC_BREAKPOINT_DISABLED; return true; } case JERRY_DEBUGGER_MEMSTATS: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t); jerry_debugger_send_memstats (); return true; } case JERRY_DEBUGGER_STOP: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t); JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP); JERRY_CONTEXT (debugger_stop_context) = NULL; *resume_exec_p = false; return true; } case JERRY_DEBUGGER_CONTINUE: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t); JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_STOP); JERRY_CONTEXT (debugger_stop_context) = NULL; *resume_exec_p = true; return true; } case JERRY_DEBUGGER_STEP: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t); JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP); JERRY_CONTEXT (debugger_stop_context) = NULL; *resume_exec_p = true; return true; } case JERRY_DEBUGGER_NEXT: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t); JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP); JERRY_CONTEXT (debugger_stop_context) = JERRY_CONTEXT (vm_top_context_p); *resume_exec_p = true; return true; } case JERRY_DEBUGGER_FINISH: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t); JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP); /* This will point to the current context's parent (where the function was called) * and in case of NULL the result will the same as in case of STEP. */ JERRY_CONTEXT (debugger_stop_context) = JERRY_CONTEXT (vm_top_context_p->prev_context_p); *resume_exec_p = true; return true; } case JERRY_DEBUGGER_GET_BACKTRACE: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_get_backtrace_t); jerry_debugger_send_backtrace (recv_buffer_p); return true; } case JERRY_DEBUGGER_EXCEPTION_CONFIG: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_exception_config_t); JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_exception_config_t, exception_config_p); if (exception_config_p->enable == 0) { JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_IGNORE_EXCEPTION); JERRY_DEBUG_MSG ("Stop at exception disabled\n"); } else { JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_VM_IGNORE_EXCEPTION); JERRY_DEBUG_MSG ("Stop at exception enabled\n"); } return true; } case JERRY_DEBUGGER_PARSER_CONFIG: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_parser_config_t); JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_parser_config_t, parser_config_p); if (parser_config_p->enable_wait != 0) { JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_PARSER_WAIT); JERRY_DEBUG_MSG ("Waiting after parsing enabled\n"); } else { JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_PARSER_WAIT); JERRY_DEBUG_MSG ("Waiting after parsing disabled\n"); } return true; } case JERRY_DEBUGGER_PARSER_RESUME: { JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t); if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_PARSER_WAIT_MODE)) { JERRY_ERROR_MSG ("Not in parser wait mode\n"); jerry_debugger_close_connection (); return false; } JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_PARSER_WAIT_MODE); return true; } case JERRY_DEBUGGER_EVAL: { if (message_size < sizeof (jerry_debugger_receive_eval_first_t) + 1) { JERRY_ERROR_MSG ("Invalid message size\n"); jerry_debugger_close_connection (); return false; } JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_eval_first_t, eval_first_p); uint32_t eval_size; memcpy (&eval_size, eval_first_p->eval_size, sizeof (uint32_t)); if (eval_size <= JERRY_CONTEXT (debugger_max_receive_size) - sizeof (jerry_debugger_receive_eval_first_t)) { if (eval_size != message_size - sizeof (jerry_debugger_receive_eval_first_t)) { JERRY_ERROR_MSG ("Invalid message size\n"); jerry_debugger_close_connection (); return false; } if (jerry_debugger_send_eval ((lit_utf8_byte_t *) (eval_first_p + 1), eval_size)) { *resume_exec_p = true; } return (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) != 0; } jerry_debugger_uint8_data_t *eval_uint8_data_p; size_t eval_data_size = sizeof (jerry_debugger_uint8_data_t) + eval_size; eval_uint8_data_p = (jerry_debugger_uint8_data_t *) jmem_heap_alloc_block (eval_data_size); eval_uint8_data_p->uint8_size = eval_size; eval_uint8_data_p->uint8_offset = (uint32_t) (message_size - sizeof (jerry_debugger_receive_eval_first_t)); lit_utf8_byte_t *eval_string_p = (lit_utf8_byte_t *) (eval_uint8_data_p + 1); memcpy (eval_string_p, (lit_utf8_byte_t *) (eval_first_p + 1), message_size - sizeof (jerry_debugger_receive_eval_first_t)); *message_data_p = eval_uint8_data_p; *expected_message_type_p = JERRY_DEBUGGER_EVAL_PART; return true; } case JERRY_DEBUGGER_CLIENT_SOURCE: { if (message_size <= sizeof (jerry_debugger_receive_client_source_first_t)) { JERRY_ERROR_MSG ("Invalid message size\n"); jerry_debugger_close_connection (); return false; } if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CLIENT_SOURCE_MODE)) { JERRY_ERROR_MSG ("Not in client source mode\n"); jerry_debugger_close_connection (); return false; } JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_client_source_first_t, client_source_first_p); uint32_t client_source_size; memcpy (&client_source_size, client_source_first_p->code_size, sizeof (uint32_t)); uint32_t header_size = sizeof (jerry_debugger_receive_client_source_first_t); if (client_source_size <= JERRY_CONTEXT (debugger_max_receive_size) - header_size && client_source_size != message_size - header_size) { JERRY_ERROR_MSG ("Invalid message size\n"); jerry_debugger_close_connection (); return false; } jerry_debugger_uint8_data_t *client_source_data_p; size_t client_source_data_size = sizeof (jerry_debugger_uint8_data_t) + client_source_size; client_source_data_p = (jerry_debugger_uint8_data_t *) jmem_heap_alloc_block (client_source_data_size); client_source_data_p->uint8_size = client_source_size; client_source_data_p->uint8_offset = (uint32_t) (message_size - sizeof (jerry_debugger_receive_client_source_first_t)); lit_utf8_byte_t *client_source_string_p = (lit_utf8_byte_t *) (client_source_data_p + 1); memcpy (client_source_string_p, (lit_utf8_byte_t *) (client_source_first_p + 1), message_size - sizeof (jerry_debugger_receive_client_source_first_t)); *message_data_p = client_source_data_p; if (client_source_data_p->uint8_size != client_source_data_p->uint8_offset) { *expected_message_type_p = JERRY_DEBUGGER_CLIENT_SOURCE_PART; } else { JERRY_DEBUGGER_CLEAR_FLAGS (JERRY_DEBUGGER_CLIENT_SOURCE_MODE); *resume_exec_p = true; } return true; } case JERRY_DEBUGGER_NO_MORE_SOURCES: { if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CLIENT_SOURCE_MODE)) { JERRY_ERROR_MSG ("Not in client source mode\n"); jerry_debugger_close_connection (); return false; } JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t); JERRY_DEBUGGER_UPDATE_FLAGS (JERRY_DEBUGGER_CLIENT_NO_SOURCE, JERRY_DEBUGGER_CLIENT_SOURCE_MODE); *resume_exec_p = true; return true; } case JERRY_DEBUGGER_CONTEXT_RESET: { if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CLIENT_SOURCE_MODE)) { JERRY_ERROR_MSG ("Not in client source mode\n"); jerry_debugger_close_connection (); return false; } JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t); JERRY_DEBUGGER_UPDATE_FLAGS (JERRY_DEBUGGER_CONTEXT_RESET_MODE, JERRY_DEBUGGER_CLIENT_SOURCE_MODE); *resume_exec_p = true; return true; } default: { JERRY_ERROR_MSG ("Unexpected message."); jerry_debugger_close_connection (); return false; } } } /* jerry_debugger_process_message */
/** * Decrease reference counter of Compact * Byte Code or regexp byte code. */ void ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */ { JERRY_ASSERT (bytecode_p->refs > 0); bytecode_p->refs--; if (bytecode_p->refs > 0) { /* Non-zero reference counter. */ return; } if (bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION) { jmem_cpointer_t *literal_start_p = NULL; uint32_t literal_end; uint32_t const_literal_end; if (bytecode_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS) { uint8_t *byte_p = (uint8_t *) bytecode_p; literal_start_p = (jmem_cpointer_t *) (byte_p + sizeof (cbc_uint16_arguments_t)); cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_p; literal_end = args_p->literal_end; const_literal_end = args_p->const_literal_end; } else { uint8_t *byte_p = (uint8_t *) bytecode_p; literal_start_p = (jmem_cpointer_t *) (byte_p + sizeof (cbc_uint8_arguments_t)); cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_p; literal_end = args_p->literal_end; const_literal_end = args_p->const_literal_end; } for (uint32_t i = const_literal_end; i < literal_end; i++) { jmem_cpointer_t bytecode_cpointer = literal_start_p[i]; ecma_compiled_code_t *bytecode_literal_p = ECMA_GET_NON_NULL_POINTER (ecma_compiled_code_t, bytecode_cpointer); /* Self references are ignored. */ if (bytecode_literal_p != bytecode_p) { ecma_bytecode_deref (bytecode_literal_p); } } #ifdef JERRY_DEBUGGER if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) && !(bytecode_p->status_flags & CBC_CODE_FLAGS_DEBUGGER_IGNORE) && jerry_debugger_send_function_cp (JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP, bytecode_p)) { /* Delay the byte code free until the debugger client is notified. * If the connection is aborted the pointer is still freed by * jerry_debugger_close_connection(). */ jerry_debugger_byte_code_free_t *byte_code_free_p = (jerry_debugger_byte_code_free_t *) bytecode_p; jmem_cpointer_t byte_code_free_head = JERRY_CONTEXT (debugger_byte_code_free_head); byte_code_free_p->prev_cp = ECMA_NULL_POINTER; jmem_cpointer_t byte_code_free_cp; JMEM_CP_SET_NON_NULL_POINTER (byte_code_free_cp, byte_code_free_p); if (byte_code_free_head == ECMA_NULL_POINTER) { JERRY_CONTEXT (debugger_byte_code_free_tail) = byte_code_free_cp; } else { jerry_debugger_byte_code_free_t *first_byte_code_free_p; first_byte_code_free_p = JMEM_CP_GET_NON_NULL_POINTER (jerry_debugger_byte_code_free_t, byte_code_free_head); first_byte_code_free_p->prev_cp = byte_code_free_cp; } JERRY_CONTEXT (debugger_byte_code_free_head) = byte_code_free_cp; return; } #endif /* JERRY_DEBUGGER */ #ifdef JMEM_STATS jmem_stats_free_byte_code_bytes (((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG); #endif /* JMEM_STATS */ } else { #ifndef CONFIG_DISABLE_REGEXP_BUILTIN re_compiled_code_t *re_bytecode_p = (re_compiled_code_t *) bytecode_p; ecma_deref_ecma_string (ECMA_GET_NON_NULL_POINTER (ecma_string_t, re_bytecode_p->pattern_cp)); #endif /* !CONFIG_DISABLE_REGEXP_BUILTIN */ } jmem_heap_free_block (bytecode_p, ((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG); } /* ecma_bytecode_deref */