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