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