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