mirror of
https://github.com/tromey/gdb-gui.git
synced 2025-09-07 02:00:17 +02:00
This adds a couple of decorators that can be used to mark functions as needing to be run in the gdb thread or in the gtk thread. This found at least one bug.
197 lines
6.4 KiB
Python
197 lines
6.4 KiB
Python
# Copyright (C) 2012, 2013 Tom Tromey <tom@tromey.com>
|
|
|
|
# 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 <http://www.gnu.org/licenses/>.
|
|
|
|
import gdb
|
|
import gui.startup
|
|
import gui.source
|
|
import gui.logwindow
|
|
import gui.toplevel
|
|
import gui.dprintf
|
|
import gui.events
|
|
import re
|
|
from gui.startup import in_gtk_thread
|
|
|
|
class GuiCommand(gdb.Command):
|
|
def __init__(self):
|
|
super(GuiCommand, self).__init__('gui', gdb.COMMAND_SUPPORT,
|
|
prefix = True)
|
|
|
|
class GuiSourceCommand(gdb.Command):
|
|
"""Create a new source window.
|
|
Usage: gui source
|
|
This creates a new source window in the GUI. Any number of source
|
|
windows can be created."""
|
|
|
|
def __init__(self):
|
|
super(GuiSourceCommand, self).__init__('gui source',
|
|
gdb.COMMAND_SUPPORT)
|
|
|
|
def invoke(self, arg, from_tty):
|
|
self.dont_repeat()
|
|
gui.startup.start_gtk()
|
|
gui.startup.send_to_gtk(gui.source.SourceWindow)
|
|
|
|
class GuiLogWindowCommand(gdb.Command):
|
|
"""Create a new log window.
|
|
Usage: gui log
|
|
This creates a new "log" window in the GUI. A log window is used
|
|
to display output from "gui print", "gui printf", "gui output",
|
|
and "gui dprintf".
|
|
|
|
Multiple log windows can be created and output can be directed to
|
|
a given instance using the "@" syntax, like:
|
|
|
|
gui printf @5 "hello\n"
|
|
"""
|
|
|
|
def __init__(self):
|
|
super(GuiLogWindowCommand, self).__init__('gui log',
|
|
gdb.COMMAND_SUPPORT)
|
|
|
|
def invoke(self, arg, from_tty):
|
|
self.dont_repeat()
|
|
gui.startup.start_gtk()
|
|
window = gui.logwindow.LogWindow()
|
|
print "Created log window %d; now the default" % window.number
|
|
|
|
class GuiPrintBase(gdb.Command):
|
|
def __init__(self, command):
|
|
super(GuiPrintBase, self).__init__('gui ' + command,
|
|
gdb.COMMAND_SUPPORT)
|
|
self.command = command
|
|
|
|
# Given ARG, return a pair (WINDOW, NEW_ARG).
|
|
def _parse_arg(self, arg, do_default = True):
|
|
arg = arg.strip()
|
|
match = re.match('@(\\d+)\\s+(.*)$', arg)
|
|
if match is not None:
|
|
winno = int(match.group(1))
|
|
arg = match.group(2)
|
|
window = gui.toplevel.state.get(winno)
|
|
if window is None:
|
|
raise gdb.GdbError('could not find window %d' % winno)
|
|
if not isinstance(window, gui.logwindow.LogWindow):
|
|
raise gdb.GdbError('window %d is not a log window' % winno)
|
|
elif do_default:
|
|
window = gui.logwindow.default_log_window
|
|
if window is None:
|
|
raise gdb.GdbError('no default log window')
|
|
else:
|
|
window = None
|
|
return (window, arg)
|
|
|
|
def invoke(self, arg, from_tty):
|
|
(window, arg) = self._parse_arg(arg)
|
|
text = gdb.execute(self.command + ' ' + arg, from_tty, True)
|
|
window.append(text)
|
|
|
|
class GuiPrintCommand(GuiPrintBase):
|
|
def __init__(self):
|
|
super(GuiPrintCommand, self).__init__('print')
|
|
|
|
class GuiOutputCommand(GuiPrintBase):
|
|
def __init__(self):
|
|
super(GuiOutputCommand, self).__init__('output')
|
|
|
|
class GuiPrintfCommand(GuiPrintBase):
|
|
def __init__(self):
|
|
super(GuiPrintfCommand, self).__init__('printf')
|
|
|
|
class GuiDprintfCommand(GuiPrintBase):
|
|
def __init__(self):
|
|
super(GuiDprintfCommand, self).__init__('dprintf')
|
|
|
|
def invoke(self, arg, from_tty):
|
|
(window, arg) = self._parse_arg(arg, False)
|
|
orig_arg = arg
|
|
(ignore, arg) = gdb.decode_line(arg)
|
|
if arg is None:
|
|
raise gdb.GdbError("no printf arguments to 'gui dprintf'")
|
|
arg = arg.strip()
|
|
if not arg.startswith(','):
|
|
raise gdb.GdbError("comma expected after linespec")
|
|
arg = arg[1:]
|
|
spec = arg[0 : -len(arg)]
|
|
DPrintfBreakpoint(spec, window, arg)
|
|
|
|
class InfoWindowsCommand(gdb.Command):
|
|
def __init__(self):
|
|
super(InfoWindowsCommand, self).__init__('info windows',
|
|
gdb.COMMAND_SUPPORT)
|
|
|
|
def invoke(self, arg, from_tty):
|
|
self.dont_repeat()
|
|
gui.toplevel.state.display()
|
|
|
|
class DeleteWindowsCommand(gdb.Command):
|
|
def __init__(self):
|
|
super(DeleteWindowsCommand, self).__init__('delete window',
|
|
gdb.COMMAND_SUPPORT)
|
|
|
|
def invoke(self, arg, from_tty):
|
|
self.dont_repeat()
|
|
winno = int(arg)
|
|
window = gui.toplevel.state.get(winno)
|
|
if window is not None:
|
|
window.destroy()
|
|
|
|
GuiCommand()
|
|
GuiSourceCommand()
|
|
GuiLogWindowCommand()
|
|
GuiPrintCommand()
|
|
GuiOutputCommand()
|
|
GuiPrintfCommand()
|
|
InfoWindowsCommand()
|
|
DeleteWindowsCommand()
|
|
|
|
_can_override = False
|
|
|
|
# A temporary test to see if you have a gdb that supports this.
|
|
class TestCommand(gdb.Command):
|
|
"""A temporary test command created for the GUI.
|
|
This does nothing, the GUI startup code uses it to see if
|
|
your copy of gdb has some command-overriding support."""
|
|
|
|
def __init__(self, set_it):
|
|
super(TestCommand, self).__init__('maint gui-test', gdb.COMMAND_DATA)
|
|
self.set_it = set_it
|
|
|
|
def invoke(self, arg, from_tty):
|
|
if self.set_it:
|
|
global _can_override
|
|
_can_override = True
|
|
else:
|
|
try:
|
|
super(TestCommand, self).invoke(arg, from_tty)
|
|
except:
|
|
pass
|
|
|
|
TestCommand(True)
|
|
TestCommand(False).invoke('', 0)
|
|
|
|
if _can_override:
|
|
class Overrider(gdb.Command):
|
|
def __init__(self, name, event):
|
|
super(Overrider, self).__init__(name, gdb.COMMAND_DATA)
|
|
self.event = event
|
|
|
|
def invoke(self, arg, from_tty):
|
|
super(Overrider, self).invoke(arg, from_tty)
|
|
self.event.post()
|
|
|
|
Overrider('up', gui.events.frame_changed)
|
|
Overrider('down', gui.events.frame_changed)
|
|
Overrider('frame', gui.events.frame_changed)
|