diff --git a/gui/commands.py b/gui/commands.py index 5531c73..007d41e 100644 --- a/gui/commands.py +++ b/gui/commands.py @@ -16,6 +16,7 @@ import gdb import gui.startup import gui.source +import gui.stack import gui.logwindow import gui.toplevel import gui.dprintf @@ -45,6 +46,24 @@ windows can be created.""" self.dont_repeat() gui.source.lru_handler.new_source_window() +class GuiStackCommand(gdb.Command): + """Create a new stack window. +Usage: gui stack +This creates a stack window in the GUI if it does not already exist.""" + + def __init__(self): + super(GuiStackCommand, self).__init__('gui stack', + gdb.COMMAND_SUPPORT) + + def invoke(self, arg, from_tty): + self.dont_repeat() + # FIXME does it make sense to have more than one? Maybe if + # we have thread-locking. + # FIXME could have arguments to set various stack flags, + # like whether to show child frames, or just show raw, + # or maybe even whatever 'bt' takes? + gui.stack.show_stack() + class GuiListCommand(gdb.Command): """List some source code in a source window. Usage: gui list LINESPEC @@ -265,6 +284,7 @@ found using "info windows".""" GuiCommand() GuiSourceCommand() +GuiStackCommand() GuiLogWindowCommand() GuiPrintCommand() GuiOutputCommand() diff --git a/gui/params.py b/gui/params.py index 08d4099..6ef155d 100644 --- a/gui/params.py +++ b/gui/params.py @@ -272,6 +272,7 @@ font_manager = _Font() _Title('source', '\\W{basename} [GDB Source @\\W{number}]') _Title('display', '\\W{command} [GDB Display @\\W{number}]') _Title('log', '[GDB Log @\\W{number}]\\W{default}') +_Title('stack', '[GDB Stack @\\W{number}]') warn_missing = _Missing() line_numbers = _Lines() diff --git a/gui/stack.py b/gui/stack.py new file mode 100644 index 0000000..ae9a81b --- /dev/null +++ b/gui/stack.py @@ -0,0 +1,104 @@ +# 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 . + +# Stack view. + +import gdb +import gdb.frames +import gdb.FrameDecorator +import gdb.FrameIterator +import gui.updatewindow +import gui.startup +import gui.markup +import gui.params + +from gui.invoker import Invoker +from gui.startup import in_gdb_thread, in_gtk_thread +from gi.repository import Gtk + +def format_frame(frame): + result = {} + result["name"] = frame.function() + result["filename"] = frame.filename() + result["pc"] = frame.address() + result["line"] = frame.line() + elided = frame.elided() + if elided is not None: + elided = list(map(format_frame, elided)) + result["elided"] = elided + # Not quite what we want... + result["solib"] = gdb.solib_name(frame.address()) + return result + # FIXME args + +class StackWindow(gui.updatewindow.UpdateWindow): + def __init__(self): + self.raw = False + super(StackWindow, self).__init__('stack') + # Connect events. + # Update buttons. + + @in_gtk_thread + def gtk_initialize(self): + self.do_up = Invoker("up") + self.do_down = Invoker("down") + builder = gui.startup.create_builder('stackwindow.xml') + builder.connect_signals(self) + + self.window = builder.get_object('stackwindow') + self.view = builder.get_object('view') + self.text = Gtk.TextBuffer() + self.view.set_buffer(self.text) + self.view.modify_font(gui.params.font_manager.get_font()) + + @in_gtk_thread + def _update(self, data): + self.text.delete(self.text.get_start_iter(), self.text.get_end_iter()) + for frame in data: + # Goofball API. + if isinstance(frame["name"], str): + self.text.insert_at_cursor(frame["name"]) + else: + # This is lame but we have no access to minimal + # symbols. + self.text.insert_at_cursor("???") + self.text.insert_at_cursor(" ") + # FIXME args + self.text.insert_at_cursor("\n") + if frame["line"] is not None: + self.text.insert_at_cursor(" at %s:%d\n" % (frame["filename"], + frame["line"])) + if frame["solib"] is not None: + self.text.insert_at_cursor(" [%s]\n" % frame["solib"]) + + @in_gdb_thread + def on_event(self): + frame_iter = None + start_frame = gdb.newest_frame() + if not self.raw: + frame_iter = gdb.frames.execute_frame_filters(start_frame, 0, -1) + if frame_iter is None: + frame_iter = map(gdb.FrameDecorator.FrameDecorator, + gdb.FrameIterator.FrameIterator(start_frame)) + data = list(map(format_frame, frame_iter)) + gui.startup.send_to_gtk(lambda: self._update(data)) + + @in_gtk_thread + def set_font(self, pango_font): + self.view.modify_font(pango_font) + +def show_stack(): + # for now + StackWindow() diff --git a/gui/stackwindow.xml b/gui/stackwindow.xml new file mode 100644 index 0000000..d0536e9 --- /dev/null +++ b/gui/stackwindow.xml @@ -0,0 +1,81 @@ + + + + + + False + 200 + 400 + + + True + False + vertical + + + True + False + + + True + False + Up one frame + Up + True + go-down + + + + False + True + + + + + True + False + Down one frame + Down + True + go-up + + + + False + True + + + + + False + True + 0 + + + + + True + True + in + + + True + True + False + 2 + 2 + -1 + False + + + + + True + True + 1 + + + + + +