device.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. # SPDX-License-Identifier: GPL-2.0
  2. #
  3. # Copyright (c) NXP 2019
  4. import gdb
  5. from linux.utils import CachedType
  6. from linux.utils import container_of
  7. from linux.lists import list_for_each_entry
  8. device_private_type = CachedType('struct device_private')
  9. device_type = CachedType('struct device')
  10. subsys_private_type = CachedType('struct subsys_private')
  11. kobject_type = CachedType('struct kobject')
  12. kset_type = CachedType('struct kset')
  13. bus_type = CachedType('struct bus_type')
  14. class_type = CachedType('struct class')
  15. def dev_name(dev):
  16. dev_init_name = dev['init_name']
  17. if dev_init_name:
  18. return dev_init_name.string()
  19. return dev['kobj']['name'].string()
  20. def kset_for_each_object(kset):
  21. return list_for_each_entry(kset['list'],
  22. kobject_type.get_type().pointer(), "entry")
  23. def for_each_bus():
  24. for kobj in kset_for_each_object(gdb.parse_and_eval('bus_kset')):
  25. subsys = container_of(kobj, kset_type.get_type().pointer(), 'kobj')
  26. subsys_priv = container_of(subsys, subsys_private_type.get_type().pointer(), 'subsys')
  27. yield subsys_priv['bus']
  28. def for_each_class():
  29. for kobj in kset_for_each_object(gdb.parse_and_eval('class_kset')):
  30. subsys = container_of(kobj, kset_type.get_type().pointer(), 'kobj')
  31. subsys_priv = container_of(subsys, subsys_private_type.get_type().pointer(), 'subsys')
  32. yield subsys_priv['class']
  33. def get_bus_by_name(name):
  34. for item in for_each_bus():
  35. if item['name'].string() == name:
  36. return item
  37. raise gdb.GdbError("Can't find bus type {!r}".format(name))
  38. def get_class_by_name(name):
  39. for item in for_each_class():
  40. if item['name'].string() == name:
  41. return item
  42. raise gdb.GdbError("Can't find device class {!r}".format(name))
  43. klist_type = CachedType('struct klist')
  44. klist_node_type = CachedType('struct klist_node')
  45. def klist_for_each(klist):
  46. return list_for_each_entry(klist['k_list'],
  47. klist_node_type.get_type().pointer(), 'n_node')
  48. def bus_for_each_device(bus):
  49. for kn in klist_for_each(bus['p']['klist_devices']):
  50. dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_bus')
  51. yield dp['device']
  52. def class_for_each_device(cls):
  53. for kn in klist_for_each(cls['p']['klist_devices']):
  54. dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_class')
  55. yield dp['device']
  56. def device_for_each_child(dev):
  57. for kn in klist_for_each(dev['p']['klist_children']):
  58. dp = container_of(kn, device_private_type.get_type().pointer(), 'knode_parent')
  59. yield dp['device']
  60. def _show_device(dev, level=0, recursive=False):
  61. gdb.write('{}dev {}:\t{}\n'.format('\t' * level, dev_name(dev), dev))
  62. if recursive:
  63. for child in device_for_each_child(dev):
  64. _show_device(child, level + 1, recursive)
  65. class LxDeviceListBus(gdb.Command):
  66. '''Print devices on a bus (or all buses if not specified)'''
  67. def __init__(self):
  68. super(LxDeviceListBus, self).__init__('lx-device-list-bus', gdb.COMMAND_DATA)
  69. def invoke(self, arg, from_tty):
  70. if not arg:
  71. for bus in for_each_bus():
  72. gdb.write('bus {}:\t{}\n'.format(bus['name'].string(), bus))
  73. for dev in bus_for_each_device(bus):
  74. _show_device(dev, level=1)
  75. else:
  76. bus = get_bus_by_name(arg)
  77. if not bus:
  78. raise gdb.GdbError("Can't find bus {!r}".format(arg))
  79. for dev in bus_for_each_device(bus):
  80. _show_device(dev)
  81. class LxDeviceListClass(gdb.Command):
  82. '''Print devices in a class (or all classes if not specified)'''
  83. def __init__(self):
  84. super(LxDeviceListClass, self).__init__('lx-device-list-class', gdb.COMMAND_DATA)
  85. def invoke(self, arg, from_tty):
  86. if not arg:
  87. for cls in for_each_class():
  88. gdb.write("class {}:\t{}\n".format(cls['name'].string(), cls))
  89. for dev in class_for_each_device(cls):
  90. _show_device(dev, level=1)
  91. else:
  92. cls = get_class_by_name(arg)
  93. for dev in class_for_each_device(cls):
  94. _show_device(dev)
  95. class LxDeviceListTree(gdb.Command):
  96. '''Print a device and its children recursively'''
  97. def __init__(self):
  98. super(LxDeviceListTree, self).__init__('lx-device-list-tree', gdb.COMMAND_DATA)
  99. def invoke(self, arg, from_tty):
  100. if not arg:
  101. raise gdb.GdbError('Please provide pointer to struct device')
  102. dev = gdb.parse_and_eval(arg)
  103. if dev.type != device_type.get_type().pointer():
  104. raise gdb.GdbError('Please provide pointer to struct device')
  105. _show_device(dev, level=0, recursive=True)
  106. class LxDeviceFindByBusName(gdb.Function):
  107. '''Find struct device by bus and name (both strings)'''
  108. def __init__(self):
  109. super(LxDeviceFindByBusName, self).__init__('lx_device_find_by_bus_name')
  110. def invoke(self, bus, name):
  111. name = name.string()
  112. bus = get_bus_by_name(bus.string())
  113. for dev in bus_for_each_device(bus):
  114. if dev_name(dev) == name:
  115. return dev
  116. class LxDeviceFindByClassName(gdb.Function):
  117. '''Find struct device by class and name (both strings)'''
  118. def __init__(self):
  119. super(LxDeviceFindByClassName, self).__init__('lx_device_find_by_class_name')
  120. def invoke(self, cls, name):
  121. name = name.string()
  122. cls = get_class_by_name(cls.string())
  123. for dev in class_for_each_device(cls):
  124. if dev_name(dev) == name:
  125. return dev
  126. LxDeviceListBus()
  127. LxDeviceListClass()
  128. LxDeviceListTree()
  129. LxDeviceFindByBusName()
  130. LxDeviceFindByClassName()