gdb-python:解析结构的每个字段,并使用适当的值打印它们(如果存在) [英] gdb-python : Parsing structure's each field and print them with proper value, if exists

查看:499
本文介绍了gdb-python:解析结构的每个字段,并使用适当的值打印它们(如果存在)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个python脚本来自动调试gdb的核心转储。我试图打印包含内核数据结构和列表(例如struct list_head)的数据结构。例如,结构如下所示:

  struct my_struct {
struct my_hardware_context ahw;
struct net_device * netdev;
struct pci_dev * pdev;
struct list_head mac_list;
....
....
};

我正在使用以下API tp打印此结构:

gdb.execute('p(*(struct my_struct *)dev_base-> priv)')



所以我可以打印'struct (仅显示地址)my_struct',struct my_hardware_context ahw,但不包含指针和列表的内容(例如struct net_device * netdev,struct pci_dev * pdev,struct list_head mac_list)。那么如何使用gdb-python脚本打印* netdev,* pdev和mac_list的内容?



编辑:使我的问题更清晰

我正在编写一个python脚本来自动调试gdb的核心转储。我试图打印包含内核数据结构和列表(例如struct list_head)的数据结构。例如,结构如下所示:

  struct my_struct {
struct my_hardware_context ahw;
struct net_device * netdev;
struct pci_dev * pdev;
struct list_head mac_list;
....
....
};

我正在使用以下API来打印此结构:(可以假定我有正确的核心转储并添加了适当的符号。



main_struct = gdb.execute('p(*(struct my_struct *)dev_base-> priv)') / code>



print main_struct



现在它将打印struct my_struct的所有成员的值,但打印到一个级别,这意味着它将打印struct my_hardware_context ahw的全部内容,因为它是一个实例,但不会打印struct net_device * netdev的内容,struct pci_dev * pdev,struct list_head,mac_list等现在手动我需要像下面这样做:

netdev = gdb.parse_and_eval('*(*( struct my_struct *)dev_base-> next-> priv).netdev')
$ b print netdev < code

pdev = gdb.parse_and_eval('*(*(struct my_struct *)dev_base-> next-> priv ).pdev')



print pdev



所以我想自动执行这些步骤。是否有任何gdb-python API或它可以迭代struct my_struct并自动打印指针,数组和列表值的方式?

谢谢。

解决方案

struct net_device来自Linux的 struct pci_dev 是用于内核而不是用户空间的代码。它们甚至不会通过使用libc的 make headers_install 获得的已消毒内核头文件导出。



GDB无法打印 struct net_device struct pci_dev ,因为它没有描述这些结构定义的调试信息。您的用户空间 struct my_struct 被声明为具有指向这些结构的不透明指针。我不认为你应该这样做。

核心转储澄清后的编辑



诀窍是将调试信息从内核和驱动模块加载到GDB中:
$ b



假设带有调试信息的内核位于 / usr / lib / debug /

  $ gdb / usr /lib/debug/lib/modules/3.9.4-200.fc18.x86_64/vmlinux vmcore 
(gdb)添加符号文件MY-DRIVER.ko TEXT-ADDR -s .data DATA-ADDR -s .bss BSS-ADDR

同时替换 TEXT-ADDR DATA-ADDR BSS-ADDR ,其地址来自/ sys / module / MY-D下的文件RIVER /分段/。 (我认为只是撒谎,并使用地址0可能会在这种情况下工作)



验证 ptype struct net_device ptype struct pci_dev ptype my_struct 工作。然后在获得 struct * my_struct 的地址之后,您应该能够打印其内容。



在追随指针时遍历结构

print-struct-follow-pointers.py

  import gdb 

def is_container(v):
c = v.type.code
return(c == gdb.TYPE_CODE_STRUCT或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

如果不是is_container(s):
gdb.write('%s\\\
'%s(s))
返回

if level> = level_limit:
gdb.write('%s {...},\\\
'%( s.type))
返回

对于s.type中的k,gdb.write('%s {\ n'%(s.type,))
。 keys():
v = s [k]
如果is_pointer(v):
gdb.write('%s%s:%s'%(indent,k,v))
try:
v1 = v.dereference()
v1.fetch_lazy()
除了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,\\\
'%(indent,k,v))
gdb.write('%s},\\\
'%(indent,))
$ b $ class PrintStructFollowPointers(gdb.Command):
'''
print- struct-follow-pointers [/ LEVEL_LIMIT] STRUCT-VALUE
'''
def __init __(self):
super(PrintStructFollowPointers,self).__ init __(
'print-struct
gdb.COMMAND_DATA,gdb.COMPLETE_SYMBOL,False)

def invoke(self,arg,from_tty):
s = arg.find('/' )
如果s == -1:
(expr,limit)=(arg,3)
else:
如果arg [:s] .strip():
(expr,limit)=(arg,3 )
else:
i = s + 1
for enumerate(arg [s + 1:],s + 1)中的(i,c):
如果不是c.isdigit ():
break
end = i
digits = arg [s + 1:end]
try:
limit = int(digits)
ValueError:
raise gdb.GdbError(PrintStructFollowPointers .__ doc__)
(expr,limit)=(arg [end:],limit)
try:
v = gdb.parse_and_eval(expr )
除了gdb.error,e:
raise gdb.GdbError(e.message)

print_struct_follow_pointers(v,limit)

PrintStructFollowPointers()



示例会话



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

您可以限制嵌入的str的级别印刷版:

 (gdb)print-struct-follow-pointers / 4 * p 


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_head). For example the structure is something like this:

struct my_struct {
  struct my_hardware_context ahw;
  struct net_device *netdev;
  struct pci_dev *pdev;
  struct list_head mac_list;
  ....
  ....
};

i am using following API tp print this structure:

gdb.execute('p (*(struct my_struct *)dev_base->priv)')

so i am able to print the content of 'struct my_struct' , struct my_hardware_context ahw, but not the content of pointers and list ( e.g. struct net_device *netdev, struct pci_dev *pdev, struct list_head mac_list) automatically (only address is printed). So how to print the content of *netdev, *pdev and mac_list using gdb-python script?

EDITED : to make my question more clear

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_head). For example the structure is something like this:

struct my_struct {
   struct my_hardware_context ahw;
   struct net_device *netdev;
   struct pci_dev *pdev;
   struct list_head mac_list;
   ....
   ....
};

i am using following API to print this structure: (it can be assumed that i have right core dump and added proper symbols.

main_struct = gdb.execute('p (*(struct my_struct *)dev_base->priv)')

print main_struct

Now it will print the values of all members of struct my_struct but upto one level , meaning it will print the whole content of struct my_hardware_context ahw because it is an instance but it will not print the content of struct net_device *netdev, struct pci_dev *pdev, struct list_head mac_list etc. so now manually i need to do it like below:

netdev = gdb.parse_and_eval('*(*(struct my_struct *)dev_base->next->priv).netdev')

print netdev

pdev = gdb.parse_and_eval('*(*(struct my_struct *)dev_base->next->priv).pdev')

print pdev

so i want to automate these steps. Is there any gdb-python API or way by which it can iterate the struct my_struct and print the pointers, arrays and lists values also automatically?

Thanks.

解决方案

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:

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

这篇关于gdb-python:解析结构的每个字段,并使用适当的值打印它们(如果存在)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆