qemu

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

test-gdbstub.py (4609B)


      1 #
      2 # This script needs to be run on startup
      3 # qemu -kernel ${KERNEL} -s -S
      4 # and then:
      5 # gdb ${KERNEL}.vmlinux -x ${QEMU_SRC}/tests/guest-debug/test-gdbstub.py
      6 
      7 import gdb
      8 
      9 failcount = 0
     10 
     11 
     12 def report(cond, msg):
     13     "Report success/fail of test"
     14     if cond:
     15         print ("PASS: %s" % (msg))
     16     else:
     17         print ("FAIL: %s" % (msg))
     18         global failcount
     19         failcount += 1
     20 
     21 
     22 def check_step():
     23     "Step an instruction, check it moved."
     24     start_pc = gdb.parse_and_eval('$pc')
     25     gdb.execute("si")
     26     end_pc = gdb.parse_and_eval('$pc')
     27 
     28     return not (start_pc == end_pc)
     29 
     30 
     31 def check_break(sym_name):
     32     "Setup breakpoint, continue and check we stopped."
     33     sym, ok = gdb.lookup_symbol(sym_name)
     34     bp = gdb.Breakpoint(sym_name)
     35 
     36     gdb.execute("c")
     37 
     38     # hopefully we came back
     39     end_pc = gdb.parse_and_eval('$pc')
     40     print ("%s == %s %d" % (end_pc, sym.value(), bp.hit_count))
     41     bp.delete()
     42 
     43     # can we test we hit bp?
     44     return end_pc == sym.value()
     45 
     46 
     47 # We need to do hbreak manually as the python interface doesn't export it
     48 def check_hbreak(sym_name):
     49     "Setup hardware breakpoint, continue and check we stopped."
     50     sym, ok = gdb.lookup_symbol(sym_name)
     51     gdb.execute("hbreak %s" % (sym_name))
     52     gdb.execute("c")
     53 
     54     # hopefully we came back
     55     end_pc = gdb.parse_and_eval('$pc')
     56     print ("%s == %s" % (end_pc, sym.value()))
     57 
     58     if end_pc == sym.value():
     59         gdb.execute("d 1")
     60         return True
     61     else:
     62         return False
     63 
     64 
     65 class WatchPoint(gdb.Breakpoint):
     66 
     67     def get_wpstr(self, sym_name):
     68         "Setup sym and wp_str for given symbol."
     69         self.sym, ok = gdb.lookup_symbol(sym_name)
     70         wp_addr = gdb.parse_and_eval(sym_name).address
     71         self.wp_str = '*(%(type)s)(&%(address)s)' % dict(
     72             type = wp_addr.type, address = sym_name)
     73 
     74         return(self.wp_str)
     75 
     76     def __init__(self, sym_name, type):
     77         wp_str = self.get_wpstr(sym_name)
     78         super(WatchPoint, self).__init__(wp_str, gdb.BP_WATCHPOINT, type)
     79 
     80     def stop(self):
     81         end_pc = gdb.parse_and_eval('$pc')
     82         print ("HIT WP @ %s" % (end_pc))
     83         return True
     84 
     85 
     86 def do_one_watch(sym, wtype, text):
     87 
     88     wp = WatchPoint(sym, wtype)
     89     gdb.execute("c")
     90     report_str = "%s for %s (%s)" % (text, sym, wp.sym.value())
     91 
     92     if wp.hit_count > 0:
     93         report(True, report_str)
     94         wp.delete()
     95     else:
     96         report(False, report_str)
     97 
     98 
     99 def check_watches(sym_name):
    100     "Watch a symbol for any access."
    101 
    102     # Should hit for any read
    103     do_one_watch(sym_name, gdb.WP_ACCESS, "awatch")
    104 
    105     # Again should hit for reads
    106     do_one_watch(sym_name, gdb.WP_READ, "rwatch")
    107 
    108     # Finally when it is written
    109     do_one_watch(sym_name, gdb.WP_WRITE, "watch")
    110 
    111 
    112 class CatchBreakpoint(gdb.Breakpoint):
    113     def __init__(self, sym_name):
    114         super(CatchBreakpoint, self).__init__(sym_name)
    115         self.sym, ok = gdb.lookup_symbol(sym_name)
    116 
    117     def stop(self):
    118         end_pc = gdb.parse_and_eval('$pc')
    119         print ("CB: %s == %s" % (end_pc, self.sym.value()))
    120         if end_pc == self.sym.value():
    121             report(False, "Hit final catchpoint")
    122 
    123 
    124 def run_test():
    125     "Run through the tests one by one"
    126 
    127     print ("Checking we can step the first few instructions")
    128     step_ok = 0
    129     for i in range(3):
    130         if check_step():
    131             step_ok += 1
    132 
    133     report(step_ok == 3, "single step in boot code")
    134 
    135     print ("Checking HW breakpoint works")
    136     break_ok = check_hbreak("kernel_init")
    137     report(break_ok, "hbreak @ kernel_init")
    138 
    139     # Can't set this up until we are in the kernel proper
    140     # if we make it to run_init_process we've over-run and
    141     # one of the tests failed
    142     print ("Setup catch-all for run_init_process")
    143     cbp = CatchBreakpoint("run_init_process")
    144     cpb2 = CatchBreakpoint("try_to_run_init_process")
    145 
    146     print ("Checking Normal breakpoint works")
    147     break_ok = check_break("wait_for_completion")
    148     report(break_ok, "break @ wait_for_completion")
    149 
    150     print ("Checking watchpoint works")
    151     check_watches("system_state")
    152 
    153 #
    154 # This runs as the script it sourced (via -x)
    155 #
    156 
    157 try:
    158     print ("Connecting to remote")
    159     gdb.execute("target remote localhost:1234")
    160 
    161     # These are not very useful in scripts
    162     gdb.execute("set pagination off")
    163     gdb.execute("set confirm off")
    164 
    165     # Run the actual tests
    166     run_test()
    167 
    168 except:
    169     print ("GDB Exception: %s" % (sys.exc_info()[0]))
    170     failcount += 1
    171     import code
    172     code.InteractiveConsole(locals=globals()).interact()
    173     raise
    174 
    175 # Finally kill the inferior and exit gdb with a count of failures
    176 gdb.execute("kill")
    177 exit(failcount)