3

カーネル リンク リストにアクセスしようとしていますが、構造は次のとおりです。

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「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 を実装する方法は?

4

4 に答える 4

0

何が問題なのかを確認するために、このコードにデバッグ プリントを追加する必要があります。最初の読み取りでは問題ないように見えますが、「offset_of」に出力すると、「キャスト」する引数のタイプを簡単に確認できます。

この行は奇妙だと思いました:

return int(str(element[field].address), 16)

代わりにこれを行うことができるようです:

return int(element[field].address)
于 2013-06-14T13:17:49.100 に答える