These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / tests / guest-debug / test-gdbstub.py
1 #
2 # This script needs to be run on startup
3 # qemu -kernel ${KERNEL} -s -S
4 # and then:
5 # gdb ${KERNEL}.vmlinux -x ${QEMU_SRC}/tests/guest-debug/test-gdbstub.py
6
7 import gdb
8
9 failcount = 0
10
11
12 def report(cond, msg):
13     "Report success/fail of test"
14     if cond:
15         print ("PASS: %s" % (msg))
16     else:
17         print ("FAIL: %s" % (msg))
18         failcount += 1
19
20
21 def check_step():
22     "Step an instruction, check it moved."
23     start_pc = gdb.parse_and_eval('$pc')
24     gdb.execute("si")
25     end_pc = gdb.parse_and_eval('$pc')
26
27     return not (start_pc == end_pc)
28
29
30 def check_break(sym_name):
31     "Setup breakpoint, continue and check we stopped."
32     sym, ok = gdb.lookup_symbol(sym_name)
33     bp = gdb.Breakpoint(sym_name)
34
35     gdb.execute("c")
36
37     # hopefully we came back
38     end_pc = gdb.parse_and_eval('$pc')
39     print ("%s == %s %d" % (end_pc, sym.value(), bp.hit_count))
40     bp.delete()
41
42     # can we test we hit bp?
43     return end_pc == sym.value()
44
45
46 # We need to do hbreak manually as the python interface doesn't export it
47 def check_hbreak(sym_name):
48     "Setup hardware breakpoint, continue and check we stopped."
49     sym, ok = gdb.lookup_symbol(sym_name)
50     gdb.execute("hbreak %s" % (sym_name))
51     gdb.execute("c")
52
53     # hopefully we came back
54     end_pc = gdb.parse_and_eval('$pc')
55     print ("%s == %s" % (end_pc, sym.value()))
56
57     if end_pc == sym.value():
58         gdb.execute("d 1")
59         return True
60     else:
61         return False
62
63
64 class WatchPoint(gdb.Breakpoint):
65
66     def get_wpstr(self, sym_name):
67         "Setup sym and wp_str for given symbol."
68         self.sym, ok = gdb.lookup_symbol(sym_name)
69         wp_addr = gdb.parse_and_eval(sym_name).address
70         self.wp_str = '*(%(type)s)(&%(address)s)' % dict(
71             type = wp_addr.type, address = sym_name)
72
73         return(self.wp_str)
74
75     def __init__(self, sym_name, type):
76         wp_str = self.get_wpstr(sym_name)
77         super(WatchPoint, self).__init__(wp_str, gdb.BP_WATCHPOINT, type)
78
79     def stop(self):
80         end_pc = gdb.parse_and_eval('$pc')
81         print ("HIT WP @ %s" % (end_pc))
82         return True
83
84
85 def do_one_watch(sym, wtype, text):
86
87     wp = WatchPoint(sym, wtype)
88     gdb.execute("c")
89     report_str = "%s for %s (%s)" % (text, sym, wp.sym.value())
90
91     if wp.hit_count > 0:
92         report(True, report_str)
93         wp.delete()
94     else:
95         report(False, report_str)
96
97
98 def check_watches(sym_name):
99     "Watch a symbol for any access."
100
101     # Should hit for any read
102     do_one_watch(sym_name, gdb.WP_ACCESS, "awatch")
103
104     # Again should hit for reads
105     do_one_watch(sym_name, gdb.WP_READ, "rwatch")
106
107     # Finally when it is written
108     do_one_watch(sym_name, gdb.WP_WRITE, "watch")
109
110
111 class CatchBreakpoint(gdb.Breakpoint):
112     def __init__(self, sym_name):
113         super(CatchBreakpoint, self).__init__(sym_name)
114         self.sym, ok = gdb.lookup_symbol(sym_name)
115
116     def stop(self):
117         end_pc = gdb.parse_and_eval('$pc')
118         print ("CB: %s == %s" % (end_pc, self.sym.value()))
119         if end_pc == self.sym.value():
120             report(False, "Hit final catchpoint")
121
122
123 def run_test():
124     "Run throught the tests one by one"
125
126     print ("Checking we can step the first few instructions")
127     step_ok = 0
128     for i in range(3):
129         if check_step():
130             step_ok += 1
131
132     report(step_ok == 3, "single step in boot code")
133
134     print ("Checking HW breakpoint works")
135     break_ok = check_hbreak("kernel_init")
136     report(break_ok, "hbreak @ kernel_init")
137
138     # Can't set this up until we are in the kernel proper
139     # if we make it to run_init_process we've over-run and
140     # one of the tests failed
141     print ("Setup catch-all for run_init_process")
142     cbp = CatchBreakpoint("run_init_process")
143     cpb2 = CatchBreakpoint("try_to_run_init_process")
144
145     print ("Checking Normal breakpoint works")
146     break_ok = check_break("wait_for_completion")
147     report(break_ok, "break @ wait_for_completion")
148
149     print ("Checking watchpoint works")
150     check_watches("system_state")
151
152 #
153 # This runs as the script it sourced (via -x)
154 #
155
156 try:
157     print ("Connecting to remote")
158     gdb.execute("target remote localhost:1234")
159
160     # These are not very useful in scripts
161     gdb.execute("set pagination off")
162     gdb.execute("set confirm off")
163
164     # Run the actual tests
165     run_test()
166
167 except:
168     print ("GDB Exception: %s" % (sys.exc_info()[0]))
169     failcount += 1
170     import code
171     code.InteractiveConsole(locals=globals()).interact()
172     raise
173
174 # Finally kill the inferior and exit gdb with a count of failures
175 gdb.execute("kill")
176 exit(failcount)