1*6acc5c04SPhilippe Mathieu-Daudé# 293b1b365SPeter Maydell# GDB debugging support 393b1b365SPeter Maydell# 493b1b365SPeter Maydell# Copyright 2012 Red Hat, Inc. and/or its affiliates 593b1b365SPeter Maydell# 693b1b365SPeter Maydell# Authors: 793b1b365SPeter Maydell# Avi Kivity <avi@redhat.com> 893b1b365SPeter Maydell# 9328eb60dSPaolo Bonzini# This work is licensed under the terms of the GNU GPL, version 2 or 10328eb60dSPaolo Bonzini# later. See the COPYING file in the top-level directory. 1193b1b365SPeter Maydell 1293b1b365SPeter Maydell# 'qemu mtree' -- display the memory hierarchy 1393b1b365SPeter Maydell 1493b1b365SPeter Maydellimport gdb 1593b1b365SPeter Maydell 1693b1b365SPeter Maydelldef isnull(ptr): 1793b1b365SPeter Maydell return ptr == gdb.Value(0).cast(ptr.type) 1893b1b365SPeter Maydell 1993b1b365SPeter Maydelldef int128(p): 208037fa55SAlex Bennée '''Read an Int128 type to a python integer. 218037fa55SAlex Bennée 228037fa55SAlex Bennée QEMU can be built with native Int128 support so we need to detect 238037fa55SAlex Bennée if the value is a structure or the native type. 248037fa55SAlex Bennée ''' 258037fa55SAlex Bennée if p.type.code == gdb.TYPE_CODE_STRUCT: 26d6b69132SYang Wei return int(p['lo']) + (int(p['hi']) << 64) 278037fa55SAlex Bennée else: 288037fa55SAlex Bennée return int(("%s" % p), 16) 2993b1b365SPeter Maydell 3093b1b365SPeter Maydellclass MtreeCommand(gdb.Command): 3193b1b365SPeter Maydell '''Display the memory tree hierarchy''' 3293b1b365SPeter Maydell def __init__(self): 3393b1b365SPeter Maydell gdb.Command.__init__(self, 'qemu mtree', gdb.COMMAND_DATA, 3493b1b365SPeter Maydell gdb.COMPLETE_NONE) 3593b1b365SPeter Maydell self.queue = [] 3693b1b365SPeter Maydell def invoke(self, arg, from_tty): 3793b1b365SPeter Maydell self.seen = set() 3893b1b365SPeter Maydell self.queue_root('address_space_memory') 3993b1b365SPeter Maydell self.queue_root('address_space_io') 4093b1b365SPeter Maydell self.process_queue() 4193b1b365SPeter Maydell def queue_root(self, varname): 4293b1b365SPeter Maydell ptr = gdb.parse_and_eval(varname)['root'] 4393b1b365SPeter Maydell self.queue.append(ptr) 4493b1b365SPeter Maydell def process_queue(self): 4593b1b365SPeter Maydell while self.queue: 4693b1b365SPeter Maydell ptr = self.queue.pop(0) 47d6b69132SYang Wei if int(ptr) in self.seen: 4893b1b365SPeter Maydell continue 4993b1b365SPeter Maydell self.print_item(ptr) 5093b1b365SPeter Maydell def print_item(self, ptr, offset = gdb.Value(0), level = 0): 51d6b69132SYang Wei self.seen.add(int(ptr)) 5293b1b365SPeter Maydell addr = ptr['addr'] 5393b1b365SPeter Maydell addr += offset 5493b1b365SPeter Maydell size = int128(ptr['size']) 5593b1b365SPeter Maydell alias = ptr['alias'] 5693b1b365SPeter Maydell klass = '' 5793b1b365SPeter Maydell if not isnull(alias): 5893b1b365SPeter Maydell klass = ' (alias)' 5993b1b365SPeter Maydell elif not isnull(ptr['ops']): 6093b1b365SPeter Maydell klass = ' (I/O)' 6193b1b365SPeter Maydell elif bool(ptr['ram']): 6293b1b365SPeter Maydell klass = ' (RAM)' 6393b1b365SPeter Maydell gdb.write('%s%016x-%016x %s%s (@ %s)\n' 6493b1b365SPeter Maydell % (' ' * level, 65d6b69132SYang Wei int(addr), 66d6b69132SYang Wei int(addr + (size - 1)), 6793b1b365SPeter Maydell ptr['name'].string(), 6893b1b365SPeter Maydell klass, 6993b1b365SPeter Maydell ptr, 7093b1b365SPeter Maydell ), 7193b1b365SPeter Maydell gdb.STDOUT) 7293b1b365SPeter Maydell if not isnull(alias): 7393b1b365SPeter Maydell gdb.write('%s alias: %s@%016x (@ %s)\n' % 7493b1b365SPeter Maydell (' ' * level, 7593b1b365SPeter Maydell alias['name'].string(), 768037fa55SAlex Bennée int(ptr['alias_offset']), 7793b1b365SPeter Maydell alias, 7893b1b365SPeter Maydell ), 7993b1b365SPeter Maydell gdb.STDOUT) 8093b1b365SPeter Maydell self.queue.append(alias) 8193b1b365SPeter Maydell subregion = ptr['subregions']['tqh_first'] 8293b1b365SPeter Maydell level += 1 8393b1b365SPeter Maydell while not isnull(subregion): 8493b1b365SPeter Maydell self.print_item(subregion, addr, level) 8593b1b365SPeter Maydell subregion = subregion['subregions_link']['tqe_next'] 86