title: container_of macro in gdb python
body: <p>i am trying to access kernel linked list, the structure is</p>
  
  <pre><code>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;
  ....
  ....
  </code></pre>
  
  <p>};</p>
  
  <p>using gdb, i am able to print this in following way:</p>
  
  <p><code>(gdb)p *(qlcnic_wait_event_t *)(((struct my_struct *)dev_base-&gt;next-&gt;priv).wait_list)</code></p>
  
  <p>Output is:</p>
  
  <pre><code>$17 = {
  list = {
    next = 0x410026a14ff0,
    prev = 0x410026a14ff0
  },
  comp_id = 0x0,
  trigger = 0x0,
  active = 0x0,
  rsp_word = 0x0 &lt;buses_init at vmkdrivers/src_9/vmklinux_9/linux/drivers/base/bus.c:1061&gt;
  </code></pre>
  
  <p>}</p>
  
  <p>to iterate the list, i need to go to 'next' of <code>wait_list</code> and using 'container_of', get base the address. so i am using container_of Macro, code is</p>
  
  <pre><code>#!/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-&gt;next-&gt;priv).wait_list)').address
  print '%s'%(ptr)
  c = container_of(ptr,"qlcnic_wait_event_t","list")
  </code></pre>
  
  <p>After doing <code>(gdb) source container_of.py</code></p>
  
  <p>The output is:</p>
  
  <pre><code>wait_list = {
   list = {
     next = 0x410026a14ff0,
     prev = 0x410026a14ff0
   },
   comp_id = 0x0,
   trigger = 0x0,
   active = 0x0,
   rsp_word = 0x0 &lt;buses_init at /src_9/linux_9/drivers/base/bus.c:1061&gt;
  }
  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.
  </code></pre>
  
  <p>why is it not working ?How to implement this container_of ?</p>