/** * Handle execution of control path that should be unreachable */ void __noreturn jerry_unreachable (const char *file, /**< file name */ const char *function, /**< function name */ const uint32_t line) /**< line */ { JERRY_ERROR_MSG ("ICE: Unreachable control path at %s(%s):%lu was executed.\n", file, function, (unsigned long) line); jerry_fatal (ERR_FAILED_INTERNAL_ASSERTION); } /* jerry_unreachable */
/** * Handle failed assertion */ void __noreturn jerry_assert_fail (const char *assertion, /**< assertion condition string */ const char *file, /**< file name */ const char *function, /**< function name */ const uint32_t line) /**< line */ { JERRY_ERROR_MSG ("ICE: Assertion '%s' failed at %s(%s):%lu.\n", assertion, file, function, (unsigned long) line); jerry_fatal (ERR_FAILED_INTERNAL_ASSERTION); } /* jerry_assert_fail */
/* * Exit with specified status code. * * If !JERRY_NDEBUG and code != 0, print status code with description * and call assertion fail handler. */ void __noreturn jerry_fatal (jerry_fatal_code_t code) /**< status code */ { #ifndef JERRY_NDEBUG switch (code) { case ERR_OUT_OF_MEMORY: { JERRY_ERROR_MSG ("Error: ERR_OUT_OF_MEMORY\n"); break; } case ERR_SYSCALL: { /* print nothing as it may invoke syscall recursively */ break; } case ERR_REF_COUNT_LIMIT: { JERRY_ERROR_MSG ("Error: ERR_REF_COUNT_LIMIT\n"); break; } case ERR_FAILED_INTERNAL_ASSERTION: { JERRY_ERROR_MSG ("Error: ERR_FAILED_INTERNAL_ASSERTION\n"); break; } } #endif /* !JERRY_NDEBUG */ jerry_port_fatal (code); /* to make compiler happy for some RTOS: 'control reaches end of non-void function' */ while (true) { } } /* jerry_fatal */
/** * 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 */