gdb-python : Parsing structure's each field and print them with proper value, if exists

后端 未结 1 981
隐瞒了意图╮
隐瞒了意图╮ 2021-01-03 05:18

I am writing a python script to automate debugging core dump from gdb. i am trying to print data structure which includes kernel data structures and lists(e.g. struct list_h

相关标签:
1条回答
  • 2021-01-03 05:50

    struct net_device, struct pci_dev from Linux are meant to be used by kernel and not userspace code. They're not even exported in the sanitized kernel headers you get with make headers_install for use with libc.

    GDB can't print struct net_device, struct pci_dev because it doesn't have debug info describing the definition of those structures. Your userspace struct my_struct is declared to have opaque pointers to those structures. I don't think you should be doing that in the first place.

    Edit After Core Dump Clarification

    The trick is loading debug info from both the kernel and your driver module into GDB:

    • Grab a kernel with debuginfo (CONFIG_DEBUG_INFO). e.g. for Centos, get the matching kernel-debuginfo package from http://debuginfo.centos.org/6/x86_64/.
    • Get the .text, .data and .bss load addresses of your driver module by inspecting /sys/module/MY-DRIVER/sections/{.text,.data,.bss} from a system running your driver under normal operation.

    Assuming the kernel with debug info is located at /usr/lib/debug/lib/modules/3.9.4-200.fc18.x86_64/vmlinux, run:

    $ gdb /usr/lib/debug/lib/modules/3.9.4-200.fc18.x86_64/vmlinux vmcore
    (gdb) add-symbol-file MY-DRIVER.ko TEXT-ADDR -s .data DATA-ADDR -s .bss BSS-ADDR
    

    while replacing TEXT-ADDR, DATA-ADDR and BSS-ADDR with the address from the files under /sys/module/MY-DRIVER/sections/. (I think just lying and using an address of 0 would probably work in this case)

    Verify that ptype struct net_device, ptype struct pci_dev, ptype my_struct work. Then after obtaining the address of a struct *my_struct the way you did before you should be able print its contents.

    Traversing a Struct While Following Pointers

    print-struct-follow-pointers.py

    import gdb
    
    def is_container(v):
        c = v.type.code
        return (c == gdb.TYPE_CODE_STRUCT or c == gdb.TYPE_CODE_UNION)
    
    def is_pointer(v):
        return (v.type.code == gdb.TYPE_CODE_PTR)
    
    def print_struct_follow_pointers(s, level_limit = 3, level = 0):
        indent = ' ' * level
    
        if not is_container(s):
            gdb.write('%s\n' % (s,))
            return
    
        if level >= level_limit:
            gdb.write('%s { ... },\n' % (s.type,))
            return
    
        gdb.write('%s {\n' % (s.type,))
        for k in s.type.keys():
            v = s[k]
            if is_pointer(v):
                gdb.write('%s %s: %s' % (indent, k, v))
                try:
                    v1 = v.dereference()
                    v1.fetch_lazy()
                except gdb.error:
                    gdb.write(',\n')
                    continue
                else:
                    gdb.write(' -> ')
                print_struct_follow_pointers(v1, level_limit, level + 1)
            elif is_container(v):
                gdb.write('%s %s: ' % (indent, k))
                print_struct_follow_pointers(v, level_limit, level + 1)
            else:
                gdb.write('%s %s: %s,\n' % (indent, k, v))
        gdb.write('%s},\n' % (indent,))
    
    class PrintStructFollowPointers(gdb.Command):
        '''
        print-struct-follow-pointers [/LEVEL_LIMIT] STRUCT-VALUE
        '''
        def __init__(self): 
            super(PrintStructFollowPointers, self).__init__(
                'print-struct-follow-pointers',
                gdb.COMMAND_DATA, gdb.COMPLETE_SYMBOL, False)
    
        def invoke(self, arg, from_tty):
            s = arg.find('/')
            if s == -1:
                (expr, limit) = (arg, 3)
            else:
                if arg[:s].strip():
                    (expr, limit) = (arg, 3)
                else:
                    i = s + 1
                    for (i, c) in enumerate(arg[s+1:], s + 1):
                        if not c.isdigit():
                            break
                    end = i
                    digits = arg[s+1:end]
                    try:
                        limit = int(digits)
                    except ValueError:
                        raise gdb.GdbError(PrintStructFollowPointers.__doc__)
                    (expr, limit) = (arg[end:], limit)
            try:
                v = gdb.parse_and_eval(expr)
            except gdb.error, e:
                raise gdb.GdbError(e.message)
    
            print_struct_follow_pointers(v, limit)
    
    PrintStructFollowPointers()
    

    Sample Session

    (gdb) source print-struct-follow-pointers.py
    (gdb) print-struct-follow-pointers *p
    

    You can limit the levels of embedded structures printed:

    (gdb) print-struct-follow-pointers/4 *p
    
    0 讨论(0)
提交回复
热议问题