From dbfb0170c1ea7fd7955c4c8b1fffeb1ebb20454c Mon Sep 17 00:00:00 2001 From: Daniel Balla Date: Thu, 13 Jul 2017 10:26:14 +0200 Subject: [PATCH] JerryDebugger breakpoint system rework (#1908) Reworking the python JerryDebugger breakpoint system. JerryScript-DCO-1.0-Signed-off-by: Daniel Balla dballa@inf.u-szeged.hu --- jerry-debugger/jerry-client-ws.py | 161 +++++++++++------- tests/debugger/do_break.expected | 16 +- tests/debugger/do_delete.cmd | 2 + tests/debugger/do_delete.expected | 22 ++- tests/debugger/do_delete_all.cmd | 4 + tests/debugger/do_delete_all.expected | 16 +- tests/debugger/do_help.expected | 7 +- tests/debugger/do_list.expected | 5 +- tests/debugger/do_pending_breakpoints.cmd | 5 +- .../debugger/do_pending_breakpoints.expected | 15 +- tests/debugger/do_pending_list.cmd | 6 - tests/debugger/do_pending_list.expected | 18 -- tests/debugger/do_pending_list.js | 20 --- 13 files changed, 159 insertions(+), 138 deletions(-) delete mode 100644 tests/debugger/do_pending_list.cmd delete mode 100644 tests/debugger/do_pending_list.expected delete mode 100644 tests/debugger/do_pending_list.js diff --git a/jerry-debugger/jerry-client-ws.py b/jerry-debugger/jerry-client-ws.py index 3b00b868c..45d1221e7 100755 --- a/jerry-debugger/jerry-client-ws.py +++ b/jerry-debugger/jerry-client-ws.py @@ -117,6 +117,23 @@ class JerryBreakpoint(object): return ("Breakpoint(line:%d, offset:%d, active_index:%d)" % (self.line, self.offset, self.active_index)) +class JerryPendingBreakpoint(object): + def __init__(self, line=None, source_name=None, function=None): + self.function = function + self.line = line + self.source_name = source_name + + self.index = -1 + + def __str__(self): + result = self.source_name or "" + if self.line: + result += ":%d" % (self.line) + else: + result += "%s()" % (self.function) + return result + + class JerryFunction(object): @@ -188,17 +205,10 @@ class DebuggerPrompt(Cmd): if args == "": print("Error: Breakpoint index expected") else: - set_breakpoint(self.debugger, False, args) + set_breakpoint(self.debugger, args) do_b = do_break - def do_fbreak(self, args): - """ Insert breakpoints on the given lines or functions, if not found add the pending list """ - if args == "": - print("Error: Breakpoint index expected") - else: - set_breakpoint(self.debugger, True, args) - def exec_command(self, args, command_id): self.stop = True if args != "": @@ -231,26 +241,32 @@ class DebuggerPrompt(Cmd): do_n = do_next def do_list(self, args): - """ Lists the available breakpoints, use 'pending' to list all the available pending breakpoints """ - if args == "pending": - for index, breakpoint in enumerate(self.debugger.pending_breakpoint_list): - print("%d: %s" % (index, breakpoint)) - return + """ Lists the available breakpoints """ + if self.debugger.active_breakpoint_list: + print("=== %sActive breakpoints %s ===" % (self.debugger.green_bg, self.debugger.nocolor)) + for breakpoint in self.debugger.active_breakpoint_list.values(): + print(" %d: %s" % (breakpoint.active_index, breakpoint)) - for breakpoint in self.debugger.active_breakpoint_list.values(): - print("%d: %s" % (breakpoint.active_index, breakpoint)) + if self.debugger.pending_breakpoint_list: + print("=== %sPending breakpoints%s ===" % (self.debugger.yellow_bg, self.debugger.nocolor)) + for breakpoint in self.debugger.pending_breakpoint_list.values(): + print(" %d: %s (pending)" % (breakpoint.index, breakpoint)) + + if not self.debugger.active_breakpoint_list and not self.debugger.pending_breakpoint_list: + print("No breakpoints") def do_delete(self, args): - """ Delete the given breakpoint, use 'delete all' to clear the breakpoints in the whole program""" + """ Delete the given breakpoint, use 'delete all|active|pending' to clear all the given breakpoints """ if not args: print("Error: Breakpoint index expected") return elif args == "all": - for i in self.debugger.active_breakpoint_list.values(): - breakpoint = self.debugger.active_breakpoint_list[i.active_index] - del self.debugger.active_breakpoint_list[i.active_index] - breakpoint.active_index = -1 - self.debugger.send_breakpoint(breakpoint) + self.debugger.delete_active() + self.debugger.delete_pending() + elif args == "pending": + self.debugger.delete_pending() + elif args == "active": + self.debugger.delete_active() else: try: breakpoint_index = int(args) @@ -263,31 +279,11 @@ class DebuggerPrompt(Cmd): del self.debugger.active_breakpoint_list[breakpoint_index] breakpoint.active_index = -1 self.debugger.send_breakpoint(breakpoint) + elif breakpoint_index in self.debugger.pending_breakpoint_list: + del self.debugger.pending_breakpoint_list[breakpoint_index] else: print("Error: Breakpoint %d not found" % (breakpoint_index)) - def do_pendingdel(self, args): - """ Delete the given pending breakpoints from the list """ - if not args: - print("Error: Pending breakpoint index expected") - return - - else: - try: - breakpoint_index = int(args) - except ValueError as val_errno: - print("Error: Integer number expectes, %s" % (val_errno)) - return - - if breakpoint_index <= len(self.debugger.pending_breakpoint_list): - try: - del self.debugger.pending_breakpoint_list[breakpoint_index] - except IndexError as index_errno: - print("Error: Index not found, %s" % (index_errno)) - return - else: - print("Error: Pending breakpoint %d not found" % (breakpoint_index)) - def exec_backtrace(self, args): max_depth = 0 @@ -470,12 +466,15 @@ class JerryDebugger(object): self.last_breakpoint_hit = None self.next_breakpoint_index = 0 self.active_breakpoint_list = {} - self.pending_breakpoint_list = [] + self.pending_breakpoint_list = {} self.line_list = Multimap() self.display = 0 self.default_viewrange = 3 self.green = '' self.red = '' + self.yellow = '' + self.green_bg = '' + self.yellow_bg = '' self.nocolor = '' self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client_socket.connect((self.host, self.port)) @@ -560,6 +559,25 @@ class JerryDebugger(object): message = message[bytes_send:] size -= bytes_send + def delete_active(self): + for i in self.active_breakpoint_list.values(): + breakpoint = self.active_breakpoint_list[i.active_index] + del self.active_breakpoint_list[i.active_index] + breakpoint.active_index = -1 + self.send_breakpoint(breakpoint) + + def delete_pending(self): + self.pending_breakpoint_list.clear() + + def breakpoint_pending_exists(self, breakpoint): + for existing_bp in self.pending_breakpoint_list.values(): + if (breakpoint.line and existing_bp.source_name == breakpoint.source_name and \ + existing_bp.line == breakpoint.line) \ + or (not breakpoint.line and existing_bp.function == breakpoint.function): + return True + + return False + def send_breakpoint(self, breakpoint): message = struct.pack(self.byte_order + "BBIBB" + self.cp_format + self.idx_format, WEBSOCKET_BINARY_FRAME | WEBSOCKET_FIN_BIT, @@ -601,6 +619,9 @@ class JerryDebugger(object): self.green = '\033[92m' self.nocolor = '\033[0m' self.red = '\033[31m' + self.yellow = '\033[93m' + self.green_bg = '\033[42m' + self.yellow_bg = '\033[43m' def get_message(self, blocking): # Connection was closed @@ -756,9 +777,12 @@ def parse_source(debugger, data): logging.debug("Pending breakpoints list: %s", debugger.pending_breakpoint_list) for breakpoint in debugger.pending_breakpoint_list: - if isinstance(breakpoint, int): - breakpoint = source_code_name + ":" + str(breakpoint) - set_breakpoint(debugger, False, breakpoint) + if debugger.pending_breakpoint_list[breakpoint].line: + breakpoint = debugger.pending_breakpoint_list[breakpoint].source_name + ":" \ + + str(debugger.pending_breakpoint_list[breakpoint].line) + else: + breakpoint = debugger.pending_breakpoint_list[breakpoint].function + set_breakpoint(debugger, breakpoint) else: logging.debug("No pending breakpoints") @@ -794,7 +818,8 @@ def print_source(debugger, line_num): for i in range(start, end): if i == last_bp.line - 1: - print("%s%4d%s %s>%s %s" % (debugger.green, i + 1, debugger.nocolor, debugger.red, debugger.nocolor, lines[i])) + print("%s%4d%s %s>%s %s" % (debugger.green, i + 1, debugger.nocolor, debugger.red, \ + debugger.nocolor, lines[i])) else: print("%s%4d%s %s" % (debugger.green, i + 1, debugger.nocolor, lines[i])) @@ -818,25 +843,34 @@ def release_function(debugger, data): def enable_breakpoint(debugger, breakpoint): - if breakpoint.active_index < 0: - debugger.next_breakpoint_index += 1 + if isinstance(breakpoint, JerryPendingBreakpoint): + if not debugger.breakpoint_pending_exists(breakpoint): + debugger.next_breakpoint_index += 1 + breakpoint.index = debugger.next_breakpoint_index + debugger.pending_breakpoint_list[debugger.next_breakpoint_index] = breakpoint + print("%sPending breakpoint%s at %s" % (debugger.yellow, debugger.nocolor, breakpoint)) + else: + print("%sPending breakpoint%s already exists" % (debugger.yellow, debugger.nocolor)) - debugger.active_breakpoint_list[debugger.next_breakpoint_index] = breakpoint - breakpoint.active_index = debugger.next_breakpoint_index - debugger.send_breakpoint(breakpoint) + else: + if breakpoint.active_index < 0: + debugger.next_breakpoint_index += 1 + debugger.active_breakpoint_list[debugger.next_breakpoint_index] = breakpoint + breakpoint.active_index = debugger.next_breakpoint_index + debugger.send_breakpoint(breakpoint) - print ("Breakpoint %d at %s" % (breakpoint.active_index, breakpoint)) + print("%sBreakpoint %d %sat %s" % (debugger.green, breakpoint.active_index, debugger.nocolor, breakpoint)) -def set_breakpoint(debugger, pending, string): +def set_breakpoint(debugger, string): line = re.match("(.*):(\\d+)$", string) found = False if line: source_name = line.group(1) - line = int(line.group(2)) + new_line = int(line.group(2)) - for breakpoint in debugger.line_list.get(line): + for breakpoint in debugger.line_list.get(new_line): func_source = breakpoint.function.source_name if (source_name == func_source or func_source.endswith("/" + source_name) or @@ -852,13 +886,16 @@ def set_breakpoint(debugger, pending, string): found = True if not found: - print("Breakpoint not found") - if pending: + print("No breakpoint found, do you want to add a %spending breakpoint%s? (y or [n])" % \ + (debugger.yellow, debugger.nocolor)) + ans = sys.stdin.readline() + if ans in ['yes\n', 'y\n']: if line: - debugger.pending_breakpoint_list.append(line) + breakpoint = JerryPendingBreakpoint(int(line.group(2)), line.group(1)) else: - debugger.pending_breakpoint_list.append(string) - print ("Pending breakpoint added") + breakpoint = JerryPendingBreakpoint(function=string) + enable_breakpoint(debugger, breakpoint) + return diff --git a/tests/debugger/do_break.expected b/tests/debugger/do_break.expected index c78624599..178285196 100644 --- a/tests/debugger/do_break.expected +++ b/tests/debugger/do_break.expected @@ -8,17 +8,19 @@ Breakpoint 2 at tests/debugger/do_break.js:36 (in test() at line:20, col:1) Breakpoint 3 at tests/debugger/do_break.js:33 (in f() at line:31, col:3) Breakpoint 4 at tests/debugger/do_break.js:45 (in f() at line:43, col:1) (jerry-debugger) list -1: tests/debugger/do_break.js:51 -2: tests/debugger/do_break.js:36 (in test() at line:20, col:1) -3: tests/debugger/do_break.js:33 (in f() at line:31, col:3) -4: tests/debugger/do_break.js:45 (in f() at line:43, col:1) +=== Active breakpoints === + 1: tests/debugger/do_break.js:51 + 2: tests/debugger/do_break.js:36 (in test() at line:20, col:1) + 3: tests/debugger/do_break.js:33 (in f() at line:31, col:3) + 4: tests/debugger/do_break.js:45 (in f() at line:43, col:1) (jerry-debugger) c Stopped at breakpoint:1 tests/debugger/do_break.js:51 (jerry-debugger) delete 1 (jerry-debugger) list -2: tests/debugger/do_break.js:36 (in test() at line:20, col:1) -3: tests/debugger/do_break.js:33 (in f() at line:31, col:3) -4: tests/debugger/do_break.js:45 (in f() at line:43, col:1) +=== Active breakpoints === + 2: tests/debugger/do_break.js:36 (in test() at line:20, col:1) + 3: tests/debugger/do_break.js:33 (in f() at line:31, col:3) + 4: tests/debugger/do_break.js:45 (in f() at line:43, col:1) (jerry-debugger) c Stopped at breakpoint:2 tests/debugger/do_break.js:36 (in test() at line:20, col:1) (jerry-debugger) continue diff --git a/tests/debugger/do_delete.cmd b/tests/debugger/do_delete.cmd index f9f2f0db0..974c7c536 100644 --- a/tests/debugger/do_delete.cmd +++ b/tests/debugger/do_delete.cmd @@ -1,6 +1,7 @@ next b do_delete.js:17 b do_delete.js:21 +y b do_delete.js:19 b do_delete.js:18 list @@ -8,3 +9,4 @@ delete 2 delete 3 list c +c diff --git a/tests/debugger/do_delete.expected b/tests/debugger/do_delete.expected index 261bcb6c2..68644446c 100644 --- a/tests/debugger/do_delete.expected +++ b/tests/debugger/do_delete.expected @@ -5,17 +5,25 @@ Stopped at tests/debugger/do_delete.js:17 (jerry-debugger) b do_delete.js:17 Breakpoint 1 at tests/debugger/do_delete.js:17 (jerry-debugger) b do_delete.js:21 -Breakpoint not found +No breakpoint found, do you want to add a pending breakpoint? (y or [n]) +Pending breakpoint at do_delete.js:21 (jerry-debugger) b do_delete.js:19 -Breakpoint 2 at tests/debugger/do_delete.js:19 +Breakpoint 3 at tests/debugger/do_delete.js:19 (jerry-debugger) b do_delete.js:18 -Breakpoint 3 at tests/debugger/do_delete.js:18 +Breakpoint 4 at tests/debugger/do_delete.js:18 (jerry-debugger) list -1: tests/debugger/do_delete.js:17 -2: tests/debugger/do_delete.js:19 -3: tests/debugger/do_delete.js:18 +=== Active breakpoints === + 1: tests/debugger/do_delete.js:17 + 3: tests/debugger/do_delete.js:19 + 4: tests/debugger/do_delete.js:18 +=== Pending breakpoints === + 2: do_delete.js:21 (pending) (jerry-debugger) delete 2 (jerry-debugger) delete 3 (jerry-debugger) list -1: tests/debugger/do_delete.js:17 +=== Active breakpoints === + 1: tests/debugger/do_delete.js:17 + 4: tests/debugger/do_delete.js:18 +(jerry-debugger) c +Stopped at breakpoint:4 tests/debugger/do_delete.js:18 (jerry-debugger) c diff --git a/tests/debugger/do_delete_all.cmd b/tests/debugger/do_delete_all.cmd index 226009da3..224ee778a 100644 --- a/tests/debugger/do_delete_all.cmd +++ b/tests/debugger/do_delete_all.cmd @@ -1,6 +1,10 @@ break do_delete_all.js:17 b do_delete_all.js:18 b do_delete_all.js:21 +b do_delete_all:350 +y +b do_delete_all:37 +y list delete all next diff --git a/tests/debugger/do_delete_all.expected b/tests/debugger/do_delete_all.expected index e958bdba9..3d80eb74f 100644 --- a/tests/debugger/do_delete_all.expected +++ b/tests/debugger/do_delete_all.expected @@ -6,10 +6,20 @@ Breakpoint 1 at tests/debugger/do_delete_all.js:17 Breakpoint 2 at tests/debugger/do_delete_all.js:18 (jerry-debugger) b do_delete_all.js:21 Breakpoint 3 at tests/debugger/do_delete_all.js:21 (in delete_test() at line:20, col:1) +(jerry-debugger) b do_delete_all:350 +No breakpoint found, do you want to add a pending breakpoint? (y or [n]) +Pending breakpoint at do_delete_all:350 +(jerry-debugger) b do_delete_all:37 +No breakpoint found, do you want to add a pending breakpoint? (y or [n]) +Pending breakpoint at do_delete_all:37 (jerry-debugger) list -1: tests/debugger/do_delete_all.js:17 -2: tests/debugger/do_delete_all.js:18 -3: tests/debugger/do_delete_all.js:21 (in delete_test() at line:20, col:1) +=== Active breakpoints === + 1: tests/debugger/do_delete_all.js:17 + 2: tests/debugger/do_delete_all.js:18 + 3: tests/debugger/do_delete_all.js:21 (in delete_test() at line:20, col:1) +=== Pending breakpoints === + 4: do_delete_all:350 (pending) + 5: do_delete_all:37 (pending) (jerry-debugger) delete all (jerry-debugger) next Stopped at tests/debugger/do_delete_all.js:16 diff --git a/tests/debugger/do_help.expected b/tests/debugger/do_help.expected index b8cf6c302..4a8947406 100644 --- a/tests/debugger/do_help.expected +++ b/tests/debugger/do_help.expected @@ -4,9 +4,8 @@ Stopped at tests/debugger/do_help.js:15 Documented commands (type help ): ======================================== -b c dump fbreak ms quit step -backtrace continue e help n s -break delete eval list next source -bt display exception memstats pendingdel src +b bt delete e help ms quit src +backtrace c display eval list n s step +break continue dump exception memstats next source (jerry-debugger) quit diff --git a/tests/debugger/do_list.expected b/tests/debugger/do_list.expected index 5425332eb..d64f4c995 100644 --- a/tests/debugger/do_list.expected +++ b/tests/debugger/do_list.expected @@ -5,6 +5,7 @@ Breakpoint 1 at tests/debugger/do_list.js:18 (jerry-debugger) b do_list.js:19 Breakpoint 2 at tests/debugger/do_list.js:19 (jerry-debugger) list -1: tests/debugger/do_list.js:18 -2: tests/debugger/do_list.js:19 +=== Active breakpoints === + 1: tests/debugger/do_list.js:18 + 2: tests/debugger/do_list.js:19 (jerry-debugger) quit diff --git a/tests/debugger/do_pending_breakpoints.cmd b/tests/debugger/do_pending_breakpoints.cmd index 56f8f5e71..e57e4d578 100644 --- a/tests/debugger/do_pending_breakpoints.cmd +++ b/tests/debugger/do_pending_breakpoints.cmd @@ -1,5 +1,6 @@ -fbreak f -list pending +break f +y +list n n c diff --git a/tests/debugger/do_pending_breakpoints.expected b/tests/debugger/do_pending_breakpoints.expected index 76418ff1d..e4283d4f5 100644 --- a/tests/debugger/do_pending_breakpoints.expected +++ b/tests/debugger/do_pending_breakpoints.expected @@ -1,15 +1,16 @@ Connecting to: localhost:5001 Stopped at tests/debugger/do_pending_breakpoints.js:15 -(jerry-debugger) fbreak f -Breakpoint not found -Pending breakpoint added -(jerry-debugger) list pending -0: f +(jerry-debugger) break f +No breakpoint found, do you want to add a pending breakpoint? (y or [n]) +Pending breakpoint at f() +(jerry-debugger) list +=== Pending breakpoints === + 1: f() (pending) (jerry-debugger) n Stopped at tests/debugger/do_pending_breakpoints.js:17 (jerry-debugger) n -Breakpoint 1 at :1 (in f() at line:1, col:1) +Breakpoint 2 at :1 (in f() at line:1, col:1) Stopped at tests/debugger/do_pending_breakpoints.js:19 (jerry-debugger) c -Stopped at breakpoint:1 :1 (in f() at line:1, col:1) +Stopped at breakpoint:2 :1 (in f() at line:1, col:1) (jerry-debugger) c diff --git a/tests/debugger/do_pending_list.cmd b/tests/debugger/do_pending_list.cmd deleted file mode 100644 index a255d22da..000000000 --- a/tests/debugger/do_pending_list.cmd +++ /dev/null @@ -1,6 +0,0 @@ -fbreak do_pending_breakpoints.js:50 -fbreak do_pending_breakpoints.js:235532 -fbreak do_pending_breakpoints.js:2145 -n -list pending -c diff --git a/tests/debugger/do_pending_list.expected b/tests/debugger/do_pending_list.expected deleted file mode 100644 index 93e0db841..000000000 --- a/tests/debugger/do_pending_list.expected +++ /dev/null @@ -1,18 +0,0 @@ -Connecting to: localhost:5001 -Stopped at tests/debugger/do_pending_list.js:15 -(jerry-debugger) fbreak do_pending_breakpoints.js:50 -Breakpoint not found -Pending breakpoint added -(jerry-debugger) fbreak do_pending_breakpoints.js:235532 -Breakpoint not found -Pending breakpoint added -(jerry-debugger) fbreak do_pending_breakpoints.js:2145 -Breakpoint not found -Pending breakpoint added -(jerry-debugger) n -Stopped at tests/debugger/do_pending_list.js:17 -(jerry-debugger) list pending -0: 50 -1: 235532 -2: 2145 -(jerry-debugger) c diff --git a/tests/debugger/do_pending_list.js b/tests/debugger/do_pending_list.js deleted file mode 100644 index 82418db0f..000000000 --- a/tests/debugger/do_pending_list.js +++ /dev/null @@ -1,20 +0,0 @@ -// 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. - -print("pending breakpoints list"); - -var x = 10; -var y = 10; -var pi = 3.14; -var z = x + y;