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