2
0

mtree.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #
  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 or
  10. # later. See the COPYING file in the top-level directory.
  11. # 'qemu mtree' -- display the memory hierarchy
  12. import gdb
  13. def isnull(ptr):
  14. return ptr == gdb.Value(0).cast(ptr.type)
  15. def int128(p):
  16. '''Read an Int128 type to a python integer.
  17. QEMU can be built with native Int128 support so we need to detect
  18. if the value is a structure or the native type.
  19. '''
  20. if p.type.code == gdb.TYPE_CODE_STRUCT:
  21. return int(p['lo']) + (int(p['hi']) << 64)
  22. else:
  23. return int(("%s" % p), 16)
  24. class MtreeCommand(gdb.Command):
  25. '''Display the memory tree hierarchy'''
  26. def __init__(self):
  27. gdb.Command.__init__(self, 'qemu mtree', gdb.COMMAND_DATA,
  28. gdb.COMPLETE_NONE)
  29. self.queue = []
  30. def invoke(self, arg, from_tty):
  31. self.seen = set()
  32. self.queue_root('address_space_memory')
  33. self.queue_root('address_space_io')
  34. self.process_queue()
  35. def queue_root(self, varname):
  36. ptr = gdb.parse_and_eval(varname)['root']
  37. self.queue.append(ptr)
  38. def process_queue(self):
  39. while self.queue:
  40. ptr = self.queue.pop(0)
  41. if int(ptr) in self.seen:
  42. continue
  43. self.print_item(ptr)
  44. def print_item(self, ptr, offset = gdb.Value(0), level = 0):
  45. self.seen.add(int(ptr))
  46. addr = ptr['addr']
  47. addr += offset
  48. size = int128(ptr['size'])
  49. alias = ptr['alias']
  50. klass = ''
  51. if not isnull(alias):
  52. klass = ' (alias)'
  53. elif not isnull(ptr['ops']):
  54. klass = ' (I/O)'
  55. elif bool(ptr['ram']):
  56. klass = ' (RAM)'
  57. gdb.write('%s%016x-%016x %s%s (@ %s)\n'
  58. % (' ' * level,
  59. int(addr),
  60. int(addr + (size - 1)),
  61. ptr['name'].string(),
  62. klass,
  63. ptr,
  64. ),
  65. gdb.STDOUT)
  66. if not isnull(alias):
  67. gdb.write('%s alias: %s@%016x (@ %s)\n' %
  68. (' ' * level,
  69. alias['name'].string(),
  70. int(ptr['alias_offset']),
  71. alias,
  72. ),
  73. gdb.STDOUT)
  74. self.queue.append(alias)
  75. subregion = ptr['subregions']['tqh_first']
  76. level += 1
  77. while not isnull(subregion):
  78. self.print_item(subregion, addr, level)
  79. subregion = subregion['subregions_link']['tqe_next']