mtree.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. #!/usr/bin/python
  2. # GDB debugging support
  3. #
  4. # Copyright 2012 Red Hat, Inc. and/or its affiliates
  5. #
  6. # Authors:
  7. # Avi Kivity <avi@redhat.com>
  8. #
  9. # This work is licensed under the terms of the GNU GPL, version 2. See
  10. # the COPYING file in the top-level directory.
  11. #
  12. # Contributions after 2012-01-13 are licensed under the terms of the
  13. # GNU GPL, version 2 or (at your option) any later version.
  14. # 'qemu mtree' -- display the memory hierarchy
  15. import gdb
  16. def isnull(ptr):
  17. return ptr == gdb.Value(0).cast(ptr.type)
  18. def int128(p):
  19. '''Read an Int128 type to a python integer.
  20. QEMU can be built with native Int128 support so we need to detect
  21. if the value is a structure or the native type.
  22. '''
  23. if p.type.code == gdb.TYPE_CODE_STRUCT:
  24. return int(p['lo']) + (int(p['hi']) << 64)
  25. else:
  26. return int(("%s" % p), 16)
  27. class MtreeCommand(gdb.Command):
  28. '''Display the memory tree hierarchy'''
  29. def __init__(self):
  30. gdb.Command.__init__(self, 'qemu mtree', gdb.COMMAND_DATA,
  31. gdb.COMPLETE_NONE)
  32. self.queue = []
  33. def invoke(self, arg, from_tty):
  34. self.seen = set()
  35. self.queue_root('address_space_memory')
  36. self.queue_root('address_space_io')
  37. self.process_queue()
  38. def queue_root(self, varname):
  39. ptr = gdb.parse_and_eval(varname)['root']
  40. self.queue.append(ptr)
  41. def process_queue(self):
  42. while self.queue:
  43. ptr = self.queue.pop(0)
  44. if int(ptr) in self.seen:
  45. continue
  46. self.print_item(ptr)
  47. def print_item(self, ptr, offset = gdb.Value(0), level = 0):
  48. self.seen.add(int(ptr))
  49. addr = ptr['addr']
  50. addr += offset
  51. size = int128(ptr['size'])
  52. alias = ptr['alias']
  53. klass = ''
  54. if not isnull(alias):
  55. klass = ' (alias)'
  56. elif not isnull(ptr['ops']):
  57. klass = ' (I/O)'
  58. elif bool(ptr['ram']):
  59. klass = ' (RAM)'
  60. gdb.write('%s%016x-%016x %s%s (@ %s)\n'
  61. % (' ' * level,
  62. int(addr),
  63. int(addr + (size - 1)),
  64. ptr['name'].string(),
  65. klass,
  66. ptr,
  67. ),
  68. gdb.STDOUT)
  69. if not isnull(alias):
  70. gdb.write('%s alias: %s@%016x (@ %s)\n' %
  71. (' ' * level,
  72. alias['name'].string(),
  73. int(ptr['alias_offset']),
  74. alias,
  75. ),
  76. gdb.STDOUT)
  77. self.queue.append(alias)
  78. subregion = ptr['subregions']['tqh_first']
  79. level += 1
  80. while not isnull(subregion):
  81. self.print_item(subregion, addr, level)
  82. subregion = subregion['subregions_link']['tqe_next']