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