mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Under the cover of the debugger transport layer, allocation on the engine's heap has been made available to the public. As there are actually no restrictions on what the allocated memory can be used for, the memory management functions better fit in the core part of the API. Closes #1805 JerryScript-DCO-1.0-Signed-off-by: Akos Kiss akiss@inf.u-szeged.hu
251 lines
8.0 KiB
C
251 lines
8.0 KiB
C
/* Copyright JS Foundation and other contributors, http://js.foundation
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "debugger.h"
|
|
#include "jcontext.h"
|
|
#include "jerryscript.h"
|
|
|
|
#ifdef JERRY_DEBUGGER
|
|
|
|
/**
|
|
* Minimum number of bytes transmitted or received.
|
|
*/
|
|
#define JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE 64
|
|
|
|
/**
|
|
* Sleep time in milliseconds between each jerry_debugger_receive call
|
|
*/
|
|
#define JERRY_DEBUGGER_TRANSPORT_TIMEOUT 100
|
|
|
|
/**
|
|
* Add a new transport layer.
|
|
*/
|
|
void
|
|
jerry_debugger_transport_add (jerry_debugger_transport_header_t *header_p, /**< transport implementation */
|
|
size_t send_message_header_size, /**< header bytes reserved for outgoing messages */
|
|
size_t max_send_message_size, /**< maximum number of bytes transmitted in a message */
|
|
size_t receive_message_header_size, /**< header bytes reserved for incoming messages */
|
|
size_t max_receive_message_size) /**< maximum number of bytes received in a message */
|
|
{
|
|
JERRY_ASSERT (max_send_message_size > JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE
|
|
&& max_receive_message_size > JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE);
|
|
|
|
header_p->next_p = JERRY_CONTEXT (debugger_transport_header_p);
|
|
JERRY_CONTEXT (debugger_transport_header_p) = header_p;
|
|
|
|
uint8_t *payload_p;
|
|
size_t max_send_size;
|
|
size_t max_receive_size;
|
|
|
|
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
|
|
{
|
|
payload_p = JERRY_CONTEXT (debugger_send_buffer_payload_p);
|
|
max_send_size = JERRY_CONTEXT (debugger_max_send_size);
|
|
max_receive_size = JERRY_CONTEXT (debugger_max_receive_size);
|
|
}
|
|
else
|
|
{
|
|
JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_CONNECTED);
|
|
payload_p = JERRY_CONTEXT (debugger_send_buffer);
|
|
max_send_size = JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE;
|
|
max_receive_size = JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE;
|
|
}
|
|
|
|
JERRY_ASSERT (max_send_size > JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE + send_message_header_size);
|
|
JERRY_ASSERT (max_receive_size > JERRY_DEBUGGER_TRANSPORT_MIN_BUFFER_SIZE + receive_message_header_size);
|
|
|
|
JERRY_CONTEXT (debugger_send_buffer_payload_p) = payload_p + send_message_header_size;
|
|
|
|
max_send_size = max_send_size - send_message_header_size;
|
|
max_receive_size = max_receive_size - receive_message_header_size;
|
|
|
|
if (max_send_size > max_send_message_size)
|
|
{
|
|
max_send_size = max_send_message_size;
|
|
}
|
|
|
|
if (max_receive_size > max_receive_message_size)
|
|
{
|
|
max_receive_size = max_receive_message_size;
|
|
}
|
|
|
|
JERRY_CONTEXT (debugger_max_send_size) = (uint8_t) max_send_size;
|
|
JERRY_CONTEXT (debugger_max_receive_size) = (uint8_t) max_receive_size;
|
|
} /* jerry_debugger_transport_add */
|
|
|
|
/**
|
|
* Starts the communication to the debugger client.
|
|
* Must be called after the connection is successfully established.
|
|
*/
|
|
void
|
|
jerry_debugger_transport_start (void)
|
|
{
|
|
JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
|
|
|
|
if (jerry_debugger_send_configuration (JERRY_CONTEXT (debugger_max_receive_size)))
|
|
{
|
|
JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_VM_STOP);
|
|
JERRY_CONTEXT (debugger_stop_context) = NULL;
|
|
}
|
|
} /* jerry_debugger_transport_start */
|
|
|
|
/**
|
|
* Returns true if a debugger client is connected.
|
|
*
|
|
* @return true - a debugger client is connected,
|
|
* false - otherwise
|
|
*/
|
|
bool
|
|
jerry_debugger_transport_is_connected (void)
|
|
{
|
|
return (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED) != 0;
|
|
} /* jerry_debugger_transport_is_connected */
|
|
|
|
/**
|
|
* Notifies the debugger server that the connection is closed.
|
|
*/
|
|
void
|
|
jerry_debugger_transport_close (void)
|
|
{
|
|
if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED))
|
|
{
|
|
return;
|
|
}
|
|
|
|
JERRY_CONTEXT (debugger_flags) = JERRY_DEBUGGER_VM_IGNORE;
|
|
|
|
jerry_debugger_transport_header_t *current_p = JERRY_CONTEXT (debugger_transport_header_p);
|
|
|
|
JERRY_ASSERT (current_p != NULL);
|
|
|
|
do
|
|
{
|
|
jerry_debugger_transport_header_t *next_p = current_p->next_p;
|
|
|
|
current_p->close (current_p);
|
|
|
|
current_p = next_p;
|
|
}
|
|
while (current_p != NULL);
|
|
|
|
jerry_port_log (JERRY_LOG_LEVEL_DEBUG, "Debugger client connection closed.\n");
|
|
|
|
jerry_debugger_free_unreferenced_byte_code ();
|
|
} /* jerry_debugger_transport_close */
|
|
|
|
/**
|
|
* Send data over the current connection
|
|
*
|
|
* @return true - data sent successfully,
|
|
* false - connection closed
|
|
*/
|
|
bool
|
|
jerry_debugger_transport_send (const uint8_t *message_p, /**< message to be sent */
|
|
size_t message_length) /**< message length in bytes */
|
|
{
|
|
JERRY_ASSERT (jerry_debugger_transport_is_connected ());
|
|
JERRY_ASSERT (message_length > 0);
|
|
|
|
jerry_debugger_transport_header_t *header_p = JERRY_CONTEXT (debugger_transport_header_p);
|
|
uint8_t *payload_p = JERRY_CONTEXT (debugger_send_buffer_payload_p);
|
|
size_t max_send_size = JERRY_CONTEXT (debugger_max_send_size);
|
|
|
|
do
|
|
{
|
|
size_t fragment_length = (message_length <= max_send_size ? message_length
|
|
: max_send_size);
|
|
|
|
memcpy (payload_p, message_p, fragment_length);
|
|
|
|
if (!header_p->send (header_p, payload_p, fragment_length))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
message_p += fragment_length;
|
|
message_length -= fragment_length;
|
|
}
|
|
while (message_length > 0);
|
|
|
|
return true;
|
|
} /* jerry_debugger_transport_send */
|
|
|
|
/**
|
|
* Receive data from the current connection
|
|
*
|
|
* Note:
|
|
* A message is received if message_start_p is not NULL
|
|
*
|
|
* @return true - function successfully completed,
|
|
* false - connection closed
|
|
*/
|
|
bool
|
|
jerry_debugger_transport_receive (jerry_debugger_transport_receive_context_t *context_p) /**< [out] receive
|
|
* context */
|
|
{
|
|
JERRY_ASSERT (jerry_debugger_transport_is_connected ());
|
|
|
|
context_p->buffer_p = JERRY_CONTEXT (debugger_receive_buffer);
|
|
context_p->received_length = JERRY_CONTEXT (debugger_received_length);
|
|
context_p->message_p = NULL;
|
|
context_p->message_length = 0;
|
|
context_p->message_total_length = 0;
|
|
|
|
jerry_debugger_transport_header_t *header_p = JERRY_CONTEXT (debugger_transport_header_p);
|
|
|
|
return header_p->receive (header_p, context_p);
|
|
} /* jerry_debugger_transport_receive */
|
|
|
|
/**
|
|
* Clear the message buffer after the message is processed
|
|
*/
|
|
void
|
|
jerry_debugger_transport_receive_completed (jerry_debugger_transport_receive_context_t *context_p) /**< receive
|
|
* context */
|
|
{
|
|
JERRY_ASSERT (context_p->message_p != NULL);
|
|
JERRY_ASSERT (context_p->buffer_p == JERRY_CONTEXT (debugger_receive_buffer));
|
|
|
|
size_t message_total_length = context_p->message_total_length;
|
|
size_t received_length = context_p->received_length;
|
|
|
|
JERRY_ASSERT (message_total_length <= received_length);
|
|
|
|
if (message_total_length == 0 || message_total_length == received_length)
|
|
{
|
|
/* All received data is processed. */
|
|
JERRY_CONTEXT (debugger_received_length) = 0;
|
|
return;
|
|
}
|
|
|
|
uint8_t *buffer_p = context_p->buffer_p;
|
|
received_length -= message_total_length;
|
|
|
|
memmove (buffer_p, buffer_p + message_total_length, received_length);
|
|
|
|
JERRY_CONTEXT (debugger_received_length) = (uint16_t) received_length;
|
|
} /* jerry_debugger_transport_receive_completed */
|
|
|
|
/**
|
|
* Suspend execution for a predefined time (JERRY_DEBUGGER_TRANSPORT_TIMEOUT ms).
|
|
*/
|
|
void
|
|
jerry_debugger_transport_sleep (void)
|
|
{
|
|
jerry_port_sleep (JERRY_DEBUGGER_TRANSPORT_TIMEOUT);
|
|
} /* jerry_debugger_transport_sleep */
|
|
|
|
#endif /* JERRY_DEBUGGER */
|