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