Exemplo n.º 1
0
def for_each_disk(prog: Program) -> Iterator[Object]:
    """
    Iterate over all disks in the system.

    :return: Iterator of ``struct gendisk *`` objects.
    """
    # Before Linux kernel commit 0d02129e76ed ("block: merge struct
    # block_device and struct hd_struct") (in v5.11), partition devices are in
    # struct hd_struct::__dev. After that commit, they are in struct
    # block_device::bd_device. We start by assuming that the kernel has this
    # commit and fall back to the old path if that fails.
    have_bd_device = True
    for device in _for_each_block_device(prog):
        if have_bd_device:
            try:
                bdev = container_of(device, "struct block_device", "bd_device")
            except LookupError:
                have_bd_device = False
            else:
                if bdev.bd_partno == 0:
                    yield bdev.bd_disk
                continue
        part = container_of(device, "struct hd_struct", "__dev")
        if part.partno == 0:
            yield container_of(part, "struct gendisk", "part0")
Exemplo n.º 2
0
def css_next_child(pos: Object, parent: Object) -> Object:
    """
    Get the next child (or ``NULL`` if there is none) of the given parent
    starting from the given position (``NULL`` to initiate traversal).

    :param pos: ``struct cgroup_subsys_state *``
    :param parent: ``struct cgroup_subsys_state *``
    :return: ``struct cgroup_subsys_state *``
    """
    if not pos:
        next_ = container_of(
            parent.children.next, "struct cgroup_subsys_state", "sibling"
        )
    elif not (pos.flags & pos.prog_["CSS_RELEASED"]):
        next_ = container_of(pos.sibling.next, "struct cgroup_subsys_state", "sibling")
    else:
        serial_nr = pos.serial_nr.value_()  # Read once and cache.
        for next_ in list_for_each_entry(
            "struct cgroup_subsys_state", parent.children.address_of_(), "sibling"
        ):
            if next_.serial_nr > serial_nr:
                break

    if next_.sibling.address_of_() != parent.children.address_of_():
        return next_
    return NULL(next_.prog_, "struct cgroup_subsys_state *")
Exemplo n.º 3
0
def print_auxiliary_device(device):
    auxiliary_device = container_of(device, "struct auxiliary_device", "dev")
    #     print(auxiliary_device.id)
    driver_data = auxiliary_device.dev.driver_data
    print("driver_data %x" % driver_data)

    mlx5_adev = container_of(auxiliary_device, "struct mlx5_adev", "adev")
    #     print(mlx5_adev)
    #     print("%x" % mlx5_adev.idx)
    #     print("%x" % mlx5_adev.mdev)
    print("mlx5_core_dev device name: %-20s" %
          mlx5_adev.mdev.device.kobj.name.string_().decode())
    print('')
Exemplo n.º 4
0
Arquivo: list.py Projeto: cneira/drgn
def list_prev_entry(pos, member):
    """
    .. c:function:: type *list_prev_entry(type *pos, member)

    Return the previous entry in a list.
    """
    return container_of(getattr(pos, member).prev, pos.type_.type, member)
Exemplo n.º 5
0
Arquivo: list.py Projeto: cneira/drgn
def list_next_entry(pos, member):
    """
    .. c:function:: type *list_next_entry(type *pos, member)

    Return the next entry in a list.
    """
    return container_of(getattr(pos, member).next, pos.type_.type, member)
Exemplo n.º 6
0
Arquivo: pid.py Projeto: osandov/drgn
def for_each_pid(prog_or_ns: Union[Program, Object]) -> Iterator[Object]:
    """
    Iterate over all PIDs in a namespace.

    :param prog_or_ns: ``struct pid_namespace *`` to iterate over, or
        :class:`Program` to iterate over initial PID namespace.
    :return: Iterator of ``struct pid *`` objects.
    """
    if isinstance(prog_or_ns, Program):
        prog = prog_or_ns
        ns = prog_or_ns["init_pid_ns"].address_of_()
    else:
        prog = prog_or_ns.prog_
        ns = prog_or_ns
    if hasattr(ns, "idr"):
        for nr, entry in idr_for_each(ns.idr):
            yield cast("struct pid *", entry)
    else:
        pid_hash = prog["pid_hash"]
        for i in range(1 << prog["pidhash_shift"].value_()):
            for upid in hlist_for_each_entry("struct upid",
                                             pid_hash[i].address_of_(),
                                             "pid_chain"):
                if upid.ns == ns:
                    yield container_of(upid, "struct pid",
                                       f"numbers[{int(ns.level)}]")
Exemplo n.º 7
0
Arquivo: pid.py Projeto: sukidoke/drgn
def for_each_pid(prog_or_ns):
    """
    .. c:function:: for_each_pid(struct pid_namespace *ns)

    Iterate over all of the PIDs in the given namespace. If given a
    :class:`Program` instead, the initial PID namespace is used.

    :return: Iterator of ``struct pid *`` objects.
    """
    if isinstance(prog_or_ns, Program):
        prog = prog_or_ns
        ns = prog_or_ns['init_pid_ns'].address_of_()
    else:
        prog = prog_or_ns.prog_
        ns = prog_or_ns
    if hasattr(ns, 'idr'):
        for nr, entry in idr_for_each(ns.idr):
            yield cast('struct pid *', entry)
    else:
        pid_hash = prog['pid_hash']
        for i in range(1 << prog['pidhash_shift'].value_()):
            for upid in hlist_for_each_entry('struct upid',
                                             pid_hash[i].address_of_(),
                                             'pid_chain'):
                if upid.ns == ns:
                    yield container_of(upid, 'struct pid',
                                       f'numbers[{int(ns.level)}]')
Exemplo n.º 8
0
def hash(rhashtable, type, member):
    nodes = []

    tbl = rhashtable.tbl

    #     print('')
    #     print("rhashtable %lx" % rhashtable.address_of_())
    #     print("bucket_table %lx" % tbl)
    #     buckets = tbl.buckets
    #     print("buckets %lx" % buckets.address_of_())

    buckets = tbl.buckets
    size = tbl.size.value_()

    print("")
    for i in range(size):
        rhash_head = buckets[i]
        if type_exist("struct rhash_lock_head"):
            rhash_head = cast("struct rhash_head *", rhash_head)
            if rhash_head.value_() == 0:
                continue
        while True:
            if rhash_head.value_() & 1:
                break
            obj = container_of(rhash_head, type, member)
            nodes.append(obj)
            rhash_head = rhash_head.next

    return nodes
Exemplo n.º 9
0
def find_pid(prog_or_ns, nr):
    """
    .. c:function:: struct pid *find_pid(struct pid_namespace *ns, int nr)

    Return the ``struct pid *`` for the given PID number in the given
    namespace. If given a :class:`Program` instead, the initial PID namespace
    is used.
    """
    if isinstance(prog_or_ns, Program):
        prog = prog_or_ns
        ns = prog_or_ns['init_pid_ns'].address_of_()
    else:
        prog = prog_or_ns.prog_
        ns = prog_or_ns
    if hasattr(ns, 'idr'):
        return cast('struct pid *', idr_find(ns.idr, nr))
    else:
        # We could implement pid_hashfn() and only search that bucket, but it's
        # different for 32-bit and 64-bit systems, and it has changed at least
        # once, in v4.7. Searching the whole hash table is slower but
        # foolproof.
        pid_hash = prog['pid_hash']
        for i in range(1 << prog['pidhash_shift'].value_()):
            for upid in hlist_for_each_entry('struct upid',
                                             pid_hash[i].address_of_(),
                                             'pid_chain'):
                if upid.nr == nr and upid.ns == ns:
                    return container_of(upid, 'struct pid',
                                        f'numbers[{ns.level.value_()}]')
        return NULL(prog, 'struct pid *')
Exemplo n.º 10
0
def get_mlx5_core_devs():
    devs = {}

    bus_type = prog["pci_bus_type"]
    subsys_private = bus_type.p
    k_list = subsys_private.klist_devices.k_list

    for dev in list_for_each_entry('struct device_private',
                                   k_list.address_of_(), 'knode_bus.n_node'):
        addr = dev.value_()
        device_private = Object(prog, 'struct device_private', address=addr)
        device = device_private.device

        # struct pci_dev {
        #     struct device dev;
        # }
        pci_dev = container_of(device, "struct pci_dev", "dev")

        driver_data = device.driver_data
        mlx5_core = Object(prog, 'struct mlx5_core_dev', address=driver_data)
        driver = device.driver
        if driver_data.value_():
            name = driver.name.string_().decode()
            if name == "mlx5_core":
                pci_name = device.kobj.name.string_().decode()
                index = pci_name.split('.')[1]
                devs[int(index)] = mlx5_core

    return devs
Exemplo n.º 11
0
def rb_find(
    type: Union[str, Type],
    root: Object,
    member: str,
    key: KeyType,
    cmp: Callable[[KeyType, Object], int],
) -> Object:
    """
    Find an entry in a red-black tree given a key and a comparator function.

    Note that this function does not have an analogue in the Linux kernel
    source code, as tree searches are all open-coded.

    :param type: Entry type.
    :param root: ``struct rb_root *``
    :param member: Name of ``struct rb_node`` member in entry type.
    :param key: Key to find.
    :param cmp: Callback taking key and entry that returns < 0 if the key is
        less than the entry, > 0 if the key is greater than the entry, and 0 if
        the key matches the entry.
    :return: ``type *`` found entry, or ``NULL`` if not found.
    """
    prog = root.prog_
    type = prog.type(type)
    node = root.rb_node.read_()
    while node:
        entry = container_of(node, type, member)
        ret = cmp(key, entry)
        if ret < 0:
            node = node.rb_left.read_()
        elif ret > 0:
            node = node.rb_right.read_()
        else:
            return entry
    return NULL(prog, prog.pointer_type(type))
Exemplo n.º 12
0
def print_sock(nsock):
    print("\tportid    : %x" % nsock.portid)
    #     print("\tdst_portid: %x" % nsock.dst_portid)  # all 0
    sock = nsock.sk
    print("\tsock %lx" % sock.address_of_().value_())
    head = sock.sk_wq.wait.head
    print("\tsk_data_ready: %s" % lib.address_to_name(hex(sock.sk_data_ready)))
    print("")
    #     print(head)
    if 1:
        return
    for entry in list_for_each_entry('struct wait_queue_entry',
                                     head.address_of_(), 'entry'):
        print("\twait_queue_entry %lx" % entry.value_())
        print("\twait_queue_entry.flags %d" % entry.flags.value_())
        eppoll_entry = container_of(entry, "struct eppoll_entry", 'wait')
        print("\teppoll_entry %lx" % eppoll_entry)
        epitem = eppoll_entry.base
        print("\tepitem %lx" % epitem)
        event = epitem.event
        ffd = epitem.ffd
        print("\tepoll_filefd %lx" % ffd.address_of_().value_())
        if entry.flags.value_():
            print("\tfd: %d" % ffd.fd.value_())
            print("\tfile: %lx" % ffd.file)

            # 10000019
            # EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLWAKEUP
            print("\tevents: %x" % event.events)
            print("\tdata: %x" % event.data)
        func = entry.func
        print("\t%s" % lib.address_to_name(hex(func)))
        print("")
Exemplo n.º 13
0
Arquivo: fs.py Projeto: osandov/drgn
def d_path(  # type: ignore  # Need positional-only arguments.
        path_or_vfsmnt: Object,
        dentry: Optional[Object] = None) -> bytes:
    if dentry is None:
        vfsmnt = path_or_vfsmnt.mnt
        dentry = path_or_vfsmnt.dentry.read_()
    else:
        vfsmnt = path_or_vfsmnt
        dentry = dentry.read_()
    mnt = container_of(vfsmnt, "struct mount", "mnt")

    d_op = dentry.d_op.read_()
    if d_op and d_op.d_dname:
        return b"[" + dentry.d_inode.i_sb.s_type.name.string_() + b"]"

    components = []
    while True:
        if dentry == mnt.mnt.mnt_root:
            mnt_parent = mnt.mnt_parent.read_()
            if mnt == mnt_parent:
                break
            dentry = mnt.mnt_mountpoint.read_()
            mnt = mnt_parent
            continue
        d_parent = dentry.d_parent.read_()
        if dentry == d_parent:
            break
        components.append(dentry.d_name.name.string_())
        components.append(b"/")
        dentry = d_parent
    if components:
        return b"".join(reversed(components))
    else:
        return b"/"
Exemplo n.º 14
0
def path_lookup(prog_or_root, path, allow_negative=False):
    """
    .. c:function:: struct path path_lookup(struct path *root, const char *path, bool allow_negative)

    Look up the given path name relative to the given root directory. If given
    a :class:`Program` instead of a ``struct path``, the initial root
    filesystem is used.

    :param bool allow_negative: Whether to allow returning a negative dentry
        (i.e., a dentry for a non-existent path).
    :raises Exception: if the dentry is negative and ``allow_negative`` is
        ``False``, or if the path is not present in the dcache. The latter does
        not necessarily mean that the path does not exist; it may be uncached.
        On a live system, you can make the kernel cache the path by accessing
        it (e.g., with :func:`open()` or :func:`os.stat()`):

        >>> path_lookup(prog, '/usr/include/stdlib.h')
        ...
        Exception: could not find '/usr/include/stdlib.h' in dcache
        >>> open('/usr/include/stdlib.h').close()
        >>> path_lookup(prog, '/usr/include/stdlib.h')
        (struct path){
                .mnt = (struct vfsmount *)0xffff8b70413cdca0,
                .dentry = (struct dentry *)0xffff8b702ac2c480,
        }
    """
    if isinstance(prog_or_root, Program):
        prog_or_root = prog_or_root["init_task"].fs.root
    mnt = root_mnt = container_of(prog_or_root.mnt.read_(), "struct mount",
                                  "mnt")
    dentry = root_dentry = prog_or_root.dentry.read_()
    components = os.fsencode(path).split(b"/")
    for i, component in enumerate(components):
        if component == b"" or component == b".":
            continue
        elif component == b"..":
            mnt, dentry = _follow_dotdot(mnt, dentry, root_mnt, root_dentry)
        else:
            for child in list_for_each_entry("struct dentry",
                                             dentry.d_subdirs.address_of_(),
                                             "d_child"):
                if child.d_name.name.string_() == component:
                    dentry = child
                    break
            else:
                failed_path = os.fsdecode(b"/".join(components[:i + 1]))
                raise Exception(f"could not find {failed_path!r} in dcache")
            mnt, dentry = _follow_mount(mnt, dentry)
    if not allow_negative and not dentry.d_inode:
        failed_path = os.fsdecode(b"/".join(components))
        raise Exception(f"{failed_path!r} dentry is negative")
    return Object(
        mnt.prog_,
        "struct path",
        value={
            "mnt": mnt.mnt.address_of_(),
            "dentry": dentry,
        },
    )
Exemplo n.º 15
0
def for_each_partition(prog: Program) -> Iterator[Object]:
    """
    Iterate over all partitions in the system.

    :return: Iterator of ``struct hd_struct *`` objects.
    """
    for device in _for_each_block_device(prog):
        yield container_of(device, "struct hd_struct", "__dev")
Exemplo n.º 16
0
def for_each_partition(prog):
    """
    Iterate over all partitions in the system.

    :return: Iterator of ``struct hd_struct *`` objects.
    """
    for device in _for_each_block_device(prog):
        yield container_of(device, 'struct hd_struct', '__dev')
Exemplo n.º 17
0
def for_each_partition(prog: Program) -> Iterator[Object]:
    """
    Iterate over all partitions in the system.

    :return: Iterator of ``struct block_device *`` or ``struct hd_struct *``
        objects depending on the kernel version.
    """
    # See the comment in for_each_disk().
    have_bd_device = True
    for device in _for_each_block_device(prog):
        if have_bd_device:
            try:
                yield container_of(device, "struct block_device", "bd_device")
                continue
            except LookupError:
                have_bd_device = False
        yield container_of(device, "struct hd_struct", "__dev")
Exemplo n.º 18
0
 def _call(self, objs: Iterable[drgn.Object]) -> Iterable[drgn.Object]:
     sname = get_valid_struct_name(self, self.args.struct_name)
     for obj in objs:
         try:
             container_obj = drgn.container_of(obj, sname, self.args.member)
         except (TypeError, LookupError) as err:
             raise sdb.CommandError(self.name, str(err))
         yield container_obj
Exemplo n.º 19
0
def find_memcg_ids(css=prog['root_mem_cgroup'].css, prefix=''):
    if not list_empty(css.children.address_of_()):
        for css in list_for_each_entry('struct cgroup_subsys_state',
                                       css.children.address_of_(), 'sibling'):
            name = prefix + '/' + css.cgroup.kn.name.string_().decode('utf-8')
            memcg = container_of(css, 'struct mem_cgroup', 'css')
            MEMCGS[css.cgroup.kn.id.value_()] = memcg
            find_memcg_ids(css, name)
Exemplo n.º 20
0
def pid_task(pid, pid_type):
    """
    .. c:function:: struct task_struct *pid_task(struct pid *pid, enum pid_type pid_type)

    Return the ``struct task_struct *`` containing the given ``struct pid *``
    of the given type.
    """
    if not pid:
        return NULL(pid.prog_, 'struct task_struct *')
    first = pid.tasks[0].first
    if not first:
        return NULL(pid.prog_, 'struct task_struct *')
    try:
        return container_of(first, 'struct task_struct',
                            f'pid_links[{int(pid_type)}]')
    except LookupError:
        return container_of(first, 'struct task_struct',
                            f'pids[{int(pid_type)}].node')
Exemplo n.º 21
0
Arquivo: list.py Projeto: jgkamat/drgn
def list_prev_entry(pos: Object, member: str) -> Object:
    """
    Return the previous entry in a list.

    :param pos: ``type*``
    :param member: Name of list node member in entry type.
    :return: ``type *``
    """
    return container_of(getattr(pos, member).prev, pos.type_.type, member)
Exemplo n.º 22
0
Arquivo: net.py Projeto: osandov/drgn
def SOCK_INODE(sock: Object) -> Object:
    """
    Get the inode of a socket.

    :param sock: ``struct socket *``
    :return: ``struct inode *``
    """
    return container_of(sock, "struct socket_alloc",
                        "socket").vfs_inode.address_of_()
Exemplo n.º 23
0
def hlist_nulls_entry(pos, type, member):
    """
    .. c:function:: type *hlist_nulls_entry(struct hlist_nulls_node *pos, type, member)

    Return an entry in a nulls hash list.

    The nulls hash list is assumed to be non-empty.
    """
    return container_of(pos, type, member)
Exemplo n.º 24
0
Arquivo: list.py Projeto: cneira/drgn
def list_last_entry(head, type, member):
    """
    .. c:function:: type *list_last_entry(struct list_head *head, type, member)

    Return the last entry in a list.

    The list is assumed to be non-empty.
    """
    return container_of(head.prev, type, member)
Exemplo n.º 25
0
def for_each_disk(prog):
    """
    Iterate over all disks in the system.

    :return: Iterator of ``struct gendisk *`` objects.
    """
    disk_type = prog['disk_type'].address_of_()
    for device in _for_each_block_device(prog):
        if device.type == disk_type:
            yield container_of(device, 'struct gendisk', 'part0.__dev')
Exemplo n.º 26
0
def inode_path(inode):
    """
    .. c:function:: char *inode_path(struct inode *inode)

    Return any path of an inode from the root of its filesystem.
    """
    if hlist_empty(inode.i_dentry):
        return None
    return dentry_path(
        container_of(inode.i_dentry.first, 'struct dentry', 'd_u.d_alias'))
Exemplo n.º 27
0
def for_each_partition(prog):
    """
    Iterate over all partitions in the system.

    :return: Iterator of ``struct hd_struct *`` objects.
    """
    devices = prog['block_class'].p.klist_devices.k_list.address_of_()
    for device in list_for_each_entry('struct device', devices,
                                      'knode_class.n_node'):
        yield container_of(device, 'struct hd_struct', '__dev')
Exemplo n.º 28
0
def for_each_disk(prog: Program) -> Iterator[Object]:
    """
    Iterate over all disks in the system.

    :return: Iterator of ``struct gendisk *`` objects.
    """
    disk_type = prog["disk_type"].address_of_()
    for device in _for_each_block_device(prog):
        if device.type == disk_type:
            yield container_of(device, "struct gendisk", "part0.__dev")
Exemplo n.º 29
0
def print_hmap(hmap_addr, struct_name, member):
    objs = []

    buckets = hmap_addr.buckets.value_()
    n = hmap_addr.n.value_()

    if n == 0:
        return objs


#     print("\n=== %s: buckets: %x, n: %d ===" % (struct_name, buckets, n))

    i = 0
    while 1:
        p = Object(prog, 'void *', address=buckets)
        if p.value_() == 0:
            buckets = buckets + 8
            continue

        data = container_of(p, "struct " + struct_name, member)
        objs.append(data)

        i += 1
        if i == n:
            return objs

        next = data.member_(member).next

        while next.value_() != 0:

            data = container_of(next, "struct " + struct_name, member)
            objs.append(data)

            i += 1
            if i == n:
                return objs

            next = data.member_(member).next

        buckets = buckets + 8

    return objs
Exemplo n.º 30
0
Arquivo: list.py Projeto: cneira/drgn
def list_first_entry(head, type, member):
    """
    .. c:function:: type *list_first_entry(struct list_head *head, type, member)

    Return the first entry in a list.

    The list is assumed to be non-empty.

    See also :func:`list_first_entry_or_null()`.
    """
    return container_of(head.next, type, member)