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