1c00506aaSAlex Bennéefrom __future__ import print_function
2c00506aaSAlex Bennée#
3*7893e42dSPhilippe Mathieu-Daudé# Test some of the system debug features with the multiarch memory
4c00506aaSAlex Bennée# test. It is a port of the original vmlinux focused test case but
5c00506aaSAlex Bennée# using the "memory" test instead.
6c00506aaSAlex Bennée#
7c00506aaSAlex Bennée# This is launched via tests/guest-debug/run-test.py
8c00506aaSAlex Bennée#
9c00506aaSAlex Bennée
10c00506aaSAlex Bennéeimport gdb
11c00506aaSAlex Bennéeimport sys
12c00506aaSAlex Bennée
13c00506aaSAlex Bennéefailcount = 0
14c00506aaSAlex Bennée
15c00506aaSAlex Bennée
16c00506aaSAlex Bennéedef report(cond, msg):
17c00506aaSAlex Bennée    "Report success/fail of test"
18c00506aaSAlex Bennée    if cond:
19c00506aaSAlex Bennée        print("PASS: %s" % (msg))
20c00506aaSAlex Bennée    else:
21c00506aaSAlex Bennée        print("FAIL: %s" % (msg))
22c00506aaSAlex Bennée        global failcount
23c00506aaSAlex Bennée        failcount += 1
24c00506aaSAlex Bennée
25c00506aaSAlex Bennée
26c00506aaSAlex Bennéedef check_step():
27c00506aaSAlex Bennée    "Step an instruction, check it moved."
28c00506aaSAlex Bennée    start_pc = gdb.parse_and_eval('$pc')
29c00506aaSAlex Bennée    gdb.execute("si")
30c00506aaSAlex Bennée    end_pc = gdb.parse_and_eval('$pc')
31c00506aaSAlex Bennée
32c00506aaSAlex Bennée    return not (start_pc == end_pc)
33c00506aaSAlex Bennée
34c00506aaSAlex Bennée
35c00506aaSAlex Bennée#
36c00506aaSAlex Bennée# Currently it's hard to create a hbreak with the pure python API and
37c00506aaSAlex Bennée# manually matching PC to symbol address is a bit flaky thanks to
38c00506aaSAlex Bennée# function prologues. However internally QEMU's gdbstub treats them
39c00506aaSAlex Bennée# the same as normal breakpoints so it will do for now.
40c00506aaSAlex Bennée#
41c00506aaSAlex Bennéedef check_break(sym_name):
42c00506aaSAlex Bennée    "Setup breakpoint, continue and check we stopped."
43c00506aaSAlex Bennée    sym, ok = gdb.lookup_symbol(sym_name)
44c00506aaSAlex Bennée    bp = gdb.Breakpoint(sym_name, gdb.BP_BREAKPOINT)
45c00506aaSAlex Bennée
46c00506aaSAlex Bennée    gdb.execute("c")
47c00506aaSAlex Bennée
48c00506aaSAlex Bennée    # hopefully we came back
49c00506aaSAlex Bennée    end_pc = gdb.parse_and_eval('$pc')
50c00506aaSAlex Bennée    report(bp.hit_count == 1,
51c00506aaSAlex Bennée           "break @ %s (%s %d hits)" % (end_pc, sym.value(), bp.hit_count))
52c00506aaSAlex Bennée
53c00506aaSAlex Bennée    bp.delete()
54c00506aaSAlex Bennée
55c00506aaSAlex Bennée
56c00506aaSAlex Bennéedef do_one_watch(sym, wtype, text):
57c00506aaSAlex Bennée
58c00506aaSAlex Bennée    wp = gdb.Breakpoint(sym, gdb.BP_WATCHPOINT, wtype)
59c00506aaSAlex Bennée    gdb.execute("c")
60c00506aaSAlex Bennée    report_str = "%s for %s" % (text, sym)
61c00506aaSAlex Bennée
62c00506aaSAlex Bennée    if wp.hit_count > 0:
63c00506aaSAlex Bennée        report(True, report_str)
64c00506aaSAlex Bennée        wp.delete()
65c00506aaSAlex Bennée    else:
66c00506aaSAlex Bennée        report(False, report_str)
67c00506aaSAlex Bennée
68c00506aaSAlex Bennée
69c00506aaSAlex Bennéedef check_watches(sym_name):
70c00506aaSAlex Bennée    "Watch a symbol for any access."
71c00506aaSAlex Bennée
72c00506aaSAlex Bennée    # Should hit for any read
73c00506aaSAlex Bennée    do_one_watch(sym_name, gdb.WP_ACCESS, "awatch")
74c00506aaSAlex Bennée
75c00506aaSAlex Bennée    # Again should hit for reads
76c00506aaSAlex Bennée    do_one_watch(sym_name, gdb.WP_READ, "rwatch")
77c00506aaSAlex Bennée
78c00506aaSAlex Bennée    # Finally when it is written
79c00506aaSAlex Bennée    do_one_watch(sym_name, gdb.WP_WRITE, "watch")
80c00506aaSAlex Bennée
81c00506aaSAlex Bennée
82c00506aaSAlex Bennéedef run_test():
83c00506aaSAlex Bennée    "Run through the tests one by one"
84c00506aaSAlex Bennée
85c00506aaSAlex Bennée    print("Checking we can step the first few instructions")
86c00506aaSAlex Bennée    step_ok = 0
87c00506aaSAlex Bennée    for i in range(3):
88c00506aaSAlex Bennée        if check_step():
89c00506aaSAlex Bennée            step_ok += 1
90c00506aaSAlex Bennée
91c00506aaSAlex Bennée    report(step_ok == 3, "single step in boot code")
92c00506aaSAlex Bennée
93c00506aaSAlex Bennée    # If we get here we have missed some of the other breakpoints.
94c00506aaSAlex Bennée    print("Setup catch-all for _exit")
95c00506aaSAlex Bennée    cbp = gdb.Breakpoint("_exit", gdb.BP_BREAKPOINT)
96c00506aaSAlex Bennée
97c00506aaSAlex Bennée    check_break("main")
98c00506aaSAlex Bennée    check_watches("test_data[128]")
99c00506aaSAlex Bennée
100c00506aaSAlex Bennée    report(cbp.hit_count == 0, "didn't reach backstop")
101c00506aaSAlex Bennée
102c00506aaSAlex Bennée#
103c00506aaSAlex Bennée# This runs as the script it sourced (via -x, via run-test.py)
104c00506aaSAlex Bennée#
105c00506aaSAlex Bennéetry:
106c00506aaSAlex Bennée    inferior = gdb.selected_inferior()
107c00506aaSAlex Bennée    arch = inferior.architecture()
108c00506aaSAlex Bennée    print("ATTACHED: %s" % arch.name())
109c00506aaSAlex Bennéeexcept (gdb.error, AttributeError):
110c00506aaSAlex Bennée    print("SKIPPING (not connected)", file=sys.stderr)
111c00506aaSAlex Bennée    exit(0)
112c00506aaSAlex Bennée
113c00506aaSAlex Bennéeif gdb.parse_and_eval('$pc') == 0:
114c00506aaSAlex Bennée    print("SKIP: PC not set")
115c00506aaSAlex Bennée    exit(0)
116c00506aaSAlex Bennée
117c00506aaSAlex Bennéetry:
118c00506aaSAlex Bennée    # Run the actual tests
119c00506aaSAlex Bennée    run_test()
120c00506aaSAlex Bennéeexcept (gdb.error):
121c00506aaSAlex Bennée    print("GDB Exception: %s" % (sys.exc_info()[0]))
122c00506aaSAlex Bennée    failcount += 1
123c00506aaSAlex Bennée    pass
124c00506aaSAlex Bennée
125c00506aaSAlex Bennée# Finally kill the inferior and exit gdb with a count of failures
126c00506aaSAlex Bennéegdb.execute("kill")
127c00506aaSAlex Bennéeexit(failcount)
128