This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] visualizing locals and backtrace in debug session


Hi,

This patch adds new post hooks which dump registers, stack, local
variables on each
step, next, run, finish command. Output goes to ~/gdbout.txt file where can be
watched by 'tail -f ~/gdbout.txt' command in the separate terminal.
Hooks are disabled by default.
auto_enable command enables the hooks.
Implemented using Python API.

Regards,
Serge Voilokov

ChangeLog:

2013-04-24  Serge Voilokov  <voilokov@gmail.com>

 New command 'auto_enable' which sets post hooks on run, step, next
 and finish commands. Hooks dump registers, stack, local variables into
 ~/gdbout.txt file which can be watched by 'tail -f ~/gdbout.txt'.
 * NEWS: New 'auto_enable' command for visualizing runtime info.
 * data-directory/Makefile.in: Add gdb/command/auto_info.py
 * data-directory/Makefile.in: Add gdb/command/auto_info.cmd
 * python/lib/gdb/command/auto_info.py: Implemention of the 'auto_print'
 command using the GDB Python API.
 * python/lib/gdb/command/auto_info.cmd: Register post hooks for run,
 step, next and finish commands which calls auto_print.

Patch:
==================================

diff -urN gdb-7.6.50.20130424/gdb/data-directory/Makefile.in
gdb/gdb/data-directory/Makefile.in
--- gdb-7.6.50.20130424/gdb/data-directory/Makefile.in 2013-01-01
01:32:56.000000000 -0500
+++ gdb/gdb/data-directory/Makefile.in 2013-04-24 15:54:16.000000000 -0400
@@ -61,6 +61,8 @@
  gdb/command/pretty_printers.py \
  gdb/command/prompt.py \
  gdb/command/explore.py \
+ gdb/command/auto_info.py \
+ gdb/command/auto_info.cmd \
  gdb/function/__init__.py \
  gdb/function/strfns.py

diff -urN gdb-7.6.50.20130424/gdb/python/lib/gdb/command/auto_info.cmd
gdb/gdb/python/lib/gdb/command/auto_info.cmd
--- gdb-7.6.50.20130424/gdb/python/lib/gdb/command/auto_info.cmd
1969-12-31 19:00:00.000000000 -0500
+++ gdb/gdb/python/lib/gdb/command/auto_info.cmd 2013-04-24
13:58:47.000000000 -0400
@@ -0,0 +1,15 @@
+define hookpost-step
+auto_print
+end
+
+define hookpost-next
+auto_print
+end
+
+define hookpost-run
+auto_print
+end
+
+define hookpost-finish
+auto_print
+end
diff -urN gdb-7.6.50.20130424/gdb/python/lib/gdb/command/auto_info.py
gdb/gdb/python/lib/gdb/command/auto_info.py
--- gdb-7.6.50.20130424/gdb/python/lib/gdb/command/auto_info.py
1969-12-31 19:00:00.000000000 -0500
+++ gdb/gdb/python/lib/gdb/command/auto_info.py 2013-04-24
14:44:49.000000000 -0400
@@ -0,0 +1,149 @@
+"""GDB hooks for run, step, next, finish commands.
+Hooks print registers, locals and stack to the ~/gdbout.txt file
+at the end of executing each command.
+~/gdbout.txt can be viewed in second terminal tail -f ~/gdbout.txt
+
+run auto_enable at gdb prompt to define hooks or
+put auto_enable into .gdbinit file
+"""
+
+import gdb, os, re, time
+
+out_file = open(os.environ['HOME'] + '/gdbout.txt', 'wt')
+
+def dump_registers(file):
+    print >> file, '\033[1;31m=== registers ===\033[0;0m'
+    v = gdb.parse_and_eval('$rax')
+    print >> file, '$rax: 0x%x (%d)' % (v, v)
+    print >> file, '\n'
+    file.flush()
+
+def dump_stack(file):
+    frame = gdb.selected_frame()
+    print >> file, '\033[1;31m=== stack ' + frame.function().name +
':' + str(frame.function().line) + ' ===\033[0;0m'
+    cnt = 0
+    while frame is not None:
+        fn = frame.function()
+        if fn is None:
+            if frame.name() is None:
+                break
+            print >> file, str(cnt).ljust(3) + str(frame.name()).ljust(60),
+        else:
+            fname = fn.name
+
+            # shorten long boost names
+            fname = fname.replace('boost::asio::', 'bas::')
+            n = fname.rfind('(')
+            if n > 0:
+                fname = fname[:n]
+            if fname.startswith('boost::_bi::bind_t'):
+                fname = 'bbind'
+
+            # compact long names
+            if len(fname) > 60:
+                fname = fname[:29] + '...' + fname[-28:]
+            fname = fname.ljust(60)
+
+            # hilight frame unless system lib
+            if not fn.symtab.filename.startswith('libs/'):
+                fname = '\033[32m' + fname + '\033[0m'
+            print >> file, str(cnt).ljust(3) + fname + ' ' \
+                + os.path.basename(fn.symtab.filename),
+        print >> file, ''
+        cnt += 1
+        frame = frame.older()
+    if cnt < 12:
+        print >> file, ''.ljust(12 - cnt, '\n')
+    file.flush()
+
+def dump_locals(file):
+    print >> file, "\033[1;31m=== locals ===\033[0;0m"
+    f = gdb.selected_frame()
+    r = re.compile('\s+')
+    cnt = 0
+    for x in gdb.selected_frame().block():
+        kind = ''
+        value = ''
+        ctype = ''
+        ccode = ''
+
+        if x.type.code == gdb.TYPE_CODE_STRUCT:
+            ccode = 'S'
+        elif x.type.code == gdb.TYPE_CODE_UNION:
+            ccode = 'U'
+        elif x.type.code == gdb.TYPE_CODE_ENUM:
+            ccode = 'E'
+
+        if x.addr_class == gdb.SYMBOL_LOC_LABEL:
+            kind = 'l'
+            ccode = ' '
+        elif x.is_argument:
+            kind = 'a'
+            value = str(x.value(f))
+            ctype = str(x.type.tag)
+        elif x.is_variable:
+            kind = 'v'
+            value = str(x.value(f))
+        elif x.is_constant:
+            kind = 'c'
+            value = str(x.value(f))
+
+        if ccode == '':
+            ctype = str(x.type)
+        else:
+            ctype = str(x.type.tag)
+
+        value = value.replace('\n', ' ')
+        value = r.sub(' ', value)
+        print >> file, kind, x.print_name.ljust(10)[:10], \
+            ccode.ljust(2), ctype.ljust(20)[:20], \
+            value.rjust(10).ljust(60)[:60]
+        cnt += 1
+
+    if cnt < 12:
+        print >> file, ''.ljust(12 - cnt, '\n')
+    file.flush()
+
+def dump_vars(file, arg):
+    print >> file, "\033[1;31m=== vars ===\033[0;0m"
+    v = gdb.parse_and_eval(arg)
+    print >> file, '%s[%s] = %s' % (arg, v.type, v)
+
+    print >> file, "\033[1;31m===\033[0;0m"
+    file.flush()
+
+
+class print_all_info(gdb.Command):
+    """
+    print registers, stack and locals to the gdbout.txt
+    """
+
+    file = None
+
+    def __init__(self):
+        gdb.Command.__init__(self, "auto_print", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        print >> out_file, ''.ljust(100, '\n')
+        dump_registers(out_file)
+        dump_stack(out_file)
+        dump_locals(out_file)
+
+print_all_info()
+
+class enable_auto_commands(gdb.Command):
+    """
+    enable auto_info hooks
+    """
+
+    file = None
+
+    def __init__(self):
+        gdb.Command.__init__(self, "auto_enable", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        cmd_path = __file__.replace('.pyc', '.cmd').replace('.py', '.cmd')
+        gdb.execute('source ' + cmd_path)
+        print 'auto_info hooks loaded'
+
+enable_auto_commands()


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]