123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- # SPDX-License-Identifier: GPL-2.0
- #
- # Copyright (c) NXP 2019
- import gdb
- from linux.utils import CachedType
- from linux.utils import container_of
- from linux.lists import list_for_each_entry
- device_private_type = CachedType('struct device_private')
- device_type = CachedType('struct device')
- subsys_private_type = CachedType('struct subsys_private')
- kobject_type = CachedType('struct kobject')
- kset_type = CachedType('struct kset')
- bus_type = CachedType('struct bus_type')
- class_type = CachedType('struct class')
- def dev_name(dev):
- dev_init_name = dev['init_name']
- if dev_init_name:
- return dev_init_name.string()
- return dev['kobj']['name'].string()
- def kset_for_each_object(kset):
- return list_for_each_entry(kset['list'],
- kobject_type.get_type().pointer(), "entry")
- def for_each_bus():
- for kobj in kset_for_each_object(gdb.parse_and_eval('bus_kset')):
- subsys = container_of(kobj, kset_type.get_type().pointer(), 'kobj')
- subsys_priv = container_of(subsys, subsys_private_type.get_type().pointer(), 'subsys')
- yield subsys_priv['bus']
- def for_each_class():
- for kobj in kset_for_each_object(gdb.parse_and_eval('class_kset')):
- subsys = container_of(kobj, kset_type.get_type().pointer(), 'kobj')
- subsys_priv = container_of(subsys, subsys_private_type.get_type().pointer(), 'subsys')
- yield subsys_priv['class']
- def get_bus_by_name(name):
- for item in for_each_bus():
- if item['name'].string() == name:
- return item
- raise gdb.GdbError("Can't find bus type {!r}".format(name))
- def get_class_by_name(name):
- for item in for_each_class():
- if item['name'].string() == name:
- return item
- raise gdb.GdbError("Can't find device class {!r}".format(name))
- klist_type = CachedType('struct klist')
- klist_node_type = CachedType('struct klist_node')
- def klist_for_each(klist):
- return list_for_each_entry(klist['k_list'],
- klist_node_type.get_type().pointer(), 'n_node')
- def bus_for_each_device(bus):
- for kn in klist_for_each(bus['p']['klist_devices']):
- dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_bus')
- yield dp['device']
- def class_for_each_device(cls):
- for kn in klist_for_each(cls['p']['klist_devices']):
- dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_class')
- yield dp['device']
- def device_for_each_child(dev):
- for kn in klist_for_each(dev['p']['klist_children']):
- dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_parent')
- yield dp['device']
- def _show_device(dev, level=0, recursive=False):
- gdb.write('{}dev {}:\t{}\n'.format('\t' * level, dev_name(dev), dev))
- if recursive:
- for child in device_for_each_child(dev):
- _show_device(child, level + 1, recursive)
- class LxDeviceListBus(gdb.Command):
- '''Print devices on a bus (or all buses if not specified)'''
- def __init__(self):
- super(LxDeviceListBus, self).__init__('lx-device-list-bus', gdb.COMMAND_DATA)
- def invoke(self, arg, from_tty):
- if not arg:
- for bus in for_each_bus():
- gdb.write('bus {}:\t{}\n'.format(bus['name'].string(), bus))
- for dev in bus_for_each_device(bus):
- _show_device(dev, level=1)
- else:
- bus = get_bus_by_name(arg)
- if not bus:
- raise gdb.GdbError("Can't find bus {!r}".format(arg))
- for dev in bus_for_each_device(bus):
- _show_device(dev)
- class LxDeviceListClass(gdb.Command):
- '''Print devices in a class (or all classes if not specified)'''
- def __init__(self):
- super(LxDeviceListClass, self).__init__('lx-device-list-class', gdb.COMMAND_DATA)
- def invoke(self, arg, from_tty):
- if not arg:
- for cls in for_each_class():
- gdb.write("class {}:\t{}\n".format(cls['name'].string(), cls))
- for dev in class_for_each_device(cls):
- _show_device(dev, level=1)
- else:
- cls = get_class_by_name(arg)
- for dev in class_for_each_device(cls):
- _show_device(dev)
- class LxDeviceListTree(gdb.Command):
- '''Print a device and its children recursively'''
- def __init__(self):
- super(LxDeviceListTree, self).__init__('lx-device-list-tree', gdb.COMMAND_DATA)
- def invoke(self, arg, from_tty):
- if not arg:
- raise gdb.GdbError('Please provide pointer to struct device')
- dev = gdb.parse_and_eval(arg)
- if dev.type != device_type.get_type().pointer():
- raise gdb.GdbError('Please provide pointer to struct device')
- _show_device(dev, level=0, recursive=True)
- class LxDeviceFindByBusName(gdb.Function):
- '''Find struct device by bus and name (both strings)'''
- def __init__(self):
- super(LxDeviceFindByBusName, self).__init__('lx_device_find_by_bus_name')
- def invoke(self, bus, name):
- name = name.string()
- bus = get_bus_by_name(bus.string())
- for dev in bus_for_each_device(bus):
- if dev_name(dev) == name:
- return dev
- class LxDeviceFindByClassName(gdb.Function):
- '''Find struct device by class and name (both strings)'''
- def __init__(self):
- super(LxDeviceFindByClassName, self).__init__('lx_device_find_by_class_name')
- def invoke(self, cls, name):
- name = name.string()
- cls = get_class_by_name(cls.string())
- for dev in class_for_each_device(cls):
- if dev_name(dev) == name:
- return dev
- LxDeviceListBus()
- LxDeviceListClass()
- LxDeviceListTree()
- LxDeviceFindByBusName()
- LxDeviceFindByClassName()
|