Skip to content

Commit 6fdea39

Browse files
author
Levente Orban
committed
Add Exception handler to debugger
JerryScript-DCO-1.0-Signed-off-by: Levente Orban orbanl@inf.u-szeged.hu
1 parent f501931 commit 6fdea39

File tree

10 files changed

+278
-108
lines changed

10 files changed

+278
-108
lines changed

jerry-core/debugger/jerry-debugger-ws.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,7 @@ jerry_debugger_close_connection_tcp (bool log_error) /**< log error */
6969
{
7070
JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
7171

72-
uint8_t debugger_flags = JERRY_CONTEXT (debugger_flags);
73-
debugger_flags = (uint8_t) (debugger_flags & ~(JERRY_DEBUGGER_CONNECTED | JERRY_DEBUGGER_VM_STOP));
74-
debugger_flags = (uint8_t) (debugger_flags | JERRY_DEBUGGER_VM_IGNORE);
75-
JERRY_CONTEXT (debugger_flags) = debugger_flags;
72+
JERRY_CONTEXT (debugger_flags) = (uint8_t) JERRY_DEBUGGER_VM_IGNORE;
7673

7774
if (log_error)
7875
{

jerry-core/debugger/jerry-debugger.c

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,27 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer the the rec
391391
return true;
392392
}
393393

394+
case JERRY_DEBUGGER_EXCEPTION_CONFIG:
395+
{
396+
JERRY_DEBUGGER_CHECK_PACKET_SIZE (jerry_debugger_receive_exception_config_t);
397+
JERRY_DEBUGGER_RECEIVE_BUFFER_AS (jerry_debugger_receive_exception_config_t, exception_config_p);
398+
399+
if (exception_config_p->enable == 0)
400+
{
401+
JERRY_CONTEXT (debugger_flags) = (uint8_t) (JERRY_CONTEXT (debugger_flags)
402+
| JERRY_DEBUGGER_VM_IGNORE_EXCEPTION);
403+
jerry_port_log (JERRY_LOG_LEVEL_DEBUG, "Stop at exception disabled\n");
404+
}
405+
else
406+
{
407+
JERRY_CONTEXT (debugger_flags) = (uint8_t) (JERRY_CONTEXT (debugger_flags)
408+
& ~JERRY_DEBUGGER_VM_IGNORE_EXCEPTION);
409+
jerry_port_log (JERRY_LOG_LEVEL_DEBUG, "Stop at exception enabled\n");
410+
}
411+
412+
return true;
413+
}
414+
394415
case JERRY_DEBUGGER_EVAL:
395416
{
396417
if (message_size < sizeof (jerry_debugger_receive_eval_first_t) + 1)
@@ -450,15 +471,15 @@ jerry_debugger_process_message (uint8_t *recv_buffer_p, /**< pointer the the rec
450471
* Tell the client that a breakpoint has been hit and wait for further debugger commands.
451472
*/
452473
void
453-
jerry_debugger_breakpoint_hit (void)
474+
jerry_debugger_breakpoint_hit (uint8_t message_type) /**< message type */
454475
{
455476
JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
456477

457478
JERRY_DEBUGGER_SEND_BUFFER_AS (jerry_debugger_send_breakpoint_hit_t, breakpoint_hit_p);
458479

459480
JERRY_DEBUGGER_INIT_SEND_MESSAGE (breakpoint_hit_p);
460481
JERRY_DEBUGGER_SET_SEND_MESSAGE_SIZE_FROM_TYPE (breakpoint_hit_p, jerry_debugger_send_breakpoint_hit_t);
461-
breakpoint_hit_p->type = (uint8_t) JERRY_DEBUGGER_BREAKPOINT_HIT;
482+
breakpoint_hit_p->type = message_type;
462483

463484
vm_frame_ctx_t *frame_ctx_p = JERRY_CONTEXT (vm_top_context_p);
464485

jerry-core/debugger/jerry-debugger.h

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ typedef enum
7777
JERRY_DEBUGGER_BREAKPOINT_MODE = 1u << 1, /**< debugger waiting at a breakpoint */
7878
JERRY_DEBUGGER_VM_STOP = 1u << 2, /**< stop at the next breakpoint regardless it is enabled */
7979
JERRY_DEBUGGER_VM_IGNORE = 1u << 3, /**< ignore all breakpoints */
80+
JERRY_DEBUGGER_VM_IGNORE_EXCEPTION = 1u << 4, /**< debugger stop at an exception */
8081
} jerry_debugger_flags_t;
8182

8283
/**
@@ -99,29 +100,31 @@ typedef enum
99100
JERRY_DEBUGGER_FUNCTION_NAME_END = 12, /**< function name last fragment */
100101
JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 13, /**< invalidate byte code compressed pointer */
101102
JERRY_DEBUGGER_BREAKPOINT_HIT = 14, /**< notify breakpoint hit */
102-
JERRY_DEBUGGER_BACKTRACE = 15, /**< backtrace data */
103-
JERRY_DEBUGGER_BACKTRACE_END = 16, /**< last backtrace data */
104-
JERRY_DEBUGGER_EVAL_RESULT = 17, /**< eval result */
105-
JERRY_DEBUGGER_EVAL_RESULT_END = 18, /**< last part of eval result */
106-
JERRY_DEBUGGER_EVAL_ERROR = 19, /**< eval result when an error is occured */
107-
JERRY_DEBUGGER_EVAL_ERROR_END = 20, /**< last part of eval result when an error is occured */
103+
JERRY_DEBUGGER_EXCEPTION_HIT = 15, /**< notify exception hit */
104+
JERRY_DEBUGGER_BACKTRACE = 16, /**< backtrace data */
105+
JERRY_DEBUGGER_BACKTRACE_END = 17, /**< last backtrace data */
106+
JERRY_DEBUGGER_EVAL_RESULT = 18, /**< eval result */
107+
JERRY_DEBUGGER_EVAL_RESULT_END = 19, /**< last part of eval result */
108+
JERRY_DEBUGGER_EVAL_ERROR = 20, /**< eval result when an error is occured */
109+
JERRY_DEBUGGER_EVAL_ERROR_END = 21, /**< last part of eval result when an error is occured */
108110

109111
/* Messages sent by the client to server. */
110112

111113
/* The following messages are accepted in both run and breakpoint modes. */
112114
JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1, /**< free byte code compressed pointer */
113115
JERRY_DEBUGGER_UPDATE_BREAKPOINT = 2, /**< update breakpoint status */
114-
JERRY_DEBUGGER_STOP = 3, /**< stop execution */
116+
JERRY_DEBUGGER_EXCEPTION_CONFIG = 3, /**< exception handler config */
117+
JERRY_DEBUGGER_STOP = 4, /**< stop execution */
115118
/* The following messages are only available in breakpoint
116119
* mode and they switch the engine to run mode. */
117-
JERRY_DEBUGGER_CONTINUE = 4, /**< continue execution */
118-
JERRY_DEBUGGER_STEP = 5, /**< next breakpoint, step into functions */
119-
JERRY_DEBUGGER_NEXT = 6, /**< next breakpoint in the same context */
120+
JERRY_DEBUGGER_CONTINUE = 5, /**< continue execution */
121+
JERRY_DEBUGGER_STEP = 6, /**< next breakpoint, step into functions */
122+
JERRY_DEBUGGER_NEXT = 7, /**< next breakpoint in the same context */
120123
/* The following messages are only available in breakpoint
121124
* mode and this mode is kept after the message is processed. */
122-
JERRY_DEBUGGER_GET_BACKTRACE = 7, /**< get backtrace */
123-
JERRY_DEBUGGER_EVAL = 8, /**< first message of evaluating a string */
124-
JERRY_DEBUGGER_EVAL_PART = 9, /**< next message of evaluating a string */
125+
JERRY_DEBUGGER_GET_BACKTRACE = 8, /**< get backtrace */
126+
JERRY_DEBUGGER_EVAL = 9, /**< first message of evaluating a string */
127+
JERRY_DEBUGGER_EVAL_PART = 10, /**< next message of evaluating a string */
125128
} jerry_debugger_header_type_t;
126129

127130
/**
@@ -243,6 +246,12 @@ typedef struct
243246
jerry_debugger_frame_t frames[JERRY_DEBUGGER_SEND_MAX (jerry_debugger_frame_t)]; /**< frames */
244247
} jerry_debugger_send_backtrace_t;
245248

249+
typedef struct
250+
{
251+
uint8_t type; /**< type of the message */
252+
uint8_t enable; /**< non-zero: enable stop at exception */
253+
} jerry_debugger_receive_exception_config_t;
254+
246255
/**
247256
* Incoming message: get backtrace.
248257
*/
@@ -282,7 +291,7 @@ void jerry_debugger_free_unreferenced_byte_code (void);
282291

283292
bool jerry_debugger_process_message (uint8_t *recv_buffer_p, uint32_t message_size,
284293
bool *resume_exec_p, uint8_t *expected_message_p, void **message_data_p);
285-
void jerry_debugger_breakpoint_hit (void);
294+
void jerry_debugger_breakpoint_hit (uint8_t message_type);
286295

287296
void jerry_debugger_send_type (jerry_debugger_header_type_t type);
288297
bool jerry_debugger_send_configuration (uint8_t max_message_size);

jerry-core/vm/vm.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2338,7 +2338,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
23382338

23392339
frame_ctx_p->byte_code_p = byte_code_start_p;
23402340

2341-
jerry_debugger_breakpoint_hit ();
2341+
jerry_debugger_breakpoint_hit (JERRY_DEBUGGER_BREAKPOINT_HIT);
23422342
#endif /* JERRY_DEBUGGER */
23432343
continue;
23442344
}
@@ -2360,7 +2360,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
23602360
&& (JERRY_CONTEXT (debugger_stop_context) == NULL
23612361
|| JERRY_CONTEXT (debugger_stop_context) == JERRY_CONTEXT (vm_top_context_p)))
23622362
{
2363-
jerry_debugger_breakpoint_hit ();
2363+
jerry_debugger_breakpoint_hit (JERRY_DEBUGGER_BREAKPOINT_HIT);
23642364
continue;
23652365
}
23662366

@@ -2380,7 +2380,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
23802380
if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_VM_STOP)
23812381
{
23822382
JERRY_ASSERT (JERRY_CONTEXT (debugger_stop_context) == NULL);
2383-
jerry_debugger_breakpoint_hit ();
2383+
jerry_debugger_breakpoint_hit (JERRY_DEBUGGER_BREAKPOINT_HIT);
23842384
}
23852385
#endif /* JERRY_DEBUGGER */
23862386
continue;
@@ -2515,6 +2515,15 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
25152515
}
25162516

25172517
stack_top_p = frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth;
2518+
#ifdef JERRY_DEBUGGER
2519+
JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
2520+
2521+
if (!(frame_ctx_p->bytecode_header_p->status_flags & CBC_CODE_FLAGS_DEBUGGER_IGNORE)
2522+
&& !(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_VM_IGNORE_EXCEPTION))
2523+
{
2524+
jerry_debugger_breakpoint_hit (JERRY_DEBUGGER_EXCEPTION_HIT);
2525+
}
2526+
#endif /* JERRY_DEBUGGER */
25182527
}
25192528

25202529
JERRY_ASSERT (frame_ctx_p->registers_p + register_end + frame_ctx_p->context_depth == stack_top_p);

jerry-debugger/jerry-client-ws.html

Lines changed: 101 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,24 @@ <h2>JerryScript HTML (WebSocket) Debugger Client</h2>
4242
var JERRY_DEBUGGER_FUNCTION_NAME_END = 12;
4343
var JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP = 13;
4444
var JERRY_DEBUGGER_BREAKPOINT_HIT = 14;
45-
var JERRY_DEBUGGER_BACKTRACE = 15;
46-
var JERRY_DEBUGGER_BACKTRACE_END = 16;
47-
var JERRY_DEBUGGER_EVAL_RESULT = 17;
48-
var JERRY_DEBUGGER_EVAL_RESULT_END = 18;
49-
var JERRY_DEBUGGER_EVAL_ERROR = 19;
50-
var JERRY_DEBUGGER_EVAL_ERROR_END = 20;
45+
var JERRY_DEBUGGER_EXCEPTION_HIT = 15;
46+
var JERRY_DEBUGGER_BACKTRACE = 16;
47+
var JERRY_DEBUGGER_BACKTRACE_END = 17;
48+
var JERRY_DEBUGGER_EVAL_RESULT = 18;
49+
var JERRY_DEBUGGER_EVAL_RESULT_END = 19;
50+
var JERRY_DEBUGGER_EVAL_ERROR = 20;
51+
var JERRY_DEBUGGER_EVAL_ERROR_END = 21;
5152

5253
var JERRY_DEBUGGER_FREE_BYTE_CODE_CP = 1;
5354
var JERRY_DEBUGGER_UPDATE_BREAKPOINT = 2;
54-
var JERRY_DEBUGGER_STOP = 3;
55-
var JERRY_DEBUGGER_CONTINUE = 4;
56-
var JERRY_DEBUGGER_STEP = 5;
57-
var JERRY_DEBUGGER_NEXT = 6;
58-
var JERRY_DEBUGGER_GET_BACKTRACE = 7;
59-
var JERRY_DEBUGGER_EVAL = 8;
60-
var JERRY_DEBUGGER_EVAL_PART = 9;
55+
var JERRY_DEBUGGER_EXCEPTION_CONFIG = 3;
56+
var JERRY_DEBUGGER_STOP = 4;
57+
var JERRY_DEBUGGER_CONTINUE = 5;
58+
var JERRY_DEBUGGER_STEP = 6;
59+
var JERRY_DEBUGGER_NEXT = 7;
60+
var JERRY_DEBUGGER_GET_BACKTRACE = 8;
61+
var JERRY_DEBUGGER_EVAL = 9;
62+
var JERRY_DEBUGGER_EVAL_PART = 10;
6163

6264
var textBox = document.getElementById("log");
6365
var commandBox = document.getElementById("command");
@@ -495,6 +497,41 @@ <h2>JerryScript HTML (WebSocket) Debugger Client</h2>
495497
socket.send(message);
496498
}
497499

500+
function getBreakpoint(breakpointData)
501+
{
502+
var returnValue = {};
503+
var func = functions[breakpointData[0]];
504+
var offset = breakpointData[1];
505+
506+
if (offset in functions)
507+
{
508+
returnValue.breakpoint = func.offsets[offset];
509+
returnValue.at = true;
510+
return returnValue;
511+
}
512+
513+
if (offset < functions.firstBreakpointOffset)
514+
{
515+
returnValue.breakpoint = func.offsets[firstBreakpointOffset];
516+
returnValue.at = true;
517+
return returnValue;
518+
}
519+
520+
nearest_offset = -1;
521+
522+
for (var current_offset in func.offsets)
523+
{
524+
if ((current_offset <= offset) && (current_offset > nearest_offset))
525+
{
526+
nearest_offset = current_offset;
527+
}
528+
}
529+
530+
returnValue.breakpoint = func.offsets[nearest_offset];
531+
returnValue.at = false;
532+
return returnValue;
533+
}
534+
498535
this.encodeMessage = encodeMessage;
499536

500537
function ParseSource()
@@ -606,6 +643,7 @@ <h2>JerryScript HTML (WebSocket) Debugger Client</h2>
606643
offsets = {}
607644

608645
func.firstBreakpointLine = func.lines[0];
646+
func.firstBreakpointOffset = func.offsets[0];
609647

610648
for (var i = 0; i < func.lines.length; i++)
611649
{
@@ -729,20 +767,29 @@ <h2>JerryScript HTML (WebSocket) Debugger Client</h2>
729767
}
730768

731769
case JERRY_DEBUGGER_BREAKPOINT_HIT:
770+
case JERRY_DEBUGGER_EXCEPTION_HIT:
732771
{
733-
var breakpoint = decodeMessage("CI", message, 1);
772+
var breakpointData = decodeMessage("CI", message, 1);
773+
var breakpointRef = getBreakpoint(breakpointData);
774+
var breakpoint = breakpointRef.breakpoint;
734775

735-
breakpoint = functions[breakpoint[0]].offsets[breakpoint[1]];
776+
if (message[0] == JERRY_DEBUGGER_EXCEPTION_HIT)
777+
{
778+
appendLog("Exception throw detected (to disable automatic stop type exception 0)");
779+
}
736780

737781
lastBreakpointHit = breakpoint;
738782

739-
breakpointIndex = "";
740-
if (breakpoint.activeIndex >= 0)
783+
var breakpointInfo = "";
784+
if (breakpoint.offset.activeIndex >= 0)
741785
{
742-
breakpointIndex = "breakpoint:" + breakpoint.activeIndex + " ";
786+
breakpointInfo = " breakpoint:" + breakpoint.offset.activeIndex + " ";
743787
}
744788

745-
appendLog("Stopped at " + breakpointIndex + breakpointToString(breakpoint));
789+
appendLog("Stopped "
790+
+ (breakpoint.at ? "at " : "around ")
791+
+ breakpointInfo
792+
+ breakpointToString(breakpoint));
746793
return;
747794
}
748795

@@ -751,31 +798,14 @@ <h2>JerryScript HTML (WebSocket) Debugger Client</h2>
751798
{
752799
for (var i = 1; i < message.byteLength; i += cpointerSize + 4)
753800
{
754-
var breakpoint = decodeMessage("CI", message, i);
755-
var func = functions[breakpoint[0]];
756-
var best_offset = -1;
801+
var breakpointData = decodeMessage("CI", message, i);
757802

758-
for (var offset in func.offsets)
759-
{
760-
if (offset <= breakpoint[1] && offset > best_offset)
761-
{
762-
best_offset = offset;
763-
}
764-
}
803+
breakpoint = getBreakpoint(breakpointData).breakpoint;
765804

766-
if (best_offset >= 0)
767-
{
768-
breakpoint = func.offsets[best_offset];
769-
appendLog(" frame " + backtraceFrame + ": " + breakpointToString(breakpoint));
770-
}
771-
else if (func.name)
772-
{
773-
appendLog(" frame " + backtraceFrame + ": " + func.name + "()");
774-
}
775-
else
776-
{
777-
appendLog(" frame " + backtraceFrame + ": <unknown>()");
778-
}
805+
appendLog(" frame "
806+
+ backtraceFrame
807+
+ ": "
808+
+ breakpointToString(breakpoint));
779809

780810
++backtraceFrame;
781811
}
@@ -873,6 +903,31 @@ <h2>JerryScript HTML (WebSocket) Debugger Client</h2>
873903
}
874904
}
875905

906+
this.sendExceptionConfig = function(enable)
907+
{
908+
if (enable == "")
909+
{
910+
appendLog("Argument required");
911+
return;
912+
}
913+
914+
if (enable == 1)
915+
{
916+
appendLog("Stop at exception enabled");
917+
}
918+
else if (enable == 0)
919+
{
920+
appendLog("Stop at exception disabled");
921+
}
922+
else
923+
{
924+
appendLog("Invalid input. Usage 1: [Enable] or 0: [Disable].");
925+
return;
926+
}
927+
928+
encodeMessage("BB", [ JERRY_DEBUGGER_EXCEPTION_CONFIG, enable ]);
929+
}
930+
876931
this.deleteBreakpoint = function(index)
877932
{
878933
breakpoint = activeBreakpoints[index];
@@ -1178,6 +1233,10 @@ <h2>JerryScript HTML (WebSocket) Debugger Client</h2>
11781233
debuggerObj.sendGetBacktrace(max_depth);
11791234
break;
11801235

1236+
case "exception":
1237+
debuggerObj.sendExceptionConfig(args[2]);
1238+
break;
1239+
11811240
case "src":
11821241
debuggerObj.printSource();
11831242
break;

0 commit comments

Comments
 (0)