lists.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. #
  2. # gdb helper commands and functions for Linux kernel debugging
  3. #
  4. # list tools
  5. #
  6. # Copyright (c) Thiebaud Weksteen, 2015
  7. #
  8. # Authors:
  9. # Thiebaud Weksteen <thiebaud@weksteen.fr>
  10. #
  11. # This work is licensed under the terms of the GNU GPL version 2.
  12. #
  13. import gdb
  14. from linux import utils
  15. list_head = utils.CachedType("struct list_head")
  16. def list_check(head):
  17. nb = 0
  18. if (head.type == list_head.get_type().pointer()):
  19. head = head.dereference()
  20. elif (head.type != list_head.get_type()):
  21. raise gdb.GdbError('argument must be of type (struct list_head [*])')
  22. c = head
  23. try:
  24. gdb.write("Starting with: {}\n".format(c))
  25. except gdb.MemoryError:
  26. gdb.write('head is not accessible\n')
  27. return
  28. while True:
  29. p = c['prev'].dereference()
  30. n = c['next'].dereference()
  31. try:
  32. if p['next'] != c.address:
  33. gdb.write('prev.next != current: '
  34. 'current@{current_addr}={current} '
  35. 'prev@{p_addr}={p}\n'.format(
  36. current_addr=c.address,
  37. current=c,
  38. p_addr=p.address,
  39. p=p,
  40. ))
  41. return
  42. except gdb.MemoryError:
  43. gdb.write('prev is not accessible: '
  44. 'current@{current_addr}={current}\n'.format(
  45. current_addr=c.address,
  46. current=c
  47. ))
  48. return
  49. try:
  50. if n['prev'] != c.address:
  51. gdb.write('next.prev != current: '
  52. 'current@{current_addr}={current} '
  53. 'next@{n_addr}={n}\n'.format(
  54. current_addr=c.address,
  55. current=c,
  56. n_addr=n.address,
  57. n=n,
  58. ))
  59. return
  60. except gdb.MemoryError:
  61. gdb.write('next is not accessible: '
  62. 'current@{current_addr}={current}\n'.format(
  63. current_addr=c.address,
  64. current=c
  65. ))
  66. return
  67. c = n
  68. nb += 1
  69. if c == head:
  70. gdb.write("list is consistent: {} node(s)\n".format(nb))
  71. return
  72. class LxListChk(gdb.Command):
  73. """Verify a list consistency"""
  74. def __init__(self):
  75. super(LxListChk, self).__init__("lx-list-check", gdb.COMMAND_DATA,
  76. gdb.COMPLETE_EXPRESSION)
  77. def invoke(self, arg, from_tty):
  78. argv = gdb.string_to_argv(arg)
  79. if len(argv) != 1:
  80. raise gdb.GdbError("lx-list-check takes one argument")
  81. list_check(gdb.parse_and_eval(argv[0]))
  82. LxListChk()