2 # This script needs to be run on startup
3 # qemu -kernel ${KERNEL} -s -S
5 # gdb ${KERNEL}.vmlinux -x ${QEMU_SRC}/tests/guest-debug/test-gdbstub.py
12 def report(cond
, msg
):
13 "Report success/fail of test"
15 print ("PASS: %s" % (msg
))
17 print ("FAIL: %s" % (msg
))
22 "Step an instruction, check it moved."
23 start_pc
= gdb
.parse_and_eval('$pc')
25 end_pc
= gdb
.parse_and_eval('$pc')
27 return not (start_pc
== end_pc
)
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
)
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
))
42 # can we test we hit bp?
43 return end_pc
== sym
.value()
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
))
53 # hopefully we came back
54 end_pc
= gdb
.parse_and_eval('$pc')
55 print ("%s == %s" % (end_pc
, sym
.value()))
57 if end_pc
== sym
.value():
64 class WatchPoint(gdb
.Breakpoint
):
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
)
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)
80 end_pc
= gdb
.parse_and_eval('$pc')
81 print ("HIT WP @ %s" % (end_pc
))
85 def do_one_watch(sym
, wtype
, text
):
87 wp
= WatchPoint(sym
, wtype
)
89 report_str
= "%s for %s (%s)" % (text
, sym
, wp
.sym
.value())
92 report(True, report_str
)
95 report(False, report_str
)
98 def check_watches(sym_name
):
99 "Watch a symbol for any access."
101 # Should hit for any read
102 do_one_watch(sym_name
, gdb
.WP_ACCESS
, "awatch")
104 # Again should hit for reads
105 do_one_watch(sym_name
, gdb
.WP_READ
, "rwatch")
107 # Finally when it is written
108 do_one_watch(sym_name
, gdb
.WP_WRITE
, "watch")
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
)
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")
124 "Run throught the tests one by one"
126 print ("Checking we can step the first few instructions")
132 report(step_ok
== 3, "single step in boot code")
134 print ("Checking HW breakpoint works")
135 break_ok
= check_hbreak("kernel_init")
136 report(break_ok
, "hbreak @ kernel_init")
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")
145 print ("Checking Normal breakpoint works")
146 break_ok
= check_break("wait_for_completion")
147 report(break_ok
, "break @ wait_for_completion")
149 print ("Checking watchpoint works")
150 check_watches("system_state")
153 # This runs as the script it sourced (via -x)
157 print ("Connecting to remote")
158 gdb
.execute("target remote localhost:1234")
160 # These are not very useful in scripts
161 gdb
.execute("set pagination off")
162 gdb
.execute("set confirm off")
164 # Run the actual tests
168 print ("GDB Exception: %s" % (sys
.exc_info()[0]))
171 code
.InteractiveConsole(locals=globals()).interact()
174 # Finally kill the inferior and exit gdb with a count of failures