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