WatchPoint
How to Write User-Defined GDB Commands in Python?
Last time we looked at user-defined commands in the GDB command-line. In this GDB tutorial, we look at writing our user-defined functions in Python. The advantage of creating user-defined commands in Python is that you can automate a more complicated task or something that you might want to check into source control and share with your teammates. Using Python is more robust too; it’s more extensible and although a bit more work, it gives you better results in multiple ways. Let’s start with the initial boilerplate for our Python code. We write it in a file; bugreport.py. We create a class which we call BugReport, and we inherit it from the We give it a docstring, so you get an inbuilt type of help in the GDB command-line. We need to give it a constructor. We call a superclass constructor; we give it a name and a command. There are different command-classes, for example, maintenance commands, obscure commands and various others. We go with We make a function that we call invoke, which is where the magic happens. This function takes an Finally, we need to instantiate one of these classes; otherwise, nothing is going to happen. Now from the GDB command-line, you can Watch my video for this GDB tutorial to see how these few lines of Python code create a simple user-defined command for a bug report and with help text too. Cool! In part 1 of this GDB tutorial series, you may recall that we sorted pagination with a bit of a hack; we just turned pagination off with a “hammer.” The problem with that is that we must not forget to turn it back on, otherwise, that could potentially cause some confusion. But what if the user had themselves already elected to turn pagination off? Happily, now we’ve got Python so we can do things properly. We could, for example, add pagination to our invoke function to ensure we end the command with pagination turned on or off, whatever your preference. The There is a better way with Check out my video to see how this code for pagination works. You may find it helpful if the bug report output went straight into a file, so let’s do that now. We could do a simple Note: Make sure you open the file for writing; adding “w”. Also, use Watch the video to see how this code for file logging works. To help you get started quickly, create a file, for example, mybugreport.py. Copy and paste the final Python code. Done! I hope you found this GDB tutorial a useful introduction to user-defined commands in GDB, and that it motivates you to start creating your user-defined commands. In my next GDB tutorial, we’ll look at how to use the Don’t forget to watch, subscribe, like, and share my video. Good luck debugging. GDB TrainingBoilerplate to get you started
$ vim bugreport.py
gdb.command
class.class BugReport (gdb.Command):
"""Collect required info for a bug report"""
COMMAND_USER
.def__init__(self):
super(BugReport, self).__init__("bugreport", gdb.COMMAND_USER)
arg
, which is just a string that contains all the arguments. It also has a boolean from_tty
, so we know whether it ran from a script or the command line. The body of the function is not terribly interesting for this GDB tutorial, let’s just have it get a backtrace of all threads and the kernel version.def invoke(self, arg, from_tty):
gdb.execute(“thread apply all backtrace full”)
import os
os.system(“uname -a”)
BugReport()
source bugreport.py
and hey presto, you have a new command called bugreport
.Pagination on/off?
def invoke(self, arg, from_tty):
pagination = gdb.execute("show pagination", to_string=True).endswith("on.\n")
if pagination: gdb.execute("set pagination off")
gdb.execute('thread apply all backtrace full')
import os
os.system('uname -a')
if pagination: gdb.execute("set pagination on")
to_string=True
is a handy little thing that executes the command but returns a string rather than writes it to the console.gdb.parameter()
.def invoke(self, arg, from_tty):
pagination = gdb.parameter("pagination")
if pagination: gdb.execute("set pagination off")
gdb.execute('thread apply all backtrace full')
import os
os.system('uname -a')
if pagination: gdb.execute("set pagination on")
Write bug report output to a file
gdb.execute("set logging file")
, but we are writing in Python, why not do this a little bit more cleanly?def invoke(self, arg, from_tty):
pagination = gdb.parameter("pagination")
if pagination: gdb.execute("set pagination off")
f = open("/tmp/bugreport.txt", "w")
f.write(gdb.execute("thread apply all backtrace full", to_string=True))
f.close()
import os
os.system("uname -a >> /tmp/bugreport.txt")
if pagination: gdb.execute("set pagination on")
to_string=True
again to write the output to a string, not to the console.Final Python code
$ vim mybugreport.py
import os
class BugReport (gdb.Command):
"""Collect required info for a bug report"""
def__init__(self):
super(BugReport, self).__init__("bugreport", gdb.COMMAND_USER)
def invoke(self, arg, from_tty):
pagination = gdb.parameter("pagination")
if pagination: gdb.execute("set pagination off")
f = open("/tmp/bugreport.txt", "w")
f.write(gdb.execute("thread apply all backtrace full", to_string=True))
f.close()
os.system("uname -a >> /tmp/bugreport.txt")
if pagination: gdb.execute("set pagination on")
BugReport()
hook command
in user-defined commands; both in the GDB command-line and in Python.
Master GDB and save time debugging complex codebases
Learn more »
Want debugging tips directly in your inbox?
Share this tutorial