Skip to content

import gdb

Occasionally I see questions about how to import gdb from the ordinary Python interpreter.  This turns out to be surprisingly easy to implement.

First, a detour into PIE and symbol visibility.

“PIE” stands for “Position Independent Executable”.  It uses essentially the same approach as a shared library, except it can be applied to the executable.  You can easily build a PIE by compiling the objects with the -fPIE flag, and then linking the resulting executable with -pie.  Normally PIEs are used as a security feature, but in our case we’re going to compile gdb this way so we can have Python dlopen it, following the usual Python approach: we install it as _gdb.so and add a a module initialization function, init_gdb. (We actually name the module “_gdb“, because that is what the gdb C code creates; the “gdb” module itself is already plain Python that happens to “import _gdb“.)

Why install the PIE rather than make a true shared library?  It is just more convenient — it doesn’t require a lot of configure and Makefile hacking, and it doesn’t slow down the build by forcing us to link gdb against a new library.

Next, what about all those functions in gdb?  There are thousands of them… won’t they possibly cause conflicts at dlopen time?  Why yes… but that’s why we have symbol visibility.  Symbol visibility is an ELF feature that lets us hide all of gdb’s symbols from any dlopen caller.  In fact, I found out during this process that you can even hide main, as ld.so seems to ignore visibility bits for this function.

Making this work is as simple as adding -fvisibility=hidden to our CFLAGS, and then marking our Python module initialization function with __attribute__((visibility("default"))).  Two notes here.  First, it’s odd that “default” means “public”; just one of those mysterious details.  Second, Python’s PyMODINIT_FUNC macro ought to do this already, but it doesn’t; there’s a Python bug.

Those are the low-level mechanics.  At this point gdb is a library, albeit an unusual one that has a single entry point.  After this I needed a few tweaks to gdb’s startup process in order to make it work smoothly.  This too was no big deal.  Now I can write scripts from Python to do gdb things:

#!/usr/bin/python
import gdb
gdb.execute('file ./install/bin/gdb')
print 'sizeof = %d' % gdb.lookup_type('struct minimal_symbol').sizeof

Then:

$ python zz.py
72

Soon I’ll polish all the patches and submit this upstream.

6 Comments

  1. Daniel Jacobowitz wrote:

    Re: main, I don’t think LD is doing anything special; it can have restricted visibility after linking because it’s only referenced from the crt files.

    I’m surprised the tweaks to the startup process were easy, but, nice job :-)

    Thursday, January 2, 2014 at 2:33 pm | Permalink
  2. tom wrote:

    Thanks, Daniel. I hadn’t thought about the crt files, but that makes perfect sense to me.

    Tuesday, January 7, 2014 at 3:11 am | Permalink
  3. Paul wrote:

    Been looking out for something like this for a while.

    I have a script that does a post-mortem analysis of core files at work. That involves two scripts – one to parse command lines, do some general housekeeping, then fire up gdb. Then the “real” code kicks with a python script to do all the hard work.

    Having it all in one script will be so much cleaner.

    Also, getting “import gdb” to operate properly in Eclipse would be a bonus.

    Monday, March 24, 2014 at 8:56 pm | Permalink
  4. peipei wrote:

    Hello:
    Can you tell me the more details on how to make gdb a python module ?

    Thank you in advance!

    Sunday, May 4, 2014 at 3:21 am | Permalink
  5. Tony Wang wrote:

    Hi Tom, I’m using the gdb with python support, but I found one thing quite annoying. That is some time I need to give binary release to other people, but if I enabling gdb with python, those users who haven’t installed python on their host machine will fail to use the binary release. So how about adding a detection mechanism to automatically detect python environment on the host pc?

    Friday, May 9, 2014 at 9:29 am | Permalink
  6. Paul wrote:

    Any idea if this feature will make it into gcc 7.8?

    Had a quick look over at gitorious (https://gitorious.org/binutils-gdb/gdb/commits/8a9ef8d02b7c361e609224f0f1553c7dc4f9e9e3) to check on progress.

    Assuming I was looking in the correct place, the last checkin was in January.

    Friday, June 27, 2014 at 8:00 pm | Permalink

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*