Merge tag 'qemu-macppc-20230206' of https://github.com/mcayland/qemu into staging
[qemu.git] / tests / tcg / multiarch / gdbstub / memory.py
blob67864ad9029be078f3cfe89eedf986ba593104de
1 from __future__ import print_function
3 # Test some of the softmmu debug features with the multiarch memory
4 # test. It is a port of the original vmlinux focused test case but
5 # using the "memory" test instead.
7 # This is launched via tests/guest-debug/run-test.py
10 import gdb
11 import sys
13 failcount = 0
16 def report(cond, msg):
17 "Report success/fail of test"
18 if cond:
19 print("PASS: %s" % (msg))
20 else:
21 print("FAIL: %s" % (msg))
22 global failcount
23 failcount += 1
26 def check_step():
27 "Step an instruction, check it moved."
28 start_pc = gdb.parse_and_eval('$pc')
29 gdb.execute("si")
30 end_pc = gdb.parse_and_eval('$pc')
32 return not (start_pc == end_pc)
36 # Currently it's hard to create a hbreak with the pure python API and
37 # manually matching PC to symbol address is a bit flaky thanks to
38 # function prologues. However internally QEMU's gdbstub treats them
39 # the same as normal breakpoints so it will do for now.
41 def check_break(sym_name):
42 "Setup breakpoint, continue and check we stopped."
43 sym, ok = gdb.lookup_symbol(sym_name)
44 bp = gdb.Breakpoint(sym_name, gdb.BP_BREAKPOINT)
46 gdb.execute("c")
48 # hopefully we came back
49 end_pc = gdb.parse_and_eval('$pc')
50 report(bp.hit_count == 1,
51 "break @ %s (%s %d hits)" % (end_pc, sym.value(), bp.hit_count))
53 bp.delete()
56 def do_one_watch(sym, wtype, text):
58 wp = gdb.Breakpoint(sym, gdb.BP_WATCHPOINT, wtype)
59 gdb.execute("c")
60 report_str = "%s for %s" % (text, sym)
62 if wp.hit_count > 0:
63 report(True, report_str)
64 wp.delete()
65 else:
66 report(False, report_str)
69 def check_watches(sym_name):
70 "Watch a symbol for any access."
72 # Should hit for any read
73 do_one_watch(sym_name, gdb.WP_ACCESS, "awatch")
75 # Again should hit for reads
76 do_one_watch(sym_name, gdb.WP_READ, "rwatch")
78 # Finally when it is written
79 do_one_watch(sym_name, gdb.WP_WRITE, "watch")
82 def run_test():
83 "Run through the tests one by one"
85 print("Checking we can step the first few instructions")
86 step_ok = 0
87 for i in range(3):
88 if check_step():
89 step_ok += 1
91 report(step_ok == 3, "single step in boot code")
93 # If we get here we have missed some of the other breakpoints.
94 print("Setup catch-all for _exit")
95 cbp = gdb.Breakpoint("_exit", gdb.BP_BREAKPOINT)
97 check_break("main")
98 check_watches("test_data[128]")
100 report(cbp.hit_count == 0, "didn't reach backstop")
103 # This runs as the script it sourced (via -x, via run-test.py)
105 try:
106 inferior = gdb.selected_inferior()
107 arch = inferior.architecture()
108 print("ATTACHED: %s" % arch.name())
109 except (gdb.error, AttributeError):
110 print("SKIPPING (not connected)", file=sys.stderr)
111 exit(0)
113 if gdb.parse_and_eval('$pc') == 0:
114 print("SKIP: PC not set")
115 exit(0)
117 try:
118 # These are not very useful in scripts
119 gdb.execute("set pagination off")
121 # Run the actual tests
122 run_test()
123 except (gdb.error):
124 print("GDB Exception: %s" % (sys.exc_info()[0]))
125 failcount += 1
126 pass
128 # Finally kill the inferior and exit gdb with a count of failures
129 gdb.execute("kill")
130 exit(failcount)