Archive for November, 2008

One annoying aspect of scripting GDB (using it’s own scripting language), is that if you test or set a variable which is not in scope, the script will generate an error and GDB will give up evaluating it. It would be useful to have a way to programatically check if the variable is in scope before trying to use it. There was even at least one try (from the brave Rob Quill) at implementing such a thing posted to the gdb-patches mailing list, but unfortunately as of now it still has some issues and haven’t been committed (I believe this patch is the latest version).

Anyway, this is the kind of thing we want to make easy to do in Python, so I decided to try to implement a solution using what we have in the Python branch. Tom Tromey already created the notion of convenience functions, which are functions that are implemented by GDB  that you can call in places where it accepts expressions, and he made it possible to implement such functions in Python. It follows that one can write a in_scope convenience function in Python which checks if a given variable name is valid in the current scope of the debugged program.

There were some missing pieces which I had to implement to get the in_scope function working (most notably, a method to get a string from a variable in the debugged program), and in the past few days I committed to the branch the patches which add those pieces. So now you can have the following script:

class InScope (gdb.Function):
    """Check if all the given variables or macros are in scope.
       Receives as argument a list of names separated by

    def __init__ (self):
        super (InScope, self).__init__ ("in_scope")

    def invoke (self, var):
        vars = set (var.string().split())
        found = set ()
        pc = gdb.get_selected_frame ().get_pc ()
        block = gdb.get_block_for_pc (pc)
        while block:
            for sym in block:
                if (sym.is_argument ()
                      or sym.is_constant ()
                      or sym.is_function ()
                      or sym.is_variable ()):
                    sym_name = sym.get_print_name ()
                    if sym_name in vars:
                        found.add (sym_name)
            block = block.get_superblock ()

        return vars == found

InScope ()

And use it like this:

Breakpoint 1, main (argc=1, argv=0x7fffffffe208) at /tmp/funcs.c:16
16        int i = 41;
(gdb) if $in_scope("i")
 >print "yay"
 >print "nay"
$1 = "yay"

If you save the script to ~/.gdb-in-scope.py, you can put the following in your ~/.gdbinit to load it automatically:

source ~/.gdb-in-scope.py

Now my goal is to cut out and submit upstream a set of patches to make the above work on regular GDB. The only problem is that I have the boring task of writing testcases and documentation for the code before I can submit it… 🙂

For now, If you want to use this script you can build a GDB from the branch, but be aware that the Python API as provided in the branch is subject to change.

Read Full Post »