qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

memory.py (3204B)


      1 from __future__ import print_function
      2 #
      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.
      6 #
      7 # This is launched via tests/guest-debug/run-test.py
      8 #
      9 
     10 import gdb
     11 import sys
     12 
     13 failcount = 0
     14 
     15 
     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
     24 
     25 
     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')
     31 
     32     return not (start_pc == end_pc)
     33 
     34 
     35 #
     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.
     40 #
     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)
     45 
     46     gdb.execute("c")
     47 
     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))
     52 
     53     bp.delete()
     54 
     55 
     56 def do_one_watch(sym, wtype, text):
     57 
     58     wp = gdb.Breakpoint(sym, gdb.BP_WATCHPOINT, wtype)
     59     gdb.execute("c")
     60     report_str = "%s for %s" % (text, sym)
     61 
     62     if wp.hit_count > 0:
     63         report(True, report_str)
     64         wp.delete()
     65     else:
     66         report(False, report_str)
     67 
     68 
     69 def check_watches(sym_name):
     70     "Watch a symbol for any access."
     71 
     72     # Should hit for any read
     73     do_one_watch(sym_name, gdb.WP_ACCESS, "awatch")
     74 
     75     # Again should hit for reads
     76     do_one_watch(sym_name, gdb.WP_READ, "rwatch")
     77 
     78     # Finally when it is written
     79     do_one_watch(sym_name, gdb.WP_WRITE, "watch")
     80 
     81 
     82 def run_test():
     83     "Run through the tests one by one"
     84 
     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
     90 
     91     report(step_ok == 3, "single step in boot code")
     92 
     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)
     96 
     97     check_break("main")
     98     check_watches("test_data[128]")
     99 
    100     report(cbp.hit_count == 0, "didn't reach backstop")
    101 
    102 #
    103 # This runs as the script it sourced (via -x, via run-test.py)
    104 #
    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)
    112 
    113 if gdb.parse_and_eval('$pc') == 0:
    114     print("SKIP: PC not set")
    115     exit(0)
    116 
    117 try:
    118     # These are not very useful in scripts
    119     gdb.execute("set pagination off")
    120 
    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
    127 
    128 # Finally kill the inferior and exit gdb with a count of failures
    129 gdb.execute("kill")
    130 exit(failcount)