Bai*_*wal 4 python gdb coredump 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;
....
....
};
Run Code Online (Sandbox Code Playgroud)
我使用以下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;
....
....
};
Run Code Online (Sandbox Code Playgroud)
我正在使用以下API来打印此结构:(可以假设我有正确的核心转储并添加了正确的符号.
main_struct = gdb.execute('p (*(struct my_struct *)dev_base->priv)')
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')
print netdev
pdev = gdb.parse_and_eval('*(*(struct my_struct *)dev_base->next->priv).pdev')
print pdev
所以我想自动化这些步骤.是否有任何gdb-python API或方法可以迭代结构my_struct并自动打印指针,数组和列表值?
谢谢.
sco*_*ttt 10
struct net_device,struct pci_dev在Linux都意味着要使用的内核,而不是用户空间代码.它们甚至不会在make headers_install与libc 一起使用的已清理的内核头文件中导出.
GDB无法打印struct net_device,struct pci_dev因为它没有描述这些结构定义的调试信息.您的用户空间struct my_struct被声明为具有指向这些结构的不透明指针.我认为你不应该首先这样做.
诀窍是将内核和驱动程序模块的调试信息加载到GDB中:
假设带有调试信息的内核位于/usr/lib/debug/lib/modules/3.9.4-200.fc18.x86_64/vmlinux,请运行:
$ 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
Run Code Online (Sandbox Code Playgroud)
同时使用/ sys/module/MY-DRIVER/sections/下文件的地址替换TEXT-ADDR,DATA-ADDR和BSS-ADDR.(我认为只是说谎并使用地址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 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()
Run Code Online (Sandbox Code Playgroud)
(gdb) source print-struct-follow-pointers.py
(gdb) print-struct-follow-pointers *p
Run Code Online (Sandbox Code Playgroud)
您可以限制打印的嵌入式结构的级别:
(gdb) print-struct-follow-pointers/4 *p
Run Code Online (Sandbox Code Playgroud)