1 from __future__
import print_function
3 # This script needs to be run on startup
4 # qemu -kernel ${KERNEL} -s -S
6 # gdb ${KERNEL}.vmlinux -x ${QEMU_SRC}/tests/guest-debug/test-gdbstub.py
13 def report(cond
, msg
):
14 "Report success/fail of test"
16 print ("PASS: %s" % (msg
))
18 print ("FAIL: %s" % (msg
))
24 "Step an instruction, check it moved."
25 start_pc
= gdb
.parse_and_eval('$pc')
27 end_pc
= gdb
.parse_and_eval('$pc')
29 return not (start_pc
== end_pc
)
32 def check_break(sym_name
):
33 "Setup breakpoint, continue and check we stopped."
34 sym
, ok
= gdb
.lookup_symbol(sym_name
)
35 bp
= gdb
.Breakpoint(sym_name
)
39 # hopefully we came back
40 end_pc
= gdb
.parse_and_eval('$pc')
41 print ("%s == %s %d" % (end_pc
, sym
.value(), bp
.hit_count
))
44 # can we test we hit bp?
45 return end_pc
== sym
.value()
48 # We need to do hbreak manually as the python interface doesn't export it
49 def check_hbreak(sym_name
):
50 "Setup hardware breakpoint, continue and check we stopped."
51 sym
, ok
= gdb
.lookup_symbol(sym_name
)
52 gdb
.execute("hbreak %s" % (sym_name
))
55 # hopefully we came back
56 end_pc
= gdb
.parse_and_eval('$pc')
57 print ("%s == %s" % (end_pc
, sym
.value()))
59 if end_pc
== sym
.value():
66 class WatchPoint(gdb
.Breakpoint
):
68 def get_wpstr(self
, sym_name
):
69 "Setup sym and wp_str for given symbol."
70 self
.sym
, ok
= gdb
.lookup_symbol(sym_name
)
71 wp_addr
= gdb
.parse_and_eval(sym_name
).address
72 self
.wp_str
= '*(%(type)s)(&%(address)s)' % dict(
73 type = wp_addr
.type, address
= sym_name
)
77 def __init__(self
, sym_name
, type):
78 wp_str
= self
.get_wpstr(sym_name
)
79 super(WatchPoint
, self
).__init
__(wp_str
, gdb
.BP_WATCHPOINT
, type)
82 end_pc
= gdb
.parse_and_eval('$pc')
83 print ("HIT WP @ %s" % (end_pc
))
87 def do_one_watch(sym
, wtype
, text
):
89 wp
= WatchPoint(sym
, wtype
)
91 report_str
= "%s for %s (%s)" % (text
, sym
, wp
.sym
.value())
94 report(True, report_str
)
97 report(False, report_str
)
100 def check_watches(sym_name
):
101 "Watch a symbol for any access."
103 # Should hit for any read
104 do_one_watch(sym_name
, gdb
.WP_ACCESS
, "awatch")
106 # Again should hit for reads
107 do_one_watch(sym_name
, gdb
.WP_READ
, "rwatch")
109 # Finally when it is written
110 do_one_watch(sym_name
, gdb
.WP_WRITE
, "watch")
113 class CatchBreakpoint(gdb
.Breakpoint
):
114 def __init__(self
, sym_name
):
115 super(CatchBreakpoint
, self
).__init
__(sym_name
)
116 self
.sym
, ok
= gdb
.lookup_symbol(sym_name
)
119 end_pc
= gdb
.parse_and_eval('$pc')
120 print ("CB: %s == %s" % (end_pc
, self
.sym
.value()))
121 if end_pc
== self
.sym
.value():
122 report(False, "Hit final catchpoint")
126 "Run through the tests one by one"
128 print ("Checking we can step the first few instructions")
134 report(step_ok
== 3, "single step in boot code")
136 print ("Checking HW breakpoint works")
137 break_ok
= check_hbreak("kernel_init")
138 report(break_ok
, "hbreak @ kernel_init")
140 # Can't set this up until we are in the kernel proper
141 # if we make it to run_init_process we've over-run and
142 # one of the tests failed
143 print ("Setup catch-all for run_init_process")
144 cbp
= CatchBreakpoint("run_init_process")
145 cpb2
= CatchBreakpoint("try_to_run_init_process")
147 print ("Checking Normal breakpoint works")
148 break_ok
= check_break("wait_for_completion")
149 report(break_ok
, "break @ wait_for_completion")
151 print ("Checking watchpoint works")
152 check_watches("system_state")
155 # This runs as the script it sourced (via -x)
159 print ("Connecting to remote")
160 gdb
.execute("target remote localhost:1234")
162 # These are not very useful in scripts
163 gdb
.execute("set pagination off")
164 gdb
.execute("set confirm off")
166 # Run the actual tests
170 print ("GDB Exception: %s" % (sys
.exc_info()[0]))
173 code
.InteractiveConsole(locals=globals()).interact()
176 # Finally kill the inferior and exit gdb with a count of failures