Add qemu 2.4.0
[kvmfornfv.git] / qemu / scripts / qemu-gdb.py
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 <avi@redhat.com>
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 def get_fs_base():
26     '''Fetch %fs base value using arch_prctl(ARCH_GET_FS)'''
27     # %rsp - 120 is scratch space according to the SystemV ABI
28     old = gdb.parse_and_eval('*(uint64_t*)($rsp - 120)')
29     gdb.execute('call arch_prctl(0x1003, $rsp - 120)', False, True)
30     fs_base = gdb.parse_and_eval('*(uint64_t*)($rsp - 120)')
31     gdb.execute('set *(uint64_t*)($rsp - 120) = %s' % old, False, True)
32     return fs_base
33
34 def get_glibc_pointer_guard():
35     '''Fetch glibc pointer guard value'''
36     fs_base = get_fs_base()
37     return gdb.parse_and_eval('*(uint64_t*)((uint64_t)%s + 0x30)' % fs_base)
38
39 def glibc_ptr_demangle(val, pointer_guard):
40     '''Undo effect of glibc's PTR_MANGLE()'''
41     return gdb.parse_and_eval('(((uint64_t)%s >> 0x11) | ((uint64_t)%s << (64 - 0x11))) ^ (uint64_t)%s' % (val, val, pointer_guard))
42
43 def bt_jmpbuf(jmpbuf):
44     '''Backtrace a jmpbuf'''
45     JB_RBX  = 0
46     JB_RBP  = 1
47     JB_R12  = 2
48     JB_R13  = 3
49     JB_R14  = 4
50     JB_R15  = 5
51     JB_RSP  = 6
52     JB_PC   = 7
53
54     old_rbx = gdb.parse_and_eval('(uint64_t)$rbx')
55     old_rbp = gdb.parse_and_eval('(uint64_t)$rbp')
56     old_rsp = gdb.parse_and_eval('(uint64_t)$rsp')
57     old_r12 = gdb.parse_and_eval('(uint64_t)$r12')
58     old_r13 = gdb.parse_and_eval('(uint64_t)$r13')
59     old_r14 = gdb.parse_and_eval('(uint64_t)$r14')
60     old_r15 = gdb.parse_and_eval('(uint64_t)$r15')
61     old_rip = gdb.parse_and_eval('(uint64_t)$rip')
62
63     pointer_guard = get_glibc_pointer_guard()
64     gdb.execute('set $rbx = %s' % jmpbuf[JB_RBX])
65     gdb.execute('set $rbp = %s' % glibc_ptr_demangle(jmpbuf[JB_RBP], pointer_guard))
66     gdb.execute('set $rsp = %s' % glibc_ptr_demangle(jmpbuf[JB_RSP], pointer_guard))
67     gdb.execute('set $r12 = %s' % jmpbuf[JB_R12])
68     gdb.execute('set $r13 = %s' % jmpbuf[JB_R13])
69     gdb.execute('set $r14 = %s' % jmpbuf[JB_R14])
70     gdb.execute('set $r15 = %s' % jmpbuf[JB_R15])
71     gdb.execute('set $rip = %s' % glibc_ptr_demangle(jmpbuf[JB_PC], pointer_guard))
72
73     gdb.execute('bt')
74
75     gdb.execute('set $rbx = %s' % old_rbx)
76     gdb.execute('set $rbp = %s' % old_rbp)
77     gdb.execute('set $rsp = %s' % old_rsp)
78     gdb.execute('set $r12 = %s' % old_r12)
79     gdb.execute('set $r13 = %s' % old_r13)
80     gdb.execute('set $r14 = %s' % old_r14)
81     gdb.execute('set $r15 = %s' % old_r15)
82     gdb.execute('set $rip = %s' % old_rip)
83
84 class QemuCommand(gdb.Command):
85     '''Prefix for QEMU debug support commands'''
86     def __init__(self):
87         gdb.Command.__init__(self, 'qemu', gdb.COMMAND_DATA,
88                              gdb.COMPLETE_NONE, True)
89
90 class CoroutineCommand(gdb.Command):
91     '''Display coroutine backtrace'''
92     def __init__(self):
93         gdb.Command.__init__(self, 'qemu coroutine', gdb.COMMAND_DATA,
94                              gdb.COMPLETE_NONE)
95
96     def invoke(self, arg, from_tty):
97         argv = gdb.string_to_argv(arg)
98         if len(argv) != 1:
99             gdb.write('usage: qemu coroutine <coroutine-pointer>\n')
100             return
101
102         coroutine_pointer = gdb.parse_and_eval(argv[0]).cast(gdb.lookup_type('CoroutineUContext').pointer())
103         bt_jmpbuf(coroutine_pointer['env']['__jmpbuf'])
104
105 class MtreeCommand(gdb.Command):
106     '''Display the memory tree hierarchy'''
107     def __init__(self):
108         gdb.Command.__init__(self, 'qemu mtree', gdb.COMMAND_DATA,
109                              gdb.COMPLETE_NONE)
110         self.queue = []
111     def invoke(self, arg, from_tty):
112         self.seen = set()
113         self.queue_root('address_space_memory')
114         self.queue_root('address_space_io')
115         self.process_queue()
116     def queue_root(self, varname):
117         ptr = gdb.parse_and_eval(varname)['root']
118         self.queue.append(ptr)
119     def process_queue(self):
120         while self.queue:
121             ptr = self.queue.pop(0)
122             if long(ptr) in self.seen:
123                 continue
124             self.print_item(ptr)
125     def print_item(self, ptr, offset = gdb.Value(0), level = 0):
126         self.seen.add(long(ptr))
127         addr = ptr['addr']
128         addr += offset
129         size = int128(ptr['size'])
130         alias = ptr['alias']
131         klass = ''
132         if not isnull(alias):
133             klass = ' (alias)'
134         elif not isnull(ptr['ops']):
135             klass = ' (I/O)'
136         elif bool(ptr['ram']):
137             klass = ' (RAM)'
138         gdb.write('%s%016x-%016x %s%s (@ %s)\n'
139                   % ('  ' * level,
140                      long(addr),
141                      long(addr + (size - 1)),
142                      ptr['name'].string(),
143                      klass,
144                      ptr,
145                      ),
146                   gdb.STDOUT)
147         if not isnull(alias):
148             gdb.write('%s    alias: %s@%016x (@ %s)\n' %
149                       ('  ' * level,
150                        alias['name'].string(),
151                        ptr['alias_offset'],
152                        alias,
153                        ),
154                       gdb.STDOUT)
155             self.queue.append(alias)
156         subregion = ptr['subregions']['tqh_first']
157         level += 1
158         while not isnull(subregion):
159             self.print_item(subregion, addr, level)
160             subregion = subregion['subregions_link']['tqe_next']
161
162 QemuCommand()
163 CoroutineCommand()
164 MtreeCommand()