]>
Commit | Line | Data |
---|---|---|
4daa187d AK |
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 <[email protected]> | |
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 | ||
17 | import gdb | |
18 | ||
19 | def isnull(ptr): | |
20 | return ptr == gdb.Value(0).cast(ptr.type) | |
21 | ||
22 | def int128(p): | |
23 | return long(p['lo']) + (long(p['hi']) << 64) | |
24 | ||
25 | class QemuCommand(gdb.Command): | |
26 | '''Prefix for QEMU debug support commands''' | |
27 | def __init__(self): | |
28 | gdb.Command.__init__(self, 'qemu', gdb.COMMAND_DATA, | |
29 | gdb.COMPLETE_NONE, True) | |
30 | ||
31 | class MtreeCommand(gdb.Command): | |
32 | '''Display the memory tree hierarchy''' | |
33 | def __init__(self): | |
34 | gdb.Command.__init__(self, 'qemu mtree', gdb.COMMAND_DATA, | |
35 | gdb.COMPLETE_NONE) | |
36 | self.queue = [] | |
37 | def invoke(self, arg, from_tty): | |
38 | self.seen = set() | |
39 | self.queue_root('address_space_memory') | |
40 | self.queue_root('address_space_io') | |
41 | self.process_queue() | |
42 | def queue_root(self, varname): | |
43 | ptr = gdb.parse_and_eval(varname)['root'] | |
44 | self.queue.append(ptr) | |
45 | def process_queue(self): | |
46 | while self.queue: | |
47 | ptr = self.queue.pop(0) | |
48 | if long(ptr) in self.seen: | |
49 | continue | |
50 | self.print_item(ptr) | |
51 | def print_item(self, ptr, offset = gdb.Value(0), level = 0): | |
52 | self.seen.add(long(ptr)) | |
53 | addr = ptr['addr'] | |
54 | addr += offset | |
55 | size = int128(ptr['size']) | |
56 | alias = ptr['alias'] | |
57 | klass = '' | |
58 | if not isnull(alias): | |
59 | klass = ' (alias)' | |
60 | elif not isnull(ptr['ops']): | |
61 | klass = ' (I/O)' | |
62 | elif bool(ptr['ram']): | |
63 | klass = ' (RAM)' | |
64 | gdb.write('%s%016x-%016x %s%s (@ %s)\n' | |
65 | % (' ' * level, | |
66 | long(addr), | |
67 | long(addr + (size - 1)), | |
68 | ptr['name'].string(), | |
69 | klass, | |
70 | ptr, | |
71 | ), | |
72 | gdb.STDOUT) | |
73 | if not isnull(alias): | |
74 | gdb.write('%s alias: %s@%016x (@ %s)\n' % | |
75 | (' ' * level, | |
76 | alias['name'].string(), | |
77 | ptr['alias_offset'], | |
78 | alias, | |
79 | ), | |
80 | gdb.STDOUT) | |
81 | self.queue.append(alias) | |
82 | subregion = ptr['subregions']['tqh_first'] | |
83 | level += 1 | |
84 | while not isnull(subregion): | |
85 | self.print_item(subregion, addr, level) | |
86 | subregion = subregion['subregions_link']['tqe_next'] | |
87 | ||
88 | QemuCommand() | |
89 | MtreeCommand() |