9. Scripting gdb

So far we’ve concentrated on way to use Python to extend gdb: writing new commands, writing new functions, and customized pretty-printing.  In this post I want to look at gdb from a different angle: as a library.  I’ve long thought it would be pretty useful to be able to use gdb as a kind of scriptable tool for messing around with running programs, or even just symbol tables and debug info; the Python work enables this.

One word of warning before we begin: we’re starting to get into the work-in-progress parts of python-gdb.  If you play around here, don’t be surprised if it is not very polished.  And, as always, we’re interested in your feedback; drop us a line on the Archer list.

For historical and technical reasons, it is pretty hard to turn gdb into an actual loadable Python library.  This might be nice to do someday; meanwhile we’ve made it possible to invoke gdb as an interpreter: add the “-P” (or “--python“) option.  Anything after this option will be passed to Python as sys.argv.  For example, try this script:

#!/home/YOURNAME/archer/install/bin/gdb -P
print "hello from python"

Ok… so far so good.  Now what?  How about a little app to print the size of a type?

#!/home/YOURNAME/archer/install/bin/gdb -P
import sys
import gdb
gdb.execute("file " + sys.argv[1])
type = gdb.Type (sys.argv[0])
print "sizeof %s = %d" % (sys.argv[0], type.sizeof ())

You can script that with gdb today, though the invocation is uglier unless you write a wrapper script.  More complicated examples are undeniably better.  For instance, you can write a “pahole” clone in Python without much effort.

That invocation of gdb.execute is a bit ugly.  In the near future (I was going to do it last week, but I got sick) we are going to add a new class to represent the process (and eventually processes) being debugged.  This class will also expose some events related to the state of the process — e.g., an event will be sent when the process stops due to a signal.

The other unfinished piece in this area is nicer I/O control.  The idea here is to defer gdb acquiring the tty until it is really needed.  With these two pieces, you could run gdb invisibly in a pipeline and have it bring up the CLI only if something goes wrong.

It will look something like:

#!/home/YOURNAME/archer/install/bin/gdb -P
import sys
import gdb

def on_stop(p):
  (status, value) = p.status
  if status != gdb.EXIT:
    gdb.cli ()
  else:
    sys.exit (value)

process = gdb.Inferior(sys.argv)
process.connect ("stop", on_stop)
process.run ()

I’ll probably use python-gobject-like connect calls, unless Python experts speak up and say I should do something different.

The next post will cover a flashier use of Python in gdb.  Stay tuned.

17 Comments

  • Sweet,

    Do you know if this kind of scripting can be hooked up to the “crash” utility ?

  • I’m afraid I don’t know.
    I don’t see why not, though.

  • Very interesting! I tried to build the archer gdb tarball
    with “./configure –with-python”; but the produced gdb
    doesn’t recognize “-P” or “–python” option. What might be
    missing? Thanks, -Yan

    —————————————————–
    $ ./gdb -P
    ./gdb: unrecognized option `-P’
    Use `./gdb –help’ for a complete list of options.
    $ ./gdb –python [1]
    ./gdb: unrecognized option `–python’
    Use `./gdb –help’ for a complete list of options.

  • yzc – I don’t think we’ve made an “archer gdb tarball”.
    Where did you get it?

    Also, for best results, send email to the archer list.
    You don’t have to be a member.

  • I first tried to use the git client, but it didn’t
    work when I tried “git clone git://sourceware.org/git/archer.git”
    or “git clone ssh://sourceware.org/git/archer.git”.
    Then I went to http://sourceware.org/git/gitweb.cgi?p=archer.git,
    picked http://sourceware.org/git/gitweb.cgi?p=archer.git;a=snapshot;h=ad88187efac2686ec0b15c558e05262a003ba504;sf=tbz2

    So, guess the one with python support can only be
    obtained with git?

  • Right, you have to use git and you must check out the correct branch.
    See the archer pages on the gdb wiki for more information on how to do that.

  • I was trying out the python support in gdb today. Great work so far! At last we will be able to do the custom debugger for our platform that we have wanted for a while. “GDB as a module” makes a lot of sense.

    I tried running our old python hack that communicates with gdb through a subprocess through gdb -P just to see what would happen and it immediatly stumbled upon the fact that argv[0] is not set to the script name. This makes it incompatible with some pretty useful modules like the OptionParser.

    And by the way, if there is a better way to report a bug, please let me know! :)

    As I said, great work so far!

  • Unless I am mistaken it seems that support for controlling processes and catching events has not yet been merged.

    The closest I can find is the patches submitted by Oguz Kayral in August http://sourceware.org/ml/archer/2009-q3/msg00148.html which do not seem to be merged into git yet. I will be looking forward to this getting added. :)

  • [...] wrote a little about events in gdb-python post #9 — but a lot has changed since then.  A Google SoC student, Oguz Kayral, wrote better support [...]

  • Hello Tom,

    first of all thank you for your great work, python scripting is a great feature in GDB!

    I have a question which I would like to ask you at this place: How can I get an iterator over the global symbol table without having a valid stack frame? I want to write a script which prints out some information on global symbols from within .gdbinit, before execution has been started. I am using GDB 7.5.

    Any hint on this would be greatly appreciated!

    Michael.

  • @Michael – there may not be a way right now. I think symbol table iteration is not very well supported yet. Please file a bug.

  • Hi!

    Any reason why the –python option is still not present in current gdb?

  • Just that nobody has gotten around to upstreaming it yet.

  • Hi,
    This may sound like a stupid question but I was wondering if I needed to install any libraries in order to create/run the python script. Is there anything additional that I have to install to run gdb commands?
    Thanks!

  • Hello Tom,
    I’m working with GDB(currently 7.3, planning to move to 7.8) for quite a long time and absolutely like the Python API, but there are few things that I can’t figure out:
    1. Is it possible to stop current thread using Python API (instead of using -exec-interrupt)?
    2. When the process is running, all new breakpoints become PENDING (even if created by gdb.Breakpoint(…)). After stopping the program they does not become valid. Is there any way to solve this problem using Python API? Currently I’m traping the thread and only after recieving stop event adding the breakpoint.
    3. Is it possible to force process all pending events without leaving the context? Something like “ProcessEvents” function that will return only after processing all events.
    Your blog helped me a lot, Thank you Very Much!

  • Hi. I’m not sure if I have the best answers, but here goes.

    1. It’s not really readily possible right now. You can maybe send a signal to the thread. Or maybe if you are in “target async” mode (with a very new gdb and the right host, this is the default now) you could use the “interrupt” command — though IIRC it is still a bit odd to use somehow. This is a hole in the Python API. I’d recommend filing a bug, if there isn’t one already.

    2. There’s already a bug about controlling the “pending” bit from Python. However it sounds like what you want is “pending” — this just means that the breakpoint can’t be resolved yet, but gdb will try again as shared libraries are loaded.

    3. There’s no way to re-enter the event loop. Right now you have to write in the asynchronous style — post another event to the queue that does the follow-up work.

Join the Discussion

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>