gpt4 book ai didi

python - gdb python 中的 container_of 宏

转载 作者:行者123 更新时间:2023-11-28 22:55:20 42 4
gpt4 key购买 nike

我正在尝试访问内核链表,结构是

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

};

使用 gdb,我可以通过以下方式打印:

(gdb)p *(qlcnic_wait_event_t *)(((struct my_struct *)dev_base->next->priv).wait_list)

输出是:

$17 = {
list = {
next = 0x410026a14ff0,
prev = 0x410026a14ff0
},
comp_id = 0x0,
trigger = 0x0,
active = 0x0,
rsp_word = 0x0 <buses_init at vmkdrivers/src_9/vmklinux_9/linux/drivers/base/bus.c:1061>

要迭代列表,我需要转到 wait_list 的“next”并使用“container_of”获取地址的基础。所以我正在使用 container_of 宏,代码是

#!/usr/bin/env python
import gdb

long_type = None

def get_type(type_name):
t = gdb.lookup_type(type_name)
if t == None:
raise gdb.GdbError("cannot resolve type '%s'" % type_name)
return t

def get_long_type():
global long_type
if long_type == None:
long_type = get_type("long")
return long_type

def offset_of(typeobj, field):
element = gdb.Value(0).cast(typeobj)
return int(str(element[field].address), 16)

def container_of(ptr, typeobj, member):
return (ptr.cast(get_long_type()) - offset_of(typeobj, member)).cast(typeobj)


class ContainerOf(gdb.Function):
__doc__ = "Return pointer to containing data structure.\n" \
"\n" \
"$container_of(PTR, \"TYPE\", \"ELEMENT\"): Given PTR, return a pointer to the\n" \
"data structure of the type TYPE in which PTR is the address of ELEMENT.\n" \
"Note that TYPE and ELEMENT have to be quoted as strings."

def __init__(self):
super(ContainerOf, self).__init__("container_of")

def invoke(self, ptr, typename, elementname):
return container_of(ptr,
gdb.lookup_type(typename.string()).pointer(),
elementname.string())

ContainerOf()
ptr = gdb.parse_and_eval('(qlcnic_wait_event_t *)(((struct my_struct *)dev_base->next->priv).wait_list)').address
print '%s'%(ptr)
c = container_of(ptr,"qlcnic_wait_event_t","list")

完成(gdb) source container_of.py

输出是:

wait_list = {
list = {
next = 0x410026a14ff0,
prev = 0x410026a14ff0
},
comp_id = 0x0,
trigger = 0x0,
active = 0x0,
rsp_word = 0x0 <buses_init at /src_9/linux_9/drivers/base/bus.c:1061>
}
ptr = 0x410026a14ff0
Traceback (most recent call last):
File "container_of.py", line 64, in ?
next = container_of(ptr,"struct qlcnic_wait_event_s","list")
File "container_of.py", line 23, in container_of
return (ptr.cast(get_long_type()) - offset_of(typeobj, member)).cast(typeobj)
File "container_of.py", line 19, in offset_of
element = gdb.Value(0).cast(typeobj)
RuntimeError: Argument must be a type.

为什么它不起作用?如何实现这个 container_of ?

最佳答案

您的代码的问题是 cast() 需要一个 gdb.Type 在这一点,不是一个字符串。调用 gdb.lookup_type() 将修复该部分。

关于offsetof/container_of:目前最方便的方法让它工作是使用 gdb 的宏工具。这只是因为它更容易访问函数或命令。

(gdb) macro define offsetof(_type, _memb) \
((long)(&((_type *)0)->_memb))
(gdb) macro define container_of(_ptr, _type, _memb) \
((_type *)((void *)(_ptr) - offsetof(_type, _memb)))

这可能会进入您的 .gdbinit。

(gdb) print offsetof(struct foo, bar)
...

要在 Python 中使用它,您可以用相同的方式重新实现它您开始使用 gdb.Type/Field 和转换操作,或者再次依赖宏定义:

(gdb) python print gdb.parse_and_eval("offsetof(struct foo, bar)")
...

关于python - gdb python 中的 container_of 宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17024695/

42 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com