Source code for crash.types.classdev

# -*- coding: utf-8 -*-
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
"""
The crash.types.classdev module offers helpers to work with class devices.
"""

from typing import Iterable

from crash.types.klist import klist_for_each
from crash.util import struct_has_member, container_of
from crash.util.symbols import Types, TypeCallbacks

import gdb

types = Types(['struct device', 'struct device_private'])

[docs]class ClassdevState: _class_is_private = True
[docs] @classmethod def setup_iterator_type(cls, gdbtype: gdb.Type) -> None: """ Detect whether to iterate the class list using ``struct device`` or ``struct device_private``. Linux v5.1-rc1 moved ``knode_class`` from ``struct device`` to ``struct device_private``. We need to detect it here to ensure list iteration works properly. Meant to be used as a TypeCallback. Args: gdbtype: The ``struct device`` type. """ if struct_has_member(gdbtype, 'knode_class'): cls._class_is_private = False
[docs] @classmethod def class_is_private(cls) -> bool: """ Returns whether the class device uses ``struct device_private`` Meant to be used only be crash.types.classdev. """ return cls._class_is_private
type_cbs = TypeCallbacks([('struct device', ClassdevState.setup_iterator_type)])
[docs]def for_each_class_device(class_struct: gdb.Value, subtype: gdb.Value = None) -> Iterable[gdb.Value]: """ Iterate over the list of class devices Args: class_struct: The class of devices to iterate subtype: A ``struct device_type *`` to use to filter the results. The value must be of type ``struct device_type *`` and will be used to compare against the ``type`` field of each ``struct device``. Yields: :obj:`gdb.Value`: A device on the class's device list. The value is of type ``struct device``. """ klist = class_struct['p']['klist_devices'] container_type = types.device_type if ClassdevState.class_is_private(): container_type = types.device_private_type for knode in klist_for_each(klist): dev = container_of(knode, container_type, 'knode_class') if ClassdevState.class_is_private(): dev = dev['device'].dereference() if subtype is None or int(subtype) == int(dev['type']): yield dev