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 #ifndef DEBUGGER_H 17 #define DEBUGGER_H 18 19 #include "ecma-globals.h" 20 #include "jerryscript-debugger-transport.h" 21 22 #if ENABLED (JERRY_DEBUGGER) 23 24 /* JerryScript debugger protocol is a simplified version of RFC-6455 (WebSockets). */ 25 26 /** 27 * Frequency of calling jerry_debugger_receive() by the VM. 28 */ 29 #define JERRY_DEBUGGER_MESSAGE_FREQUENCY 5 30 31 /** 32 * This constant represents that the string to be sent has no subtype. 33 */ 34 #define JERRY_DEBUGGER_NO_SUBTYPE 0 35 36 /** 37 * Limited resources available for the engine, so it is important to 38 * check the maximum buffer size. It needs to be between 64 and 256 bytes. 39 */ 40 #if JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE < 64 || JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE > 256 41 #error Please define the MAX_BUFFER_SIZE between 64 and 256 bytes. 42 #endif /* JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE < 64 || JERRY_DEBUGGER_TRANSPORT_MAX_BUFFER_SIZE > 256 */ 43 44 /** 45 * Calculate the maximum number of items for a given type 46 * which can be transmitted in one message. 47 */ 48 #define JERRY_DEBUGGER_SEND_MAX(type) \ 49 ((size_t) ((JERRY_CONTEXT (debugger_max_send_size) - sizeof (jerry_debugger_send_type_t)) / sizeof (type))) 50 51 /** 52 * Calculate the size of a message when a count number of items transmitted. 53 */ 54 #define JERRY_DEBUGGER_SEND_SIZE(count, type) \ 55 ((size_t) ((count * sizeof (type)) + sizeof (jerry_debugger_send_type_t))) 56 57 /** 58 * Debugger operation modes: 59 * 60 * The debugger has two operation modes: run mode and breakpoint mode. 61 * 62 * In run mode the debugger server accepts only a limited number of message 63 * types from the debugger client (e.g. stop execution, set breakpoint). 64 * 65 * In breakpoint mode the JavaScript execution is stopped at a breakpoint and 66 * more message types are accepted (e.g. get backtrace, evaluate expression). 67 * 68 * Switching between modes: 69 * 70 * When the JavaScript execution stops at a breakpoint the server sends a 71 * JERRY_DEBUGGER_BREAKPOINT_HIT message to the client. The client can only 72 * issue breakpoint mode commands after this message is received. 73 * 74 * Certain breakpoint mode commands (e.g. continue) resumes the JavaScript 75 * execution and the client must not send any breakpoint mode messages 76 * until the JERRY_DEBUGGER_BREAKPOINT_HIT is received again. 77 * 78 * The debugger server starts in run mode but stops at the first available 79 * breakpoint. 80 */ 81 82 /** 83 * Debugger option flags. 84 */ 85 typedef enum 86 { 87 JERRY_DEBUGGER_CONNECTED = 1u << 0, /**< debugger is connected */ 88 JERRY_DEBUGGER_BREAKPOINT_MODE = 1u << 1, /**< debugger waiting at a breakpoint */ 89 JERRY_DEBUGGER_VM_STOP = 1u << 2, /**< stop at the next breakpoint even if disabled */ 90 JERRY_DEBUGGER_VM_IGNORE = 1u << 3, /**< ignore all breakpoints */ 91 JERRY_DEBUGGER_VM_IGNORE_EXCEPTION = 1u << 4, /**< debugger doesn't stop at any exception */ 92 JERRY_DEBUGGER_VM_EXCEPTION_THROWN = 1u << 5, /**< no need to stop for this exception */ 93 JERRY_DEBUGGER_PARSER_WAIT = 1u << 6, /**< debugger should wait after parsing is completed */ 94 JERRY_DEBUGGER_PARSER_WAIT_MODE = 1u << 7, /**< debugger is waiting after parsing is completed */ 95 JERRY_DEBUGGER_CLIENT_SOURCE_MODE = 1u << 8, /**< debugger waiting for client code */ 96 JERRY_DEBUGGER_CLIENT_NO_SOURCE = 1u << 9, /**< debugger leaving the client source loop */ 97 JERRY_DEBUGGER_CONTEXT_RESET_MODE = 1u << 10, /**< debugger and engine reinitialization mode */ 98 #ifdef ACE_DEBUGGER_CUSTOM 99 JERRY_DEBUGGER_TRANSPORT_STARTED = 1u << 11, /**< only can send data to client after this flag set */ 100 #endif 101 } jerry_debugger_flags_t; 102 103 /** 104 * Set debugger flags. 105 */ 106 #define JERRY_DEBUGGER_SET_FLAGS(flags) \ 107 JERRY_CONTEXT (debugger_flags) = (JERRY_CONTEXT (debugger_flags) | (uint32_t) (flags)) 108 109 /** 110 * Clear debugger flags. 111 */ 112 #define JERRY_DEBUGGER_CLEAR_FLAGS(flags) \ 113 JERRY_CONTEXT (debugger_flags) = (JERRY_CONTEXT (debugger_flags) & (uint32_t) ~(flags)) 114 115 /** 116 * Set and clear debugger flags. 117 */ 118 #define JERRY_DEBUGGER_UPDATE_FLAGS(flags_to_set, flags_to_clear) \ 119 JERRY_CONTEXT (debugger_flags) = ((JERRY_CONTEXT (debugger_flags) | (uint32_t) (flags_to_set)) \ 120 & (uint32_t) ~(flags_to_clear)) 121 122 /** 123 * Types for the package. 124 */ 125 typedef enum 126 { 127 /* Messages sent by the server to client. */ 128 /* This is a handshake message, sent once during initialization. */ 129 JERRY_DEBUGGER_CONFIGURATION = 1, /**< debugger configuration */ 130 /* These messages are sent by the parser. */ 131 JERRY_DEBUGGER_PARSE_ERROR = 2, /**< parse error */ 132 JERRY_DEBUGGER_BYTE_CODE_CP = 3, /**< byte code compressed pointer */ 133 JERRY_DEBUGGER_PARSE_FUNCTION = 4, /**< parsing a new function */ 134 JERRY_DEBUGGER_BREAKPOINT_LIST = 5, /**< list of line offsets */ 135 JERRY_DEBUGGER_BREAKPOINT_OFFSET_LIST = 6, /**< list of byte code offsets */ 136 JERRY_DEBUGGER_SOURCE_CODE = 7, /**< source code fragment */ 137 JERRY_DEBUGGER_SOURCE_CODE_END = 8, /**< source code last fragment */ 138 JERRY_DEBUGGER_SOURCE_CODE_NAME = 9, /**< source code name fragment */ 139 JERRY_DEBUGGER_SOURCE_CODE_NAME_END = 10, /**< source code name last fragment */ 140 JERRY_DEBUGGER_FUNCTION_NAME = 11, /**< function name fragment */ 141 JERRY_DEBUGGER_FUNCTION_NAME_END = 12, /**< function name last fragment */ 142 JERRY_DEBUGGER_WAITING_AFTER_PARSE = 13, /**< engine waiting for a parser resume */ 143 /* These messages are generic messages. */ 144 JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 14, /**< invalidate byte code compressed pointer */ 145 JERRY_DEBUGGER_MEMSTATS_RECEIVE = 15, /**< memstats sent to the client */ 146 JERRY_DEBUGGER_BREAKPOINT_HIT = 16, /**< notify breakpoint hit */ 147 JERRY_DEBUGGER_EXCEPTION_HIT = 17, /**< notify exception hit */ 148 JERRY_DEBUGGER_EXCEPTION_STR = 18, /**< exception string fragment */ 149 JERRY_DEBUGGER_EXCEPTION_STR_END = 19, /**< exception string last fragment */ 150 JERRY_DEBUGGER_BACKTRACE_TOTAL = 20, /**< number of total frames */ 151 JERRY_DEBUGGER_BACKTRACE = 21, /**< backtrace data */ 152 JERRY_DEBUGGER_BACKTRACE_END = 22, /**< last backtrace data */ 153 JERRY_DEBUGGER_EVAL_RESULT = 23, /**< eval result */ 154 JERRY_DEBUGGER_EVAL_RESULT_END = 24, /**< last part of eval result */ 155 JERRY_DEBUGGER_WAIT_FOR_SOURCE = 25, /**< engine waiting for source code */ 156 JERRY_DEBUGGER_OUTPUT_RESULT = 26, /**< output sent by the program to the debugger */ 157 JERRY_DEBUGGER_OUTPUT_RESULT_END = 27, /**< last output result data */ 158 JERRY_DEBUGGER_SCOPE_CHAIN = 28, /**< scope chain */ 159 JERRY_DEBUGGER_SCOPE_CHAIN_END = 29, /**< last output of scope chain */ 160 JERRY_DEBUGGER_SCOPE_VARIABLES = 30, /**< scope variables */ 161 JERRY_DEBUGGER_SCOPE_VARIABLES_END = 31, /**< last output of scope variables */ 162 JERRY_DEBUGGER_CLOSE_CONNECTION = 32, /**< close connection with the client */ 163 JERRY_DEBUGGER_MESSAGES_OUT_MAX_COUNT, /**< number of different type of output messages by the debugger */ 164 165 /* Messages sent by the client to server. */ 166 167 /* The following messages are accepted in both run and breakpoint modes. */ 168 JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1, /**< free byte code compressed pointer */ 169 JERRY_DEBUGGER_UPDATE_BREAKPOINT = 2, /**< update breakpoint status */ 170 JERRY_DEBUGGER_EXCEPTION_CONFIG = 3, /**< exception handler config */ 171 JERRY_DEBUGGER_PARSER_CONFIG = 4, /**< parser config */ 172 JERRY_DEBUGGER_MEMSTATS = 5, /**< list memory statistics */ 173 JERRY_DEBUGGER_STOP = 6, /**< stop execution */ 174 /* The following message is only available in waiting after parse mode. */ 175 JERRY_DEBUGGER_PARSER_RESUME = 7, /**< stop waiting after parse */ 176 /* The following four messages are only available in client switch mode. */ 177 JERRY_DEBUGGER_CLIENT_SOURCE = 8, /**< first message of client source */ 178 JERRY_DEBUGGER_CLIENT_SOURCE_PART = 9, /**< next message of client source */ 179 JERRY_DEBUGGER_NO_MORE_SOURCES = 10, /**< no more sources notification */ 180 JERRY_DEBUGGER_CONTEXT_RESET = 11, /**< context reset request */ 181 /* The following messages are only available in breakpoint 182 * mode and they switch the engine to run mode. */ 183 JERRY_DEBUGGER_CONTINUE = 12, /**< continue execution */ 184 JERRY_DEBUGGER_STEP = 13, /**< next breakpoint, step into functions */ 185 JERRY_DEBUGGER_NEXT = 14, /**< next breakpoint in the same context */ 186 JERRY_DEBUGGER_FINISH = 15, /**< Continue running just after the function in the current stack frame returns */ 187 /* The following messages are only available in breakpoint 188 * mode and this mode is kept after the message is processed. */ 189 JERRY_DEBUGGER_GET_BACKTRACE = 16, /**< get backtrace */ 190 JERRY_DEBUGGER_EVAL = 17, /**< first message of evaluating a string */ 191 JERRY_DEBUGGER_EVAL_PART = 18, /**< next message of evaluating a string */ 192 JERRY_DEBUGGER_GET_SCOPE_CHAIN = 19, /**< get type names of the scope chain */ 193 JERRY_DEBUGGER_GET_SCOPE_VARIABLES = 20, /**< get variables of a scope */ 194 JERRY_DEBUGGER_MESSAGES_IN_MAX_COUNT, /**< number of different type of input messages */ 195 } jerry_debugger_header_type_t; 196 197 /** 198 * Debugger option flags. 199 */ 200 typedef enum 201 { 202 JERRY_DEBUGGER_LITTLE_ENDIAN = 1u << 0, /**< little endian */ 203 } jerry_debugger_configuration_flags_t; 204 205 /** 206 * Subtypes of eval. 207 */ 208 typedef enum 209 { 210 JERRY_DEBUGGER_EVAL_EVAL = 0, /**< evaluate expression */ 211 JERRY_DEBUGGER_EVAL_THROW = 1, /**< evaluate expression and throw the result */ 212 JERRY_DEBUGGER_EVAL_ABORT = 2, /**< evaluate expression and abrot with the result */ 213 } jerry_debugger_eval_type_t; 214 215 /** 216 * Subtypes of eval_result. 217 */ 218 typedef enum 219 { 220 JERRY_DEBUGGER_EVAL_OK = 1, /**< eval result, no error */ 221 JERRY_DEBUGGER_EVAL_ERROR = 2, /**< eval result when an error has occurred */ 222 } jerry_debugger_eval_result_type_t; 223 224 /** 225 * Subtypes of output_result. 226 * 227 * Note: 228 * This enum has to be kept in sync with jerry_log_level_t with an offset 229 * of +2. 230 */ 231 typedef enum 232 { 233 JERRY_DEBUGGER_OUTPUT_OK = 1, /**< output result, no error */ 234 JERRY_DEBUGGER_OUTPUT_ERROR = 2, /**< output result, error */ 235 JERRY_DEBUGGER_OUTPUT_WARNING = 3, /**< output result, warning */ 236 JERRY_DEBUGGER_OUTPUT_DEBUG = 4, /**< output result, debug */ 237 JERRY_DEBUGGER_OUTPUT_TRACE = 5, /**< output result, trace */ 238 } jerry_debugger_output_subtype_t; 239 240 /** 241 * Types of scopes. 242 */ 243 typedef enum 244 { 245 JERRY_DEBUGGER_SCOPE_WITH = 1, /**< with */ 246 JERRY_DEBUGGER_SCOPE_LOCAL = 2, /**< local */ 247 JERRY_DEBUGGER_SCOPE_CLOSURE = 3, /**< closure */ 248 JERRY_DEBUGGER_SCOPE_GLOBAL = 4, /**< global */ 249 JERRY_DEBUGGER_SCOPE_NON_CLOSURE = 5 /**< non closure */ 250 } jerry_debugger_scope_chain_type_t; 251 252 /** 253 * Type of scope variables. 254 */ 255 typedef enum 256 { 257 JERRY_DEBUGGER_VALUE_NONE = 1, 258 JERRY_DEBUGGER_VALUE_UNDEFINED = 2, 259 JERRY_DEBUGGER_VALUE_NULL = 3, 260 JERRY_DEBUGGER_VALUE_BOOLEAN = 4, 261 JERRY_DEBUGGER_VALUE_NUMBER = 5, 262 JERRY_DEBUGGER_VALUE_STRING = 6, 263 JERRY_DEBUGGER_VALUE_FUNCTION = 7, 264 JERRY_DEBUGGER_VALUE_ARRAY = 8, 265 JERRY_DEBUGGER_VALUE_OBJECT = 9 266 } jerry_debugger_scope_variable_type_t; 267 268 /** 269 * Byte data for evaluating expressions and receiving client source. 270 */ 271 typedef struct 272 { 273 uint32_t uint8_size; /**< total size of the client source */ 274 uint32_t uint8_offset; /**< current offset in the client source */ 275 } jerry_debugger_uint8_data_t; 276 277 /** 278 * Delayed free of byte code data. 279 */ 280 typedef struct 281 { 282 uint16_t size; /**< size of the byte code header divided by JMEM_ALIGNMENT */ 283 jmem_cpointer_t prev_cp; /**< previous byte code data to be freed */ 284 } jerry_debugger_byte_code_free_t; 285 286 /** 287 * Outgoing message: JerryScript configuration. 288 */ 289 typedef struct 290 { 291 uint8_t type; /**< type of the message */ 292 uint8_t configuration; /**< configuration option bits */ 293 uint8_t version[sizeof (uint32_t)]; /**< debugger version */ 294 uint8_t max_message_size; /**< maximum incoming message size */ 295 uint8_t cpointer_size; /**< size of compressed pointers */ 296 } jerry_debugger_send_configuration_t; 297 298 /** 299 * Outgoing message: message without arguments. 300 */ 301 typedef struct 302 { 303 uint8_t type; /**< type of the message */ 304 } jerry_debugger_send_type_t; 305 306 /** 307 * Incoming message: message without arguments. 308 */ 309 typedef struct 310 { 311 uint8_t type; /**< type of the message */ 312 } jerry_debugger_receive_type_t; 313 314 /** 315 * Outgoing message: string (Source file name or function name). 316 */ 317 typedef struct 318 { 319 uint8_t type; /**< type of the message */ 320 uint8_t string[]; /**< string data */ 321 } jerry_debugger_send_string_t; 322 323 /** 324 * Outgoing message: uint32 value. 325 */ 326 typedef struct 327 { 328 uint8_t type; /**< type of the message */ 329 uint8_t line[sizeof (uint32_t)]; /**< value data */ 330 uint8_t column[sizeof (uint32_t)]; /**< value data */ 331 } jerry_debugger_send_parse_function_t; 332 333 /** 334 * Outgoing message: byte code compressed pointer. 335 */ 336 typedef struct 337 { 338 uint8_t type; /**< type of the message */ 339 uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */ 340 } jerry_debugger_send_byte_code_cp_t; 341 342 /** 343 * Incoming message: byte code compressed pointer. 344 */ 345 typedef struct 346 { 347 uint8_t type; /**< type of the message */ 348 uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */ 349 } jerry_debugger_receive_byte_code_cp_t; 350 351 /** 352 * Incoming message: update (enable/disable) breakpoint status. 353 */ 354 typedef struct 355 { 356 uint8_t type; /**< type of the message */ 357 uint8_t is_set_breakpoint; /**< set or clear breakpoint */ 358 uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */ 359 uint8_t offset[sizeof (uint32_t)]; /**< breakpoint offset */ 360 } jerry_debugger_receive_update_breakpoint_t; 361 362 /** 363 * Outgoing message: send memory statistics 364 */ 365 typedef struct 366 { 367 uint8_t type; /**< type of the message */ 368 uint8_t allocated_bytes[sizeof (uint32_t)]; /**< allocated bytes */ 369 uint8_t byte_code_bytes[sizeof (uint32_t)]; /**< byte code bytes */ 370 uint8_t string_bytes[sizeof (uint32_t)]; /**< string bytes */ 371 uint8_t object_bytes[sizeof (uint32_t)]; /**< object bytes */ 372 uint8_t property_bytes[sizeof (uint32_t)]; /**< property bytes */ 373 } jerry_debugger_send_memstats_t; 374 375 /** 376 * Outgoing message: notify breakpoint hit. 377 */ 378 typedef struct 379 { 380 uint8_t type; /**< type of the message */ 381 uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */ 382 uint8_t offset[sizeof (uint32_t)]; /**< breakpoint offset */ 383 } jerry_debugger_send_breakpoint_hit_t; 384 385 /** 386 * Stack frame descriptor for sending backtrace information. 387 */ 388 typedef struct 389 { 390 uint8_t byte_code_cp[sizeof (jmem_cpointer_t)]; /**< byte code compressed pointer */ 391 uint8_t offset[sizeof (uint32_t)]; /**< last breakpoint offset */ 392 } jerry_debugger_frame_t; 393 394 /** 395 * Outgoing message: backtrace information. 396 */ 397 typedef struct 398 { 399 uint8_t type; /**< type of the message */ 400 jerry_debugger_frame_t frames[]; /**< frames */ 401 } jerry_debugger_send_backtrace_t; 402 403 /** 404 * Outgoing message: scope chain. 405 */ 406 typedef struct 407 { 408 uint8_t type; /**< type of the message */ 409 uint8_t scope_types[]; /**< scope types */ 410 } jerry_debugger_send_scope_chain_t; 411 412 /** 413 * Outgoing message: number of total frames in backtrace. 414 */ 415 typedef struct 416 { 417 uint8_t type; /**< type of the message */ 418 uint8_t frame_count[sizeof (uint32_t)]; /**< total number of frames */ 419 } jerry_debugger_send_backtrace_total_t; 420 421 /** 422 * Incoming message: set behaviour when exception occures. 423 */ 424 typedef struct 425 { 426 uint8_t type; /**< type of the message */ 427 uint8_t enable; /**< non-zero: enable stop at exception */ 428 } jerry_debugger_receive_exception_config_t; 429 430 /** 431 * Incoming message: set parser configuration. 432 */ 433 typedef struct 434 { 435 uint8_t type; /**< type of the message */ 436 uint8_t enable_wait; /**< non-zero: wait after parsing is completed */ 437 } jerry_debugger_receive_parser_config_t; 438 439 /** 440 * Incoming message: get backtrace. 441 */ 442 typedef struct 443 { 444 uint8_t type; /**< type of the message */ 445 uint8_t min_depth[sizeof (uint32_t)]; /**< minimum depth*/ 446 uint8_t max_depth[sizeof (uint32_t)]; /**< maximum depth (0 - unlimited) */ 447 uint8_t get_total_frame_count; /**< non-zero: if total frame count is also requested */ 448 } jerry_debugger_receive_get_backtrace_t; 449 450 /** 451 * Incoming message: first message of evaluating expression. 452 */ 453 typedef struct 454 { 455 uint8_t type; /**< type of the message */ 456 uint8_t eval_size[sizeof (uint32_t)]; /**< total size of the message */ 457 } jerry_debugger_receive_eval_first_t; 458 459 /** 460 * Incoming message: get scope variables 461 */ 462 typedef struct 463 { 464 uint8_t type; /**< type of the message */ 465 uint8_t chain_index[sizeof (uint32_t)]; /**< index element of the scope */ 466 } jerry_debugger_receive_get_scope_variables_t; 467 468 /** 469 * Incoming message: first message of client source. 470 */ 471 typedef struct 472 { 473 uint8_t type; /**< type of the message */ 474 uint8_t code_size[sizeof (uint32_t)]; /**< total size of the message */ 475 } jerry_debugger_receive_client_source_first_t; 476 477 void jerry_debugger_free_unreferenced_byte_code (void); 478 479 bool jerry_debugger_receive (jerry_debugger_uint8_data_t **message_data_p); 480 481 void jerry_debugger_breakpoint_hit (uint8_t message_type); 482 483 void jerry_debugger_send_type (jerry_debugger_header_type_t type); 484 bool jerry_debugger_send_configuration (uint8_t max_message_size); 485 void jerry_debugger_send_data (jerry_debugger_header_type_t type, const void *data, size_t size); 486 bool jerry_debugger_send_string (uint8_t message_type, uint8_t sub_type, const uint8_t *string_p, size_t string_length); 487 bool jerry_debugger_send_function_cp (jerry_debugger_header_type_t type, ecma_compiled_code_t *compiled_code_p); 488 bool jerry_debugger_send_parse_function (uint32_t line, uint32_t column); 489 void jerry_debugger_send_memstats (void); 490 bool jerry_debugger_send_exception_string (ecma_value_t exception_value); 491 492 #endif /* ENABLED (JERRY_DEBUGGER) */ 493 494 #endif /* !DEBUGGER_H */ 495