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
))
23 "Step an instruction, check it moved."
24 start_pc
= gdb
.parse_and_eval('$pc')
26 end_pc
= gdb
.parse_and_eval('$pc')
28 return not (start_pc
== end_pc
)
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
)
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
))
43 # can we test we hit bp?
44 return end_pc
== sym
.value()
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
))
54 # hopefully we came back
55 end_pc
= gdb
.parse_and_eval('$pc')
56 print ("%s == %s" % (end_pc
, sym
.value()))
58 if end_pc
== sym
.value():
65 class WatchPoint(gdb
.Breakpoint
):
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
)
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)
81 end_pc
= gdb
.parse_and_eval('$pc')
82 print ("HIT WP @ %s" % (end_pc
))
86 def do_one_watch(sym
, wtype
, text
):
88 wp
= WatchPoint(sym
, wtype
)
90 report_str
= "%s for %s (%s)" % (text
, sym
, wp
.sym
.value())
93 report(True, report_str
)
96 report(False, report_str
)
99 def check_watches(sym_name
):
100 "Watch a symbol for any access."
102 # Should hit for any read
103 do_one_watch(sym_name
, gdb
.WP_ACCESS
, "awatch")
105 # Again should hit for reads
106 do_one_watch(sym_name
, gdb
.WP_READ
, "rwatch")
108 # Finally when it is written
109 do_one_watch(sym_name
, gdb
.WP_WRITE
, "watch")
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
)
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")
125 "Run through the tests one by one"
127 print ("Checking we can step the first few instructions")
133 report(step_ok
== 3, "single step in boot code")
135 print ("Checking HW breakpoint works")
136 break_ok
= check_hbreak("kernel_init")
137 report(break_ok
, "hbreak @ kernel_init")
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")
146 print ("Checking Normal breakpoint works")
147 break_ok
= check_break("wait_for_completion")
148 report(break_ok
, "break @ wait_for_completion")
150 print ("Checking watchpoint works")
151 check_watches("system_state")
154 # This runs as the script it sourced (via -x)
158 print ("Connecting to remote")
159 gdb
.execute("target remote localhost:1234")
161 # These are not very useful in scripts
162 gdb
.execute("set pagination off")
163 gdb
.execute("set confirm off")
165 # Run the actual tests
169 print ("GDB Exception: %s" % (sys
.exc_info()[0]))
172 code
.InteractiveConsole(locals=globals()).interact()
175 # Finally kill the inferior and exit gdb with a count of failures