From 5d4944d252afe962188570a3cb103a6536a3fa9a Mon Sep 17 00:00:00 2001 From: Alexander K Date: Sun, 17 Apr 2022 10:24:50 +0200 Subject: [PATCH 01/20] Add new option to change a variable's radix --- Context.sublime-menu | 4 ++++ sublimegdb.py | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/Context.sublime-menu b/Context.sublime-menu index ff92041..5d20295 100644 --- a/Context.sublime-menu +++ b/Context.sublime-menu @@ -52,6 +52,10 @@ { "caption": "Add watch", "command": "gdb_add_watch" + }, + { + "caption": "Set variable format", + "command": "gdb_set_var_fmt" } ] }] diff --git a/sublimegdb.py b/sublimegdb.py index 5ffb726..da20423 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -373,6 +373,7 @@ def __init__(self, vp=None, parent=None): self.update_value() self.dirty = False self.deleted = False + self.var_format = "natural" def delete(self): run_cmd("-var-delete %s" % self.get_name()) @@ -383,6 +384,12 @@ def update_value(self): if get_result(line) == "done": self['value'] = parse_result_line(line)["value"] + def set_fmt(self, fmt): + self.var_format = fmt + run_cmd("-var-set-format %s %s" % (self["name"], self.var_format), True) + self.update_value() + + def update(self, d): for key in d: if key.startswith("new_"): @@ -2143,6 +2150,23 @@ def run(self, edit): exp = self.view.substr(self.view.word(self.view.sel()[0].begin())) gdb_breakpoint_view.toggle_watch(exp) +class GdbSetVarFmt(sublime_plugin.TextCommand): + def run(self, edit): + choices = ["natural", "decimal", "hexadecimal", "octal"] + var = None + def on_fmt_choose(idx): + if idx >= 0: + var.set_fmt(choices[idx]) + gdb_variables_view.update_variables(True) + + if gdb_variables_view.is_open() and self.view.id() == gdb_variables_view.get_view().id(): + var = gdb_variables_view.get_variable_at_line(self.view.rowcol(self.view.sel()[0].begin())[0]) + if var is not None: + self.view.window().show_quick_panel(choices, on_fmt_choose) + else: + sublime.status_message("No variable selected to choose format for.") + + class GdbToggleBreakpoint(sublime_plugin.TextCommand): def run(self, edit): From 83c866f847738b42303d66a676f53c1f31fb1d34 Mon Sep 17 00:00:00 2001 From: Alexander K Date: Sun, 17 Apr 2022 10:49:27 +0200 Subject: [PATCH 02/20] WIP Memdump --- Default.sublime-commands | 4 ++ sublimegdb.py | 134 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 137 insertions(+), 1 deletion(-) diff --git a/Default.sublime-commands b/Default.sublime-commands index d5f8764..e74994e 100644 --- a/Default.sublime-commands +++ b/Default.sublime-commands @@ -84,5 +84,9 @@ { "caption": "SublimeGDB: Open Threads View", "command": "gdb_open_threads_view" + }, + { + "caption": "SublimeGDB: Add MemDump", + "command": "gdb_add_mem_dump" } ] diff --git a/sublimegdb.py b/sublimegdb.py index da20423..9b75311 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -522,6 +522,10 @@ def __setitem__(self, key, value): def is_dynamic(self): return ('dynamic' in self) + @property + def is_memdump(self): + return False + def update_from(self, var): if (var.is_expanded): self.expand() @@ -589,6 +593,125 @@ def filter_type(type): return type +class GDBMemDump: + def __init__(self, exp, memlen, vp=None, parent=None): + self.parent = parent + self.valuepair = vp + self.line = 0 + self.is_expanded = False + self.dirty = True + self.deleted = False + self.cols = 5 + self.len = memlen + self.exp = exp + self.expfmt = "x" + self.wordlen = 1 + self.rows = self.len // self.cols + 1 + self.data = {} + + def delete(self): + self.deleted = True + + def update_value(self): + line = run_cmd("-data-read-memory %s %s %d %d %d" % (self.exp, self.expfmt, self.wordlen, self.rows, self.cols) , True) + if get_result(line) == "done": + self.data = parse_result_line(line) + print("Got data: {}".format(self.data)) + + def set_fmt(self, fmt): + pass + + + def update(self, d): + pass + + def is_existing(self): + return True + + def get_expression(self): + return self.exp + + def add_children(self, name): + pass + + def is_editable(self): + return False + + def edit_on_done(self, val): + pass + + def find(self, name): + return None + + def edit(self): + pass + + def get_name(self): + return self.exp + + def expand(self): + if not self.is_existing(): + return + self.is_expanded = True + + def has_children(self): + return False + + def collapse(self): + self.is_expanded = False + + def __str__(self): + return "dump %s" % (self.exp) + + def __iter__(self): + return self.valuepair.__iter__() + + def __getitem__(self, key): + return self.valuepair[key] + + + @property + def is_dynamic(self): + return False + + @property + def is_memdump(self): + return True + + def update_from(self, var): + pass + + def find_child_expression(self, exp): + return None + + def clear_dirty(self): + self.dirty = False + + def is_dirty(self): + return self.dirty + + def format(self, indent="", output="", line=0, dirty=[]): + if self.is_expanded: + icon = "-" + else: + icon = "+" + + output += "%s%s%s\n" % (indent, icon, self.exp) + indent = " " + + if self.is_expanded: + for l in self.data['memory']: + output += "%s%s\n" % (indent, " ".join(l['data'])) + + + + return (output, line) + + @staticmethod + def filter_type(type): + return "dump" + + def qtod(q): val = struct.pack("Q", q) return struct.unpack("d", val)[0] @@ -792,7 +915,10 @@ def update_variables(self, sameFrame): if sameFrame: variables = [] for var in self.variables: # completely replace dynamic variables because we don't always get proper update notifications - if (var.is_dynamic): + if var.is_memdump: + variables.append(var) + var.update_value() + elif (var.is_dynamic): var.delete() newVar = self.create_variable(var['exp'], False) if (newVar): # may have gone out of scope without notification @@ -2167,6 +2293,12 @@ def on_fmt_choose(idx): sublime.status_message("No variable selected to choose format for.") +class GdbAddMemDump(sublime_plugin.TextCommand): + def run(self, edit): + gdb_variables_view.variables.append(GDBMemDump("c", 5)) + gdb_variables_view.update_variables(True) + + class GdbToggleBreakpoint(sublime_plugin.TextCommand): def run(self, edit): From 2e9c00218fac768f244a508cb8bc6c4d260f9912 Mon Sep 17 00:00:00 2001 From: Alexander K Date: Sun, 17 Apr 2022 11:21:30 +0200 Subject: [PATCH 03/20] Working Memdump display with collapse --- sublimegdb.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sublimegdb.py b/sublimegdb.py index 9b75311..e5532d8 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -593,12 +593,17 @@ def filter_type(type): return type +class GDBMemDumpChild: + def __init__(self, line, parent): + self.line = line + self.parent = parent + class GDBMemDump: def __init__(self, exp, memlen, vp=None, parent=None): self.parent = parent self.valuepair = vp self.line = 0 - self.is_expanded = False + self.is_expanded = True self.dirty = True self.deleted = False self.cols = 5 @@ -608,6 +613,7 @@ def __init__(self, exp, memlen, vp=None, parent=None): self.wordlen = 1 self.rows = self.len // self.cols + 1 self.data = {} + self.children = [] def delete(self): self.deleted = True @@ -616,7 +622,6 @@ def update_value(self): line = run_cmd("-data-read-memory %s %s %d %d %d" % (self.exp, self.expfmt, self.wordlen, self.rows, self.cols) , True) if get_result(line) == "done": self.data = parse_result_line(line) - print("Got data: {}".format(self.data)) def set_fmt(self, fmt): pass @@ -650,12 +655,10 @@ def get_name(self): return self.exp def expand(self): - if not self.is_existing(): - return self.is_expanded = True def has_children(self): - return False + return True def collapse(self): self.is_expanded = False @@ -696,14 +699,15 @@ def format(self, indent="", output="", line=0, dirty=[]): else: icon = "+" - output += "%s%s%s\n" % (indent, icon, self.exp) + output += "%sDUMP of %s\n" % (icon, self.exp) indent = " " + self.line = line if self.is_expanded: for l in self.data['memory']: output += "%s%s\n" % (indent, " ".join(l['data'])) - - + line += 1 + self.children.append(GDBMemDumpChild(line, self)) return (output, line) From ace5998d043108bf3dff65c0d36403b24bfbe07a Mon Sep 17 00:00:00 2001 From: Alexander K Date: Sun, 17 Apr 2022 11:45:22 +0200 Subject: [PATCH 04/20] Get line formats right --- sublimegdb.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sublimegdb.py b/sublimegdb.py index e5532d8..56325e0 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -693,6 +693,13 @@ def clear_dirty(self): def is_dirty(self): return self.dirty + def fmt_line(self, data, line): + dat = data[:max(self.len-((line-self.line)*self.cols),0)] + if self.expfmt == "x": + return " ".join([x[2:].upper() for x in dat]) + else: + return " ".join(dat) + def format(self, indent="", output="", line=0, dirty=[]): if self.is_expanded: icon = "-" @@ -705,7 +712,7 @@ def format(self, indent="", output="", line=0, dirty=[]): if self.is_expanded: for l in self.data['memory']: - output += "%s%s\n" % (indent, " ".join(l['data'])) + output += "%s%s\n" % (indent, self.fmt_line(l['data'], line)) line += 1 self.children.append(GDBMemDumpChild(line, self)) From 16317fd6e77edb131c89cab8acae80294e4ac572 Mon Sep 17 00:00:00 2001 From: Alexander K Date: Sun, 17 Apr 2022 11:45:41 +0200 Subject: [PATCH 05/20] User interaction for MemDump, expression and length --- sublimegdb.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/sublimegdb.py b/sublimegdb.py index 56325e0..397be06 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -2306,8 +2306,16 @@ def on_fmt_choose(idx): class GdbAddMemDump(sublime_plugin.TextCommand): def run(self, edit): - gdb_variables_view.variables.append(GDBMemDump("c", 5)) - gdb_variables_view.update_variables(True) + expression = [""] + length = [0] + def on_memdump_explen(l): + length[0] = int(l) + gdb_variables_view.variables.append(GDBMemDump(expression[0], length[0])) + gdb_variables_view.update_variables(True) + def on_memdump_expdone(exp): + expression[0] = exp + self.view.window().show_input_panel("Memdump length", "", on_memdump_explen, None, None) + self.view.window().show_input_panel("Memdump Expression", "", on_memdump_expdone, None, None) From 482146eea452e58e2bced2bfa51f293277e89475 Mon Sep 17 00:00:00 2001 From: Alexander K Date: Sun, 17 Apr 2022 11:49:40 +0200 Subject: [PATCH 06/20] Prepend address --- sublimegdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sublimegdb.py b/sublimegdb.py index 397be06..6590f8e 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -712,7 +712,7 @@ def format(self, indent="", output="", line=0, dirty=[]): if self.is_expanded: for l in self.data['memory']: - output += "%s%s\n" % (indent, self.fmt_line(l['data'], line)) + output += "%s%s: %s\n" % (indent, l['addr'].upper(),self.fmt_line( l['data'], line)) line += 1 self.children.append(GDBMemDumpChild(line, self)) From 5b451fc56679041c9d4a125c160bef7ca9e8b9f9 Mon Sep 17 00:00:00 2001 From: Alexander K Date: Sun, 17 Apr 2022 14:24:34 +0200 Subject: [PATCH 07/20] Highligh changes in memdump per step --- sublimegdb.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/sublimegdb.py b/sublimegdb.py index 6590f8e..6846bcb 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -613,6 +613,7 @@ def __init__(self, exp, memlen, vp=None, parent=None): self.wordlen = 1 self.rows = self.len // self.cols + 1 self.data = {} + self.oldata = {} self.children = [] def delete(self): @@ -621,11 +622,29 @@ def delete(self): def update_value(self): line = run_cmd("-data-read-memory %s %s %d %d %d" % (self.exp, self.expfmt, self.wordlen, self.rows, self.cols) , True) if get_result(line) == "done": + self.oldata = self.data self.data = parse_result_line(line) def set_fmt(self, fmt): pass + def getchanged(self, view): + regions = [] + + if not 'memory' in self.oldata: + print("No old data") + return regions + for idx, (d, od) in enumerate(zip(self.data['memory'], self.oldata['memory'])): + newdat = d['data'] + olddat = od['data'] if 'data' in od else None + offset = 6 + len(d['addr']) + if not olddat: + continue + for i in range(len(newdat)): + if(newdat[i] != olddat[i]): + fieldlen = len(newdat[i]) if self.expfmt != "x" else len(newdat[i])-2 + regions.append(sublime.Region(view.text_point(self.line+idx+1, i*(fieldlen+1)+offset), view.text_point(self.line+idx+1, i*(fieldlen+1)+fieldlen)+offset)) + return regions def update(self, d): pass @@ -884,7 +903,10 @@ def update_view(self): output = "" line = 0 dirtylist = [] + dirty_memdump = [] for local in self.variables: + if local.is_memdump: + dirty_memdump.append(local) output, line = local.format(line=line, dirty=dirtylist) self.add_line(output) self.update() @@ -892,11 +914,16 @@ def update_view(self): v = self.get_view() for dirty in dirtylist: regions.append(v.full_line(v.text_point(dirty.line, 0))) + + for mdump in dirty_memdump: + regions.extend(mdump.getchanged(v)) + v.add_regions("sublimegdb.dirtyvariables", regions, get_setting("changed_variable_scope", "entity.name.class"), get_setting("changed_variable_icon", ""), sublime.DRAW_OUTLINED) + def extract_varnames(self, res): if "name" in res: return listify(res["name"]) From 545d68189d99f922b882755d7b7006c0c54ae36e Mon Sep 17 00:00:00 2001 From: Alexander K Date: Sun, 17 Apr 2022 16:22:02 +0200 Subject: [PATCH 08/20] Working highlighting of memdump --- sublimegdb.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sublimegdb.py b/sublimegdb.py index 6846bcb..41ff0d3 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -630,21 +630,22 @@ def set_fmt(self, fmt): def getchanged(self, view): regions = [] + if not self.is_expanded: + return regions if not 'memory' in self.oldata: - print("No old data") return regions - for idx, (d, od) in enumerate(zip(self.data['memory'], self.oldata['memory'])): - newdat = d['data'] - olddat = od['data'] if 'data' in od else None - offset = 6 + len(d['addr']) + for idx in range(len(self.data['memory'])): + newdat = self.data['memory'][idx]['data'] + olddat = self.oldata['memory'][idx]['data'] if self.oldata else None + offset = 6 + len(self.data['memory'][idx]['addr']) if not olddat: continue for i in range(len(newdat)): - if(newdat[i] != olddat[i]): + if(newdat[i] != olddat[i] and idx*self.cols+i < self.len): fieldlen = len(newdat[i]) if self.expfmt != "x" else len(newdat[i])-2 regions.append(sublime.Region(view.text_point(self.line+idx+1, i*(fieldlen+1)+offset), view.text_point(self.line+idx+1, i*(fieldlen+1)+fieldlen)+offset)) - return regions + return regions def update(self, d): pass From 9db55dc2be614974370062014db179fe5163aef5 Mon Sep 17 00:00:00 2001 From: Alexander K Date: Sun, 17 Apr 2022 16:51:54 +0200 Subject: [PATCH 09/20] Working ascii dump --- sublimegdb.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/sublimegdb.py b/sublimegdb.py index 41ff0d3..8a03d8d 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -620,7 +620,7 @@ def delete(self): self.deleted = True def update_value(self): - line = run_cmd("-data-read-memory %s %s %d %d %d" % (self.exp, self.expfmt, self.wordlen, self.rows, self.cols) , True) + line = run_cmd("-data-read-memory %s %s %d %d %d \".\"" % (self.exp, self.expfmt, self.wordlen, self.rows, self.cols) , True) if get_result(line) == "done": self.oldata = self.data self.data = parse_result_line(line) @@ -713,12 +713,20 @@ def clear_dirty(self): def is_dirty(self): return self.dirty - def fmt_line(self, data, line): - dat = data[:max(self.len-((line-self.line)*self.cols),0)] + def fmt_line(self, data, asci, line): + limit = max(self.len-((line-self.line)*self.cols), 0) + dat = data[:limit] + if asci is not None: + if self.expfmt == "x": + space = max(((line+1-self.line)*self.cols - self.len),0) * (1+len(data[0])-2) + else: + space = max(((line+1-self.line)*self.cols - self.len),0) * (1+len(data[0])) + else: + space = 0 if self.expfmt == "x": - return " ".join([x[2:].upper() for x in dat]) + return " ".join([x[2:].upper() for x in dat]) + (" "*space) + (" // " if asci else "") + (asci or "") else: - return " ".join(dat) + return " ".join(dat) + (" "*space) + (" // " if asci else "") + (asci or "") def format(self, indent="", output="", line=0, dirty=[]): if self.is_expanded: @@ -732,7 +740,7 @@ def format(self, indent="", output="", line=0, dirty=[]): if self.is_expanded: for l in self.data['memory']: - output += "%s%s: %s\n" % (indent, l['addr'].upper(),self.fmt_line( l['data'], line)) + output += "%s%s: %s\n" % (indent, l['addr'].upper().replace("X", "x"),self.fmt_line(l['data'], l['ascii'] if 'ascii' in l else None, line)) line += 1 self.children.append(GDBMemDumpChild(line, self)) From e10e3b3e2a320177e67753de031adc0900563ad4 Mon Sep 17 00:00:00 2001 From: Alexander K Date: Sun, 17 Apr 2022 17:02:03 +0200 Subject: [PATCH 10/20] Ascii highlighting --- sublimegdb.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sublimegdb.py b/sublimegdb.py index 8a03d8d..31f01de 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -645,6 +645,8 @@ def getchanged(self, view): if(newdat[i] != olddat[i] and idx*self.cols+i < self.len): fieldlen = len(newdat[i]) if self.expfmt != "x" else len(newdat[i])-2 regions.append(sublime.Region(view.text_point(self.line+idx+1, i*(fieldlen+1)+offset), view.text_point(self.line+idx+1, i*(fieldlen+1)+fieldlen)+offset)) + if self.data['memory'][idx]['ascii']: + regions.append(sublime.Region(view.text_point(self.line+idx+1, (self.cols*(fieldlen+1))+offset+3+i), view.text_point(self.line+idx+1, (self.cols*(fieldlen+1))+offset+3+i+1))) return regions def update(self, d): From 64ea4bdccd56009d681379424d18eca2b5c58a90 Mon Sep 17 00:00:00 2001 From: Alexander K Date: Sun, 17 Apr 2022 17:11:39 +0200 Subject: [PATCH 11/20] User can set wordlen for memdump now --- sublimegdb.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sublimegdb.py b/sublimegdb.py index 31f01de..a0e249c 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -599,7 +599,7 @@ def __init__(self, line, parent): self.parent = parent class GDBMemDump: - def __init__(self, exp, memlen, vp=None, parent=None): + def __init__(self, exp, memlen, wordlen=1, vp=None, parent=None): self.parent = parent self.valuepair = vp self.line = 0 @@ -610,7 +610,7 @@ def __init__(self, exp, memlen, vp=None, parent=None): self.len = memlen self.exp = exp self.expfmt = "x" - self.wordlen = 1 + self.wordlen = wordlen self.rows = self.len // self.cols + 1 self.data = {} self.oldata = {} @@ -646,7 +646,7 @@ def getchanged(self, view): fieldlen = len(newdat[i]) if self.expfmt != "x" else len(newdat[i])-2 regions.append(sublime.Region(view.text_point(self.line+idx+1, i*(fieldlen+1)+offset), view.text_point(self.line+idx+1, i*(fieldlen+1)+fieldlen)+offset)) if self.data['memory'][idx]['ascii']: - regions.append(sublime.Region(view.text_point(self.line+idx+1, (self.cols*(fieldlen+1))+offset+3+i), view.text_point(self.line+idx+1, (self.cols*(fieldlen+1))+offset+3+i+1))) + regions.append(sublime.Region(view.text_point(self.line+idx+1, (self.cols*(fieldlen+1))+offset+3+self.wordlen*i), view.text_point(self.line+idx+1, (self.cols*(fieldlen+1))+offset+3+(i+1)*self.wordlen))) return regions def update(self, d): @@ -2346,10 +2346,14 @@ class GdbAddMemDump(sublime_plugin.TextCommand): def run(self, edit): expression = [""] length = [0] + wordlength = [0] + def on_memdump_wordlen(l): + wordlength[0] = int(l) + gdb_variables_view.variables.append(GDBMemDump(expression[0], length[0], wordlen=wordlength[0])) + gdb_variables_view.update_variables(True) def on_memdump_explen(l): length[0] = int(l) - gdb_variables_view.variables.append(GDBMemDump(expression[0], length[0])) - gdb_variables_view.update_variables(True) + self.view.window().show_input_panel("Memdump wordlength", "", on_memdump_wordlen, None, None) def on_memdump_expdone(exp): expression[0] = exp self.view.window().show_input_panel("Memdump length", "", on_memdump_explen, None, None) From 25a46ff6323eeb6dd321fa89078ba7db2168728e Mon Sep 17 00:00:00 2001 From: Alexander K Date: Sun, 17 Apr 2022 17:38:38 +0200 Subject: [PATCH 12/20] Fixes for memdump out of scope --- sublimegdb.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/sublimegdb.py b/sublimegdb.py index a0e249c..181bd1c 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -621,9 +621,15 @@ def delete(self): def update_value(self): line = run_cmd("-data-read-memory %s %s %d %d %d \".\"" % (self.exp, self.expfmt, self.wordlen, self.rows, self.cols) , True) - if get_result(line) == "done": + if get_result(line, False) == "done": self.oldata = self.data self.data = parse_result_line(line) + self.deleted = False + else: + self.oldata = self.data + self.data = {} + self.deleted = True + def set_fmt(self, fmt): pass @@ -740,7 +746,7 @@ def format(self, indent="", output="", line=0, dirty=[]): indent = " " self.line = line - if self.is_expanded: + if self.is_expanded and 'memory' in self.data: for l in self.data['memory']: output += "%s%s: %s\n" % (indent, l['addr'].upper().replace("X", "x"),self.fmt_line(l['data'], l['ascii'] if 'ascii' in l else None, line)) line += 1 From ec1be138fc03f864a34299a235049ae6c1092803 Mon Sep 17 00:00:00 2001 From: Alexander K Date: Sun, 17 Apr 2022 18:08:45 +0200 Subject: [PATCH 13/20] Fix appearance of memdump in put of scope case --- sublimegdb.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/sublimegdb.py b/sublimegdb.py index 181bd1c..6430210 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -624,11 +624,14 @@ def update_value(self): if get_result(line, False) == "done": self.oldata = self.data self.data = parse_result_line(line) - self.deleted = False + self.valuepair = {'exp': self.exp} + if self.is_expanded is False and not self.oldata: + self.is_expanded = True else: self.oldata = self.data self.data = {} - self.deleted = True + self.is_expanded = False + self.children = list() def set_fmt(self, fmt): @@ -719,7 +722,7 @@ def clear_dirty(self): self.dirty = False def is_dirty(self): - return self.dirty + return True def fmt_line(self, data, asci, line): limit = max(self.len-((line-self.line)*self.cols), 0) @@ -745,6 +748,8 @@ def format(self, indent="", output="", line=0, dirty=[]): output += "%sDUMP of %s\n" % (icon, self.exp) indent = " " self.line = line + + self.children = list() if self.is_expanded and 'memory' in self.data: for l in self.data['memory']: @@ -992,7 +997,9 @@ def update_variables(self, sameFrame): for var in self.variables: real = var.find(name) if (real is not None): - if "in_scope" in value and value["in_scope"] == "false": + if var.is_memdump: + continue + elif "in_scope" in value and value["in_scope"] == "false": real.delete() dellist.append(real) continue @@ -2359,10 +2366,10 @@ def on_memdump_wordlen(l): gdb_variables_view.update_variables(True) def on_memdump_explen(l): length[0] = int(l) - self.view.window().show_input_panel("Memdump wordlength", "", on_memdump_wordlen, None, None) + self.view.window().show_input_panel("Memdump wordlength", "1", on_memdump_wordlen, None, None) def on_memdump_expdone(exp): expression[0] = exp - self.view.window().show_input_panel("Memdump length", "", on_memdump_explen, None, None) + self.view.window().show_input_panel("Memdump number of words", "", on_memdump_explen, None, None) self.view.window().show_input_panel("Memdump Expression", "", on_memdump_expdone, None, None) From a3472547e56d1897df263788238f72c27cfb899f Mon Sep 17 00:00:00 2001 From: Alexander K Date: Sun, 17 Apr 2022 18:11:22 +0200 Subject: [PATCH 14/20] Add out of scope note for missing dumps --- sublimegdb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sublimegdb.py b/sublimegdb.py index 6430210..11eaf91 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -745,11 +745,11 @@ def format(self, indent="", output="", line=0, dirty=[]): else: icon = "+" - output += "%sDUMP of %s\n" % (icon, self.exp) + self.children = list() + output += "%sDUMP of %s %s\n" % (icon, self.exp, "//(NOT IN SCOPE)" if not self.data else "") indent = " " self.line = line - self.children = list() if self.is_expanded and 'memory' in self.data: for l in self.data['memory']: From b9f2a421591c215b86aa8f9e140c5f5cd3eadf98 Mon Sep 17 00:00:00 2001 From: Alexander K Date: Sun, 17 Apr 2022 18:14:58 +0200 Subject: [PATCH 15/20] Make memdump width customizable --- sublimegdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sublimegdb.py b/sublimegdb.py index 11eaf91..670f8c0 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -606,7 +606,7 @@ def __init__(self, exp, memlen, wordlen=1, vp=None, parent=None): self.is_expanded = True self.dirty = True self.deleted = False - self.cols = 5 + self.cols = get_setting("memdump_cols", 4) self.len = memlen self.exp = exp self.expfmt = "x" From 7532d8d4f61f0854321a6ee1a54586a66f9727e4 Mon Sep 17 00:00:00 2001 From: Alexander K Date: Sun, 17 Apr 2022 18:25:30 +0200 Subject: [PATCH 16/20] Fix table row count and data emptiness failure --- sublimegdb.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sublimegdb.py b/sublimegdb.py index 670f8c0..32cd092 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -31,6 +31,7 @@ import os import sys import re +import math import queue from datetime import datetime from functools import partial @@ -611,7 +612,7 @@ def __init__(self, exp, memlen, wordlen=1, vp=None, parent=None): self.exp = exp self.expfmt = "x" self.wordlen = wordlen - self.rows = self.len // self.cols + 1 + self.rows = math.ceil(float(self.len) / self.cols) self.data = {} self.oldata = {} self.children = [] @@ -642,11 +643,14 @@ def getchanged(self, view): if not self.is_expanded: return regions - if not 'memory' in self.oldata: + if not 'memory' in self.oldata or not 'memory' in self.data: return regions for idx in range(len(self.data['memory'])): newdat = self.data['memory'][idx]['data'] olddat = self.oldata['memory'][idx]['data'] if self.oldata else None + # calculating the regions is a bit tricky because all characters in a line have to be included in the calc. + # one byte is displayed within fieldlen plus one space characters + # the comment sign takes 3 chars with one space included offset = 6 + len(self.data['memory'][idx]['addr']) if not olddat: continue From 0a4d5eea33c090c49b35e8445c175a1bf62ebc39 Mon Sep 17 00:00:00 2001 From: Alexander K Date: Sun, 17 Apr 2022 19:36:30 +0200 Subject: [PATCH 17/20] Enable adding memdumps from project file --- sublimegdb.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sublimegdb.py b/sublimegdb.py index 32cd092..c715222 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -1035,6 +1035,11 @@ def update_variables(self, sameFrame): var.delete() args = self.extract_varnames(parse_result_line(run_cmd("-stack-list-arguments 0 %d %d" % (gdb_stack_index, gdb_stack_index), True))["stack-args"]["frame"]["args"]) self.variables = [] + + memdumps = get_setting("memdumps", []) + for m in memdumps: + self.variables.append(GDBMemDump(m['exp'], m['words'], wordlen=m['wordlen'])) + for arg in args: self.add_variable(arg) loc = self.extract_varnames(parse_result_line(run_cmd("-stack-list-locals 0", True))["locals"]) From dbc2f0680416ec87f935bf9297f0691c51dce333 Mon Sep 17 00:00:00 2001 From: Alexander K Date: Sun, 17 Apr 2022 19:48:37 +0200 Subject: [PATCH 18/20] Fix line counting for memdumps --- sublimegdb.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sublimegdb.py b/sublimegdb.py index c715222..56e4bea 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -761,6 +761,7 @@ def format(self, indent="", output="", line=0, dirty=[]): line += 1 self.children.append(GDBMemDumpChild(line, self)) + line += 1 return (output, line) @staticmethod From 5cd8285333280f255111b8eea43fa4b11c7b82f6 Mon Sep 17 00:00:00 2001 From: Alexander K Date: Mon, 18 Apr 2022 18:04:21 +0200 Subject: [PATCH 19/20] Fix updating variables after GDB pause with memdumps --- sublimegdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sublimegdb.py b/sublimegdb.py index 56e4bea..27d9c16 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -602,7 +602,7 @@ def __init__(self, line, parent): class GDBMemDump: def __init__(self, exp, memlen, wordlen=1, vp=None, parent=None): self.parent = parent - self.valuepair = vp + self.valuepair = vp if vp else {'exp': exp} self.line = 0 self.is_expanded = True self.dirty = True From a39defbc3b1c75c5440710ab7da93763d7a361db Mon Sep 17 00:00:00 2001 From: Alexander K Date: Mon, 18 Apr 2022 21:26:34 +0200 Subject: [PATCH 20/20] Fix memdump not updating when initialized --- sublimegdb.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sublimegdb.py b/sublimegdb.py index 27d9c16..48a7710 100644 --- a/sublimegdb.py +++ b/sublimegdb.py @@ -616,6 +616,7 @@ def __init__(self, exp, memlen, wordlen=1, vp=None, parent=None): self.data = {} self.oldata = {} self.children = [] + self.update_value() def delete(self): self.deleted = True