Search code examples
pythoncdebuggingscriptinggdb

GDB: Displaying all the variables in a scope


I'd like to have an opportunity to display and then track step by step all the variables of a given C function with one command.

As I understand, GDB doesn't contain a built-in command like this.

I asked Chat-GPT and it came up with a Python script which is supposed to enable a custom command DISPLAY with the functionality I need:

class DisplayCommand(gdb.Command):
    def __init__(self):
        super(DisplayCommand, self).__init__("DISPLAY", gdb.COMMAND_USER)

    def invoke(self, arg, from_tty):
        frame = gdb.selected_frame()
        block = frame.block()
        while block:
            for sym in block:
                if (sym.is_argument or sym.is_variable) and not sym.is_function and not sym.is_constant:
                    try:
                        gdb.execute("display " + sym.name)
                    except gdb.error:
                        pass
            block = block.superblock

DisplayCommand()

But when I try to use the script in GDB, it doesn't work:

fedor@fedor-Latitude-E7250:~/c$ gdb str_analyzer
...

Reading symbols from str_analyzer...
(gdb) source /home/fedor/gdb_commands/gdb_commands.py
(gdb) start
Temporary breakpoint 1 at 0x12c0: file str_analyzer.c, line 51.
Starting program: /home/fedor/c/str_analyzer 

Temporary breakpoint 1, main () at str_analyzer.c:51
51  {
(gdb) n
53      enum boolean spc = true;
(gdb) 
54      enum boolean word = false;
(gdb) 
55      int curr_wrd_lnght = 0;
(gdb) 
56      int longest_wrd = 0;
(gdb) 
57      int spc_count = 0;
(gdb) 
58      int lngst_spc_sequence = 0;
(gdb) 
59      while ((c=getchar()) != EOF) {
(gdb) 
Hello, world!
60          switch (c) {
(gdb) DISPLAY 
(gdb)

Is there a way to make the script work, or to solve the problem in a different way?

P.S.

fedor@fedor-Latitude-E7250:~/c$ gdb --version
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04.1) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

fedor@fedor-Latitude-E7250:~/c$ gdb --configuration
This GDB was configured as follows:
   configure --host=x86_64-linux-gnu --target=x86_64-linux-gnu
             --with-auto-load-dir=$debugdir:$datadir/auto-load
             --with-auto-load-safe-path=$debugdir:$datadir/auto-load
             --with-expat
             --with-gdb-datadir=/usr/share/gdb (relocatable)
             --with-jit-reader-dir=/usr/lib/gdb (relocatable)
             --without-libunwind-ia64
             --with-lzma
             --with-babeltrace
             --without-intel-pt
             --with-mpfr
             --without-xxhash
             --with-python=/usr (relocatable)
             --without-guile
             --disable-source-highlight
             --with-separate-debug-dir=/usr/lib/debug (relocatable)
             --with-system-gdbinit=/etc/gdb/gdbinit

("Relocatable" means the directory can be moved with the GDB installation
tree, and GDB will still find it.)

Solution

  • I think this does what you want. It uses the pipe command, which was added to GDB a few years ago.

    (gdb) define DISPLAY
      pipe info args -q | awk '{ print "display", $1 }' > ~/display.gdb
      pipe info locals -q | awk '{ print "display", $1 }' >> ~/display.gdb
      source ~/display.gdb
      end