1

How to do it for a c code..? Is it possible..? I read this post. I also want to do similar things but i am not able to use the given updated script at link GDB-Python scripting: any samples iterating through C/C++ struct fields

I followed the following steps to test : my source code name was : test.c and pretty.py

gcc -g test.c

gdb test

(gdb) source pretty.py

(gdb) run

(gdb) print <stcruct object>

How to use this script?

Community
  • 1
  • 1
Baijnath Jaiswal
  • 377
  • 5
  • 17

1 Answers1

3

That script implements a new GDB command, wzd which takes a C structure as argument. You can tell from the Python doc string after class PrintGList

"""print fields of a struct: wzd struct_object
Iterate through the fields of a struct, and display
a human-readable form of the objects."""

You were expecting the script to implement a GDB pretty printer for a custom data type and change what gets printed when you use GDB's print command but that's not how the script is hooked up.

The class name PrintGList suggests that code originated from a script that printed the linked lists in the glib library. Copy and paste coding strikes again ;) I've fixed a few minor bugs and cleaned up the code below (wzd.py):

import gdb

def _type_is_container(t):
    return t.code == gdb.TYPE_CODE_STRUCT

class WZD(gdb.Command):
    '''print fields of a struct: wzd struct_object

Iterate through the fields of a struct, and display
a human-readable form of the objects.'''

    def __init__(self):
        gdb.Command.__init__(self, "wzd", gdb.COMMAND_DATA, gdb.COMPLETE_SYMBOL, True)

    def invoke(self, arg, from_tty):

        arg_list = gdb.string_to_argv(arg)
        if len(arg_list) < 1:
            print "usage: wzd struct"
            return

        n = arg_list[0]
        l = gdb.parse_and_eval(arg_list[0])
        (t, m) = (l.type, l.type.tag)

        print "  variable %s " % n, " type %s " % t

        if l.type.code == gdb.TYPE_CODE_STRUCT:
            print "Found a struct  %s " % n
            self._print_fields(n, t)
        else:
            print "Found no struct"

    def _print_fields(self, n, typeobject):
        print typeobject
        flds = typeobject.fields()
        for x in flds:
            sn = n + "." + x.name
            if _type_is_container(x.type):
                tag_msg = ', tag: %r' % (x.type.tag,)
            else:
                tag_msg = ''
            print '  field %r type %s (code: %s%s)' % (sn, x.type, x.type.code, tag_msg)
            if _type_is_container(x.type):
                print "Found sub level struct  %s " % sn
                sl = gdb.parse_and_eval(sn)
                sm = sl.type.tag
                st = sl.type
                self._print_fields(sn, x.type)

    def _deep_items (self, type_):
        for k, v in type_.iteritems():
            if k:
                print " k v %s " % k , " %s " % v
            else:
                print "   v    ",      " %s " % v

WZD()

Test program (struct-read.c):

#include <assert.h>
#include <stdio.h>

/* https://github.com/scottt/debugbreak */
#include <debugbreak/debugbreak.h>

struct T {
    int x, y;
};

struct S {
    struct T t;
    char b;
};

int main()
{
    int r;
    struct S s;
    r = scanf("%d%d%c", &s.t.x, &s.t.y, &s.b);
    assert(r == 3);
    debug_break();

    return 0;
}

Sample GDB session:

$ echo 1 2 x > in
$ gdb -q -x wzd.py struct-read
<...>

(gdb) run < in
<...>
Program received signal SIGTRAP, Trace/breakpoint trap.
main () at struct-read.c:25
25  }

(gdb) wzd s
  variable s   type struct S 
Found a struct  s 
struct S
  field 's.t' type struct T (code: 3, tag: 'T')
Found sub level struct  s.t 
struct T
  field 's.t.x' type int (code: 8)
  field 's.t.y' type int (code: 8)
  field 's.b' type char (code: 8)
scottt
  • 7,008
  • 27
  • 37
  • @BaijnathJaiswal, you're welcome. I want to stress that the Python code above is really not very well written or clean. If you have a particular data structure you want to process with Python and GDB, consider posting another question on SO if you run into problems. – scottt May 14 '13 at 09:27
  • sure..! and thanks again as your answer was very helpful to me.:-) – Baijnath Jaiswal May 14 '13 at 09:38
  • @ scottt, can we print all the global and local variables(with corresponding values) also in the same ways..? – Baijnath Jaiswal May 14 '13 at 11:11
  • 1
    @BaijnathJaiswal, Yes, see http://stackoverflow.com/a/16268295/676030 and http://stackoverflow.com/a/15312719/676030 – scottt May 14 '13 at 12:01
  • @ scott, thanks. Nice work. but the script in this link http://stackoverflow.com/a/16268295/676030 does not fetch all the global variables. Actually i am looking similar, but want to obtain all global variables(local, if possible) and their values in human readable form. The other link is printing values but it is just an automation of gdb steps i think. – Baijnath Jaiswal May 14 '13 at 14:01
  • @ scottt, Sorry, my observation was wrong, your script in this link http://stackoverflow.com/a/16268295/676030 is fetching all the variables.And using symbol.value() i am able to print the corresponding values also. But the problem is, we need to run the code again `(gdb) start`. Can we extract the same from coredump file (without executing the code again)..? – Baijnath Jaiswal May 15 '13 at 09:26
  • @ scottt, can you please tell me, is it possible to extract stucts and sub-structs without executing binary again..? – Baijnath Jaiswal May 21 '13 at 16:27
  • @BaijnathJaiswal, yes, it's possible. Inspecting data from core files when you have the matching binary with debug info should just work. – scottt May 21 '13 at 17:24