Skip to content

Commit

Permalink
scripts/qemu-gdb: Split MtreeCommand into its own module
Browse files Browse the repository at this point in the history
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
  • Loading branch information
pm215 committed Sep 11, 2015
1 parent ba9cef7 commit 93b1b36
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 62 deletions.
70 changes: 8 additions & 62 deletions scripts/qemu-gdb.py
Expand Up @@ -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)'''
Expand Down Expand Up @@ -102,63 +105,6 @@ def invoke(self, arg, from_tty):
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()
28 changes: 28 additions & 0 deletions scripts/qemugdb/__init__.py
@@ -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"
82 changes: 82 additions & 0 deletions scripts/qemugdb/mtree.py
@@ -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']

0 comments on commit 93b1b36

Please sign in to comment.