Implement memstats command in the debugger (#1838)
Implementation of memstats command in jerry-debugger, python and html client. Shows the allocated bytes, byte code bytes, string bytes, object bytes, property bytes and heap size. JerryScript-DCO-1.0-Signed-off-by: Daniel Balla dballa@inf.u-szeged.hu
This commit is contained in:
committed by
Zoltan Herczeg
parent
e58f2880df
commit
8894077656
@@ -347,6 +347,14 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer the the rec
|
|||||||
return true;
|
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:
|
case JERRY_DEBUGGER_STOP:
|
||||||
{
|
{
|
||||||
JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t);
|
JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_type_t);
|
||||||
@@ -669,4 +677,42 @@ jerry_debugger_send_parse_function (uint32_t line, /**< line */
|
|||||||
return jerry_debugger_send (sizeof (jerry_debugger_send_parse_function_t));
|
return jerry_debugger_send (sizeof (jerry_debugger_send_parse_function_t));
|
||||||
} /* jerry_debugger_send_parse_function */
|
} /* jerry_debugger_send_parse_function */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send memory statistics to the debugger client.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
jerry_debugger_send_memstats (void)
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
|
||||||
|
|
||||||
|
JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_memstats_t, memstats_p);
|
||||||
|
JERRY_DEBUGGER_INIT_SEND_MESSAGE (memstats_p);
|
||||||
|
JERRY_DEBUGGER_SET_SEND_MESSAGE_SIZE_FROM_TYPE (memstats_p, jerry_debugger_send_memstats_t);
|
||||||
|
|
||||||
|
memstats_p->type = JERRY_DEBUGGER_MEMSTATS_RECEIVE;
|
||||||
|
|
||||||
|
#ifdef JMEM_STATS /* if jmem_stats are defined */
|
||||||
|
jmem_heap_stats_t *heap_stats = &JERRY_CONTEXT (jmem_heap_stats);
|
||||||
|
|
||||||
|
uint32_t allocated_bytes = (uint32_t) heap_stats->allocated_bytes;
|
||||||
|
memcpy (memstats_p->allocated_bytes, &allocated_bytes, sizeof (uint32_t));
|
||||||
|
uint32_t byte_code_bytes = (uint32_t) heap_stats->byte_code_bytes;
|
||||||
|
memcpy (memstats_p->byte_code_bytes, &byte_code_bytes, sizeof (uint32_t));
|
||||||
|
uint32_t string_bytes = (uint32_t) heap_stats->string_bytes;
|
||||||
|
memcpy (memstats_p->string_bytes, &string_bytes, sizeof (uint32_t));
|
||||||
|
uint32_t object_bytes = (uint32_t) heap_stats->object_bytes;
|
||||||
|
memcpy (memstats_p->object_bytes, &object_bytes, sizeof (uint32_t));
|
||||||
|
uint32_t property_bytes = (uint32_t) heap_stats->property_bytes;
|
||||||
|
memcpy (memstats_p->property_bytes, &property_bytes, sizeof (uint32_t));
|
||||||
|
#else /* if not, just put zeros */
|
||||||
|
memset (memstats_p->allocated_bytes, 0, sizeof (uint32_t));
|
||||||
|
memset (memstats_p->byte_code_bytes, 0, sizeof (uint32_t));
|
||||||
|
memset (memstats_p->string_bytes, 0, sizeof (uint32_t));
|
||||||
|
memset (memstats_p->object_bytes, 0, sizeof (uint32_t));
|
||||||
|
memset (memstats_p->property_bytes, 0, sizeof (uint32_t));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
jerry_debugger_send (sizeof (jerry_debugger_send_memstats_t));
|
||||||
|
} /* jerry_debugger_send_memstats */
|
||||||
|
|
||||||
#endif /* JERRY_DEBUGGER */
|
#endif /* JERRY_DEBUGGER */
|
||||||
|
|||||||
@@ -99,14 +99,15 @@ typedef enum
|
|||||||
JERRY_DEBUGGER_FUNCTION_NAME = 11, /**< function name fragment */
|
JERRY_DEBUGGER_FUNCTION_NAME = 11, /**< function name fragment */
|
||||||
JERRY_DEBUGGER_FUNCTION_NAME_END = 12, /**< function name last fragment */
|
JERRY_DEBUGGER_FUNCTION_NAME_END = 12, /**< function name last fragment */
|
||||||
JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 13, /**< invalidate byte code compressed pointer */
|
JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 13, /**< invalidate byte code compressed pointer */
|
||||||
JERRY_DEBUGGER_BREAKPOINT_HIT = 14, /**< notify breakpoint hit */
|
JERRY_DEBUGGER_MEMSTATS_RECEIVE = 14, /**< memstats sent to the client*/
|
||||||
JERRY_DEBUGGER_EXCEPTION_HIT = 15, /**< notify exception hit */
|
JERRY_DEBUGGER_BREAKPOINT_HIT = 15, /**< notify breakpoint hit */
|
||||||
JERRY_DEBUGGER_BACKTRACE = 16, /**< backtrace data */
|
JERRY_DEBUGGER_EXCEPTION_HIT = 16, /**< notify exception hit */
|
||||||
JERRY_DEBUGGER_BACKTRACE_END = 17, /**< last backtrace data */
|
JERRY_DEBUGGER_BACKTRACE = 17, /**< backtrace data */
|
||||||
JERRY_DEBUGGER_EVAL_RESULT = 18, /**< eval result */
|
JERRY_DEBUGGER_BACKTRACE_END = 18, /**< last backtrace data */
|
||||||
JERRY_DEBUGGER_EVAL_RESULT_END = 19, /**< last part of eval result */
|
JERRY_DEBUGGER_EVAL_RESULT = 19, /**< eval result */
|
||||||
JERRY_DEBUGGER_EVAL_ERROR = 20, /**< eval result when an error is occured */
|
JERRY_DEBUGGER_EVAL_RESULT_END = 20, /**< last part of eval result */
|
||||||
JERRY_DEBUGGER_EVAL_ERROR_END = 21, /**< last part of eval result when an error is occured */
|
JERRY_DEBUGGER_EVAL_ERROR = 21, /**< eval result when an error is occured */
|
||||||
|
JERRY_DEBUGGER_EVAL_ERROR_END = 22, /**< last part of eval result when an error is occured */
|
||||||
|
|
||||||
/* Messages sent by the client to server. */
|
/* Messages sent by the client to server. */
|
||||||
|
|
||||||
@@ -114,17 +115,18 @@ typedef enum
|
|||||||
JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1, /**< free byte code compressed pointer */
|
JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1, /**< free byte code compressed pointer */
|
||||||
JERRY_DEBUGGER_UPDATE_BREAKPOINT = 2, /**< update breakpoint status */
|
JERRY_DEBUGGER_UPDATE_BREAKPOINT = 2, /**< update breakpoint status */
|
||||||
JERRY_DEBUGGER_EXCEPTION_CONFIG = 3, /**< exception handler config */
|
JERRY_DEBUGGER_EXCEPTION_CONFIG = 3, /**< exception handler config */
|
||||||
JERRY_DEBUGGER_STOP = 4, /**< stop execution */
|
JERRY_DEBUGGER_MEMSTATS = 4, /**< list memory statistics */
|
||||||
|
JERRY_DEBUGGER_STOP = 5, /**< stop execution */
|
||||||
/* The following messages are only available in breakpoint
|
/* The following messages are only available in breakpoint
|
||||||
* mode and they switch the engine to run mode. */
|
* mode and they switch the engine to run mode. */
|
||||||
JERRY_DEBUGGER_CONTINUE = 5, /**< continue execution */
|
JERRY_DEBUGGER_CONTINUE = 6, /**< continue execution */
|
||||||
JERRY_DEBUGGER_STEP = 6, /**< next breakpoint, step into functions */
|
JERRY_DEBUGGER_STEP = 7, /**< next breakpoint, step into functions */
|
||||||
JERRY_DEBUGGER_NEXT = 7, /**< next breakpoint in the same context */
|
JERRY_DEBUGGER_NEXT = 8, /**< next breakpoint in the same context */
|
||||||
/* The following messages are only available in breakpoint
|
/* The following messages are only available in breakpoint
|
||||||
* mode and this mode is kept after the message is processed. */
|
* mode and this mode is kept after the message is processed. */
|
||||||
JERRY_DEBUGGER_GET_BACKTRACE = 8, /**< get backtrace */
|
JERRY_DEBUGGER_GET_BACKTRACE = 9, /**< get backtrace */
|
||||||
JERRY_DEBUGGER_EVAL = 9, /**< first message of evaluating a string */
|
JERRY_DEBUGGER_EVAL = 10, /**< first message of evaluating a string */
|
||||||
JERRY_DEBUGGER_EVAL_PART = 10, /**< next message of evaluating a string */
|
JERRY_DEBUGGER_EVAL_PART = 11, /**< next message of evaluating a string */
|
||||||
} jerry_debugger_header_type_t;
|
} jerry_debugger_header_type_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -216,6 +218,20 @@ typedef struct
|
|||||||
uint8_t offset[sizeof (uint32_t)]; /**< breakpoint offset */
|
uint8_t offset[sizeof (uint32_t)]; /**< breakpoint offset */
|
||||||
} jerry_debugger_receive_update_breakpoint_t;
|
} jerry_debugger_receive_update_breakpoint_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Outgoing message: send memory statistics
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
jerry_debugger_send_header_t header; /**< message header */
|
||||||
|
uint8_t type; /**< type of the message */
|
||||||
|
uint8_t allocated_bytes[sizeof (uint32_t)]; /**< allocated bytes */
|
||||||
|
uint8_t byte_code_bytes[sizeof (uint32_t)]; /**< byte code bytes */
|
||||||
|
uint8_t string_bytes[sizeof (uint32_t)]; /**< string bytes */
|
||||||
|
uint8_t object_bytes[sizeof (uint32_t)]; /**< object bytes */
|
||||||
|
uint8_t property_bytes[sizeof (uint32_t)]; /**< property bytes */
|
||||||
|
} jerry_debugger_send_memstats_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Outgoing message: notify breakpoint hit.
|
* Outgoing message: notify breakpoint hit.
|
||||||
*/
|
*/
|
||||||
@@ -299,6 +315,7 @@ void jerry_debugger_send_data (jerry_debugger_header_type_t type, const void *da
|
|||||||
bool jerry_debugger_send_string (uint8_t message_type, const uint8_t *string_p, size_t string_length);
|
bool jerry_debugger_send_string (uint8_t message_type, const uint8_t *string_p, size_t string_length);
|
||||||
bool jerry_debugger_send_function_cp (jerry_debugger_header_type_t type, ecma_compiled_code_t *compiled_code_p);
|
bool jerry_debugger_send_function_cp (jerry_debugger_header_type_t type, ecma_compiled_code_t *compiled_code_p);
|
||||||
bool jerry_debugger_send_parse_function (uint32_t line, uint32_t column);
|
bool jerry_debugger_send_parse_function (uint32_t line, uint32_t column);
|
||||||
|
void jerry_debugger_send_memstats (void);
|
||||||
|
|
||||||
#endif /* JERRY_DEBUGGER */
|
#endif /* JERRY_DEBUGGER */
|
||||||
|
|
||||||
|
|||||||
@@ -48,25 +48,27 @@ var JERRY_DEBUGGER_SOURCE_CODE_NAME_END = 10;
|
|||||||
var JERRY_DEBUGGER_FUNCTION_NAME = 11;
|
var JERRY_DEBUGGER_FUNCTION_NAME = 11;
|
||||||
var JERRY_DEBUGGER_FUNCTION_NAME_END = 12;
|
var JERRY_DEBUGGER_FUNCTION_NAME_END = 12;
|
||||||
var JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 13;
|
var JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 13;
|
||||||
var JERRY_DEBUGGER_BREAKPOINT_HIT = 14;
|
var JERRY_DEBUGGER_MEMSTATS_RECEIVE = 14;
|
||||||
var JERRY_DEBUGGER_EXCEPTION_HIT = 15;
|
var JERRY_DEBUGGER_BREAKPOINT_HIT = 15;
|
||||||
var JERRY_DEBUGGER_BACKTRACE = 16;
|
var JERRY_DEBUGGER_EXCEPTION_HIT = 16;
|
||||||
var JERRY_DEBUGGER_BACKTRACE_END = 17;
|
var JERRY_DEBUGGER_BACKTRACE = 17;
|
||||||
var JERRY_DEBUGGER_EVAL_RESULT = 18;
|
var JERRY_DEBUGGER_BACKTRACE_END = 18;
|
||||||
var JERRY_DEBUGGER_EVAL_RESULT_END = 19;
|
var JERRY_DEBUGGER_EVAL_RESULT = 19;
|
||||||
var JERRY_DEBUGGER_EVAL_ERROR = 20;
|
var JERRY_DEBUGGER_EVAL_RESULT_END = 20;
|
||||||
var JERRY_DEBUGGER_EVAL_ERROR_END = 21;
|
var JERRY_DEBUGGER_EVAL_ERROR = 21;
|
||||||
|
var JERRY_DEBUGGER_EVAL_ERROR_END = 22;
|
||||||
|
|
||||||
var JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1;
|
var JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1;
|
||||||
var JERRY_DEBUGGER_UPDATE_BREAKPOINT = 2;
|
var JERRY_DEBUGGER_UPDATE_BREAKPOINT = 2;
|
||||||
var JERRY_DEBUGGER_EXCEPTION_CONFIG = 3;
|
var JERRY_DEBUGGER_EXCEPTION_CONFIG = 3;
|
||||||
var JERRY_DEBUGGER_STOP = 4;
|
var JERRY_DEBUGGER_MEMSTATS = 4;
|
||||||
var JERRY_DEBUGGER_CONTINUE = 5;
|
var JERRY_DEBUGGER_STOP = 5;
|
||||||
var JERRY_DEBUGGER_STEP = 6;
|
var JERRY_DEBUGGER_CONTINUE = 6;
|
||||||
var JERRY_DEBUGGER_NEXT = 7;
|
var JERRY_DEBUGGER_STEP = 7;
|
||||||
var JERRY_DEBUGGER_GET_BACKTRACE = 8;
|
var JERRY_DEBUGGER_NEXT = 8;
|
||||||
var JERRY_DEBUGGER_EVAL = 9;
|
var JERRY_DEBUGGER_GET_BACKTRACE = 9;
|
||||||
var JERRY_DEBUGGER_EVAL_PART = 10;
|
var JERRY_DEBUGGER_EVAL = 10;
|
||||||
|
var JERRY_DEBUGGER_EVAL_PART = 11;
|
||||||
|
|
||||||
var textBox = document.getElementById("log");
|
var textBox = document.getElementById("log");
|
||||||
var commandBox = document.getElementById("command");
|
var commandBox = document.getElementById("command");
|
||||||
@@ -806,6 +808,18 @@ function DebuggerClient(address)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case JERRY_DEBUGGER_MEMSTATS_RECEIVE:
|
||||||
|
{
|
||||||
|
var messagedata = decodeMessage("IIIII", message, 1);
|
||||||
|
|
||||||
|
appendLog("Allocated bytes: " + messagedata[0]);
|
||||||
|
appendLog("Byte code bytes: " + messagedata[1]);
|
||||||
|
appendLog("String bytes: " + messagedata[2]);
|
||||||
|
appendLog("Object bytes: " + messagedata[3]);
|
||||||
|
appendLog("Property bytes: " + messagedata[4]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
case JERRY_DEBUGGER_BREAKPOINT_HIT:
|
case JERRY_DEBUGGER_BREAKPOINT_HIT:
|
||||||
case JERRY_DEBUGGER_EXCEPTION_HIT:
|
case JERRY_DEBUGGER_EXCEPTION_HIT:
|
||||||
{
|
{
|
||||||
@@ -1287,6 +1301,11 @@ function debuggerCommand(event)
|
|||||||
debuggerObj.encodeMessage("B", [ JERRY_DEBUGGER_STOP ]);
|
debuggerObj.encodeMessage("B", [ JERRY_DEBUGGER_STOP ]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "ms":
|
||||||
|
case "memstats":
|
||||||
|
debuggerObj.encodeMessage("B", [ JERRY_DEBUGGER_MEMSTATS ]);
|
||||||
|
break;
|
||||||
|
|
||||||
case "c":
|
case "c":
|
||||||
case "continue":
|
case "continue":
|
||||||
debuggerObj.sendResumeExec(JERRY_DEBUGGER_CONTINUE);
|
debuggerObj.sendResumeExec(JERRY_DEBUGGER_CONTINUE);
|
||||||
|
|||||||
@@ -39,27 +39,29 @@ JERRY_DEBUGGER_SOURCE_CODE_NAME_END = 10
|
|||||||
JERRY_DEBUGGER_FUNCTION_NAME = 11
|
JERRY_DEBUGGER_FUNCTION_NAME = 11
|
||||||
JERRY_DEBUGGER_FUNCTION_NAME_END = 12
|
JERRY_DEBUGGER_FUNCTION_NAME_END = 12
|
||||||
JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 13
|
JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 13
|
||||||
JERRY_DEBUGGER_BREAKPOINT_HIT = 14
|
JERRY_DEBUGGER_MEMSTATS_RECEIVE = 14
|
||||||
JERRY_DEBUGGER_EXCEPTION_HIT = 15
|
JERRY_DEBUGGER_BREAKPOINT_HIT = 15
|
||||||
JERRY_DEBUGGER_BACKTRACE = 16
|
JERRY_DEBUGGER_EXCEPTION_HIT = 16
|
||||||
JERRY_DEBUGGER_BACKTRACE_END = 17
|
JERRY_DEBUGGER_BACKTRACE = 17
|
||||||
JERRY_DEBUGGER_EVAL_RESULT = 18
|
JERRY_DEBUGGER_BACKTRACE_END = 18
|
||||||
JERRY_DEBUGGER_EVAL_RESULT_END = 19
|
JERRY_DEBUGGER_EVAL_RESULT = 19
|
||||||
JERRY_DEBUGGER_EVAL_ERROR = 20
|
JERRY_DEBUGGER_EVAL_RESULT_END = 20
|
||||||
JERRY_DEBUGGER_EVAL_ERROR_END = 21
|
JERRY_DEBUGGER_EVAL_ERROR = 21
|
||||||
|
JERRY_DEBUGGER_EVAL_ERROR_END = 22
|
||||||
|
|
||||||
|
|
||||||
# Messages sent by the client to server.
|
# Messages sent by the client to server.
|
||||||
JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1
|
JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1
|
||||||
JERRY_DEBUGGER_UPDATE_BREAKPOINT = 2
|
JERRY_DEBUGGER_UPDATE_BREAKPOINT = 2
|
||||||
JERRY_DEBUGGER_EXCEPTION_CONFIG = 3
|
JERRY_DEBUGGER_EXCEPTION_CONFIG = 3
|
||||||
JERRY_DEBUGGER_STOP = 4
|
JERRY_DEBUGGER_MEMSTATS = 4
|
||||||
JERRY_DEBUGGER_CONTINUE = 5
|
JERRY_DEBUGGER_STOP = 5
|
||||||
JERRY_DEBUGGER_STEP = 6
|
JERRY_DEBUGGER_CONTINUE = 6
|
||||||
JERRY_DEBUGGER_NEXT = 7
|
JERRY_DEBUGGER_STEP = 7
|
||||||
JERRY_DEBUGGER_GET_BACKTRACE = 8
|
JERRY_DEBUGGER_NEXT = 8
|
||||||
JERRY_DEBUGGER_EVAL = 9
|
JERRY_DEBUGGER_GET_BACKTRACE = 9
|
||||||
JERRY_DEBUGGER_EVAL_PART = 10
|
JERRY_DEBUGGER_EVAL = 10
|
||||||
|
JERRY_DEBUGGER_EVAL_PART = 11
|
||||||
|
|
||||||
MAX_BUFFER_SIZE = 128
|
MAX_BUFFER_SIZE = 128
|
||||||
WEBSOCKET_BINARY_FRAME = 2
|
WEBSOCKET_BINARY_FRAME = 2
|
||||||
@@ -389,6 +391,12 @@ class DebuggerPrompt(Cmd):
|
|||||||
|
|
||||||
self.debugger.send_exception_config(enable)
|
self.debugger.send_exception_config(enable)
|
||||||
|
|
||||||
|
def do_memstats(self, args):
|
||||||
|
""" Memory statistics """
|
||||||
|
self.exec_command(args, JERRY_DEBUGGER_MEMSTATS);
|
||||||
|
return
|
||||||
|
|
||||||
|
do_ms = do_memstats
|
||||||
|
|
||||||
class Multimap(object):
|
class Multimap(object):
|
||||||
|
|
||||||
@@ -932,6 +940,19 @@ def main():
|
|||||||
|
|
||||||
prompt.cmdloop()
|
prompt.cmdloop()
|
||||||
|
|
||||||
|
elif buffer_type == JERRY_DEBUGGER_MEMSTATS_RECEIVE:
|
||||||
|
|
||||||
|
memory_stats = struct.unpack(debugger.byte_order + debugger.idx_format *5,
|
||||||
|
data[3: 3 + 4 *5])
|
||||||
|
|
||||||
|
print("Allocated bytes: %d" % (memory_stats[0]))
|
||||||
|
print("Byte code bytes: %d" % (memory_stats[1]))
|
||||||
|
print("String bytes: %d" % (memory_stats[2]))
|
||||||
|
print("Object bytes: %d" % (memory_stats[3]))
|
||||||
|
print("Property bytes: %d" % (memory_stats[4]))
|
||||||
|
|
||||||
|
prompt.cmdloop()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise Exception("Unknown message")
|
raise Exception("Unknown message")
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ Stopped at tests/debugger/do_help.js:15
|
|||||||
|
|
||||||
Documented commands (type help <topic>):
|
Documented commands (type help <topic>):
|
||||||
========================================
|
========================================
|
||||||
b bt delete eval help next s
|
b bt delete eval help ms pendingdel src
|
||||||
backtrace c dump exception list pendingdel src
|
backtrace c dump exception list n quit step
|
||||||
break continue e fbreak n quit step
|
break continue e fbreak memstats next s
|
||||||
|
|
||||||
(jerry-debugger) quit
|
(jerry-debugger) quit
|
||||||
|
|||||||
Reference in New Issue
Block a user