scripts/qemu-gdb: Split MtreeCommand into its own module
As we add more commands to our Python gdb debugging support, it's going to get unwieldy to have everything in a single file. Split the implementation of the 'mtree' command from qemu-gdb.py into its own module. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Message-id: 1439574392-4403-2-git-send-email-peter.maydell@linaro.org
This commit is contained in:
		
							parent
							
								
									ba9cef7b6e
								
							
						
					
					
						commit
						93b1b365dc
					
				| 
						 | 
				
			
			@ -16,11 +16,14 @@
 | 
			
		|||
 | 
			
		||||
import gdb
 | 
			
		||||
 | 
			
		||||
def isnull(ptr):
 | 
			
		||||
    return ptr == gdb.Value(0).cast(ptr.type)
 | 
			
		||||
import os, sys
 | 
			
		||||
 | 
			
		||||
def int128(p):
 | 
			
		||||
    return long(p['lo']) + (long(p['hi']) << 64)
 | 
			
		||||
# Annoyingly, gdb doesn't put the directory of scripts onto the
 | 
			
		||||
# module search path. Do it manually.
 | 
			
		||||
 | 
			
		||||
sys.path.append(os.path.dirname(__file__))
 | 
			
		||||
 | 
			
		||||
from qemugdb import mtree
 | 
			
		||||
 | 
			
		||||
def get_fs_base():
 | 
			
		||||
    '''Fetch %fs base value using arch_prctl(ARCH_GET_FS)'''
 | 
			
		||||
| 
						 | 
				
			
			@ -102,63 +105,6 @@ class CoroutineCommand(gdb.Command):
 | 
			
		|||
        coroutine_pointer = gdb.parse_and_eval(argv[0]).cast(gdb.lookup_type('CoroutineUContext').pointer())
 | 
			
		||||
        bt_jmpbuf(coroutine_pointer['env']['__jmpbuf'])
 | 
			
		||||
 | 
			
		||||
class MtreeCommand(gdb.Command):
 | 
			
		||||
    '''Display the memory tree hierarchy'''
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        gdb.Command.__init__(self, 'qemu mtree', gdb.COMMAND_DATA,
 | 
			
		||||
                             gdb.COMPLETE_NONE)
 | 
			
		||||
        self.queue = []
 | 
			
		||||
    def invoke(self, arg, from_tty):
 | 
			
		||||
        self.seen = set()
 | 
			
		||||
        self.queue_root('address_space_memory')
 | 
			
		||||
        self.queue_root('address_space_io')
 | 
			
		||||
        self.process_queue()
 | 
			
		||||
    def queue_root(self, varname):
 | 
			
		||||
        ptr = gdb.parse_and_eval(varname)['root']
 | 
			
		||||
        self.queue.append(ptr)
 | 
			
		||||
    def process_queue(self):
 | 
			
		||||
        while self.queue:
 | 
			
		||||
            ptr = self.queue.pop(0)
 | 
			
		||||
            if long(ptr) in self.seen:
 | 
			
		||||
                continue
 | 
			
		||||
            self.print_item(ptr)
 | 
			
		||||
    def print_item(self, ptr, offset = gdb.Value(0), level = 0):
 | 
			
		||||
        self.seen.add(long(ptr))
 | 
			
		||||
        addr = ptr['addr']
 | 
			
		||||
        addr += offset
 | 
			
		||||
        size = int128(ptr['size'])
 | 
			
		||||
        alias = ptr['alias']
 | 
			
		||||
        klass = ''
 | 
			
		||||
        if not isnull(alias):
 | 
			
		||||
            klass = ' (alias)'
 | 
			
		||||
        elif not isnull(ptr['ops']):
 | 
			
		||||
            klass = ' (I/O)'
 | 
			
		||||
        elif bool(ptr['ram']):
 | 
			
		||||
            klass = ' (RAM)'
 | 
			
		||||
        gdb.write('%s%016x-%016x %s%s (@ %s)\n'
 | 
			
		||||
                  % ('  ' * level,
 | 
			
		||||
                     long(addr),
 | 
			
		||||
                     long(addr + (size - 1)),
 | 
			
		||||
                     ptr['name'].string(),
 | 
			
		||||
                     klass,
 | 
			
		||||
                     ptr,
 | 
			
		||||
                     ),
 | 
			
		||||
                  gdb.STDOUT)
 | 
			
		||||
        if not isnull(alias):
 | 
			
		||||
            gdb.write('%s    alias: %s@%016x (@ %s)\n' %
 | 
			
		||||
                      ('  ' * level,
 | 
			
		||||
                       alias['name'].string(),
 | 
			
		||||
                       ptr['alias_offset'],
 | 
			
		||||
                       alias,
 | 
			
		||||
                       ),
 | 
			
		||||
                      gdb.STDOUT)
 | 
			
		||||
            self.queue.append(alias)
 | 
			
		||||
        subregion = ptr['subregions']['tqh_first']
 | 
			
		||||
        level += 1
 | 
			
		||||
        while not isnull(subregion):
 | 
			
		||||
            self.print_item(subregion, addr, level)
 | 
			
		||||
            subregion = subregion['subregions_link']['tqe_next']
 | 
			
		||||
 | 
			
		||||
QemuCommand()
 | 
			
		||||
CoroutineCommand()
 | 
			
		||||
MtreeCommand()
 | 
			
		||||
mtree.MtreeCommand()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,28 @@
 | 
			
		|||
#!/usr/bin/python
 | 
			
		||||
 | 
			
		||||
# GDB debugging support
 | 
			
		||||
#
 | 
			
		||||
# Copyright (c) 2015 Linaro Ltd
 | 
			
		||||
#
 | 
			
		||||
# This program is free software; you can redistribute it and/or
 | 
			
		||||
# modify it under the terms of the GNU General Public License
 | 
			
		||||
# as published by the Free Software Foundation; either version 2
 | 
			
		||||
# of the License, or (at your option) any later version.
 | 
			
		||||
#
 | 
			
		||||
# This program is distributed in the hope that it will be useful,
 | 
			
		||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
# GNU General Public License for more details.
 | 
			
		||||
#
 | 
			
		||||
# You should have received a copy of the GNU General Public License
 | 
			
		||||
# along with this program; if not, see
 | 
			
		||||
# <http://www.gnu.org/licenses/gpl-2.0.html>
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
# We don't need to do anything in our init file currently.
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Support routines for debugging QEMU under GDB
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
__license__    = "GPL version 2 or (at your option) any later version"
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,82 @@
 | 
			
		|||
#!/usr/bin/python
 | 
			
		||||
 | 
			
		||||
# GDB debugging support
 | 
			
		||||
#
 | 
			
		||||
# Copyright 2012 Red Hat, Inc. and/or its affiliates
 | 
			
		||||
#
 | 
			
		||||
# Authors:
 | 
			
		||||
#  Avi Kivity <avi@redhat.com>
 | 
			
		||||
#
 | 
			
		||||
# This work is licensed under the terms of the GNU GPL, version 2.  See
 | 
			
		||||
# the COPYING file in the top-level directory.
 | 
			
		||||
#
 | 
			
		||||
# Contributions after 2012-01-13 are licensed under the terms of the
 | 
			
		||||
# GNU GPL, version 2 or (at your option) any later version.
 | 
			
		||||
 | 
			
		||||
# 'qemu mtree' -- display the memory hierarchy
 | 
			
		||||
 | 
			
		||||
import gdb
 | 
			
		||||
 | 
			
		||||
def isnull(ptr):
 | 
			
		||||
    return ptr == gdb.Value(0).cast(ptr.type)
 | 
			
		||||
 | 
			
		||||
def int128(p):
 | 
			
		||||
    return long(p['lo']) + (long(p['hi']) << 64)
 | 
			
		||||
 | 
			
		||||
class MtreeCommand(gdb.Command):
 | 
			
		||||
    '''Display the memory tree hierarchy'''
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        gdb.Command.__init__(self, 'qemu mtree', gdb.COMMAND_DATA,
 | 
			
		||||
                             gdb.COMPLETE_NONE)
 | 
			
		||||
        self.queue = []
 | 
			
		||||
    def invoke(self, arg, from_tty):
 | 
			
		||||
        self.seen = set()
 | 
			
		||||
        self.queue_root('address_space_memory')
 | 
			
		||||
        self.queue_root('address_space_io')
 | 
			
		||||
        self.process_queue()
 | 
			
		||||
    def queue_root(self, varname):
 | 
			
		||||
        ptr = gdb.parse_and_eval(varname)['root']
 | 
			
		||||
        self.queue.append(ptr)
 | 
			
		||||
    def process_queue(self):
 | 
			
		||||
        while self.queue:
 | 
			
		||||
            ptr = self.queue.pop(0)
 | 
			
		||||
            if long(ptr) in self.seen:
 | 
			
		||||
                continue
 | 
			
		||||
            self.print_item(ptr)
 | 
			
		||||
    def print_item(self, ptr, offset = gdb.Value(0), level = 0):
 | 
			
		||||
        self.seen.add(long(ptr))
 | 
			
		||||
        addr = ptr['addr']
 | 
			
		||||
        addr += offset
 | 
			
		||||
        size = int128(ptr['size'])
 | 
			
		||||
        alias = ptr['alias']
 | 
			
		||||
        klass = ''
 | 
			
		||||
        if not isnull(alias):
 | 
			
		||||
            klass = ' (alias)'
 | 
			
		||||
        elif not isnull(ptr['ops']):
 | 
			
		||||
            klass = ' (I/O)'
 | 
			
		||||
        elif bool(ptr['ram']):
 | 
			
		||||
            klass = ' (RAM)'
 | 
			
		||||
        gdb.write('%s%016x-%016x %s%s (@ %s)\n'
 | 
			
		||||
                  % ('  ' * level,
 | 
			
		||||
                     long(addr),
 | 
			
		||||
                     long(addr + (size - 1)),
 | 
			
		||||
                     ptr['name'].string(),
 | 
			
		||||
                     klass,
 | 
			
		||||
                     ptr,
 | 
			
		||||
                     ),
 | 
			
		||||
                  gdb.STDOUT)
 | 
			
		||||
        if not isnull(alias):
 | 
			
		||||
            gdb.write('%s    alias: %s@%016x (@ %s)\n' %
 | 
			
		||||
                      ('  ' * level,
 | 
			
		||||
                       alias['name'].string(),
 | 
			
		||||
                       ptr['alias_offset'],
 | 
			
		||||
                       alias,
 | 
			
		||||
                       ),
 | 
			
		||||
                      gdb.STDOUT)
 | 
			
		||||
            self.queue.append(alias)
 | 
			
		||||
        subregion = ptr['subregions']['tqh_first']
 | 
			
		||||
        level += 1
 | 
			
		||||
        while not isnull(subregion):
 | 
			
		||||
            self.print_item(subregion, addr, level)
 | 
			
		||||
            subregion = subregion['subregions_link']['tqe_next']
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue