From 7647b97c014c524e5ade14f2e7a40e759824c4ae Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Fri, 8 May 2015 13:01:23 -0600 Subject: [PATCH] try to update source window when breakpoints change this is not tested yet --- gui/adapt.py | 9 ++++++-- gui/bpcache.py | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ gui/events.py | 7 ++++--- gui/source.py | 29 +++++++++++++++++++++++-- 4 files changed, 95 insertions(+), 7 deletions(-) create mode 100644 gui/bpcache.py diff --git a/gui/adapt.py b/gui/adapt.py index f3b7bfc..5111f6f 100644 --- a/gui/adapt.py +++ b/gui/adapt.py @@ -25,10 +25,15 @@ breakpoints have been set.""", 13598: """Your gdb doesn't have a "before prompt" event. This means that various windows won't be able to react to -commands like "up" or "down".""" +commands like "up" or "down".""", + + 18385: """Your gdb doesn't expose locations on a gdb.Breakpoint. +This can be worked around, but maybe not always reliably. +This means that sometimes breakpoints won't display in source windows.""" } -_warning = "See https://sourceware.org/bugzilla/show_bug.cgi?id=%s for more information." +_warning = """See https://sourceware.org/bugzilla/show_bug.cgi?id=%s +for more information.""" _first_report = True diff --git a/gui/bpcache.py b/gui/bpcache.py new file mode 100644 index 0000000..87b2fce --- /dev/null +++ b/gui/bpcache.py @@ -0,0 +1,57 @@ +# Copyright (C) 2015 Tom Tromey + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import gdb +import gui.events +import gui.adapt + +# This maps from (FILENAME,LINE) to a set of breakpoints referencing +# that file/line. Then we emit events when entries are created or +# destroyed. +breakpoint_source_map = {} + +def _breakpoint_created(bp): + if bp.location is None: + return + gui.adapt.notify_bug(18385) + (rest, locs) = gdb.decode_line(bp.location) + if rest is not None: + # Let's assume we couldn't reparse for some reason. + return + for sal in locs: + if sal.symtab is None: + continue + entry = (sal.symtab.fullname(), sal.line) + if entry not in breakpoint_source_map: + breakpoint_source_map[entry] = set() + if bp.number not in breakpoint_source_map[entry]: + breakpoint_source_map[entry].add(bp.number) + gui.events.location_changed.post(entry, True) + else: + breakpoint_source_map[entry].add(bp.number) + +def _breakpoint_deleted(bp): + num = bp.number + for entry in breakpoint_source_map: + if num in breakpoint_source_map[entry]: + breakpoint_source_map[entry].discard(bp.number) + if len(breakpoint_source_map[entry]) == 0: + gui.events.location_changed.post(entry, False) + +if not hasattr(gdb.events, 'breakpoint_created'): + gui.adapt.notify_bug(15620) +else: + gdb.events.breakpoint_created.connect(_breakpoint_created) + gdb.events.breakpoint_deleted.connect(_breakpoint_deleted) diff --git a/gui/events.py b/gui/events.py index 9f053eb..97dd91e 100644 --- a/gui/events.py +++ b/gui/events.py @@ -1,4 +1,4 @@ -# Copyright (C) 2013 Tom Tromey +# Copyright (C) 2013, 2015 Tom Tromey # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -25,8 +25,9 @@ class _Event(object): def disconnect(self, callback): self.funcs.remove(callback) - def post(self): + def post(self, *args, **kwargs): for fun in self.funcs: - fun() + fun(*args, **kwargs) frame_changed = _Event() +location_changed = _Event() diff --git a/gui/source.py b/gui/source.py index f849b4f..1ccc4ba 100644 --- a/gui/source.py +++ b/gui/source.py @@ -26,6 +26,7 @@ import gui.events import os.path import gui.gdbutil import gui.params +import gui.bpcache from gi.repository import Gtk, GtkSource, GObject, Gdk, GdkPixbuf, Pango @@ -34,6 +35,7 @@ class BufferManager: self.buffers = {} self.lang_manager = None gui.params.source_theme.set_buffer_manager(self) + gui.events.location_changed.connect(self._location_changed) def release_buffer(self, buff): # FIXME: we should be smart about buffer caching. @@ -41,10 +43,13 @@ class BufferManager: @in_gtk_thread def _set_marks(self, buffer, line_set): + buffer.all_marks = {} iter = buffer.get_iter_at_line(0) while True: - if iter.get_line() + 1 in line_set: - mark = buffer.create_source_mark(None, 'executable', iter) + line = iter.get_line() + 1 + if line in line_set: + all_marks[line] = buffer.create_source_mark(None, 'executable', + iter) if not iter.forward_line(): break @@ -91,6 +96,26 @@ class BufferManager: def change_theme(self): gui.startup.send_to_gtk(self._do_change_theme) + @in_gtk_thread + def update_breakpoint_location(self, sal, is_set): + if is_set: + category = 'breakpoint' + else: + category = 'executable' + [fullname, line] = sal + if fullname in self.buffers: + buffer = self.buffers[fullname] + if line in buffer.all_marks: + if buffer.all_marks[line].category is not category: + iter = buffer.get_iter_at_line(line - 1) + buffer.all_marks[line] = buffer.create_source_mark(None, + category, + iter) + + @in_gdb_thread + def _location_changed(self, loc, is_set): + gui.startup.send_to_gtk(self.update_breakpoint_location) + buffer_manager = BufferManager() # Return (FRAME, SYMTAB, FILE, LINE) for the selected frame, or, if