You should declare you are using a global version of a variable before you attempt to modify it in a function. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20181109152119.9242-5-alex.bennee@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
		
			
				
	
	
		
			179 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			179 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from __future__ import print_function
 | |
| #
 | |
| # This script needs to be run on startup
 | |
| # qemu -kernel ${KERNEL} -s -S
 | |
| # and then:
 | |
| # gdb ${KERNEL}.vmlinux -x ${QEMU_SRC}/tests/guest-debug/test-gdbstub.py
 | |
| 
 | |
| import gdb
 | |
| 
 | |
| failcount = 0
 | |
| 
 | |
| 
 | |
| def report(cond, msg):
 | |
|     "Report success/fail of test"
 | |
|     if cond:
 | |
|         print ("PASS: %s" % (msg))
 | |
|     else:
 | |
|         print ("FAIL: %s" % (msg))
 | |
|         global failcount
 | |
|         failcount += 1
 | |
| 
 | |
| 
 | |
| def check_step():
 | |
|     "Step an instruction, check it moved."
 | |
|     start_pc = gdb.parse_and_eval('$pc')
 | |
|     gdb.execute("si")
 | |
|     end_pc = gdb.parse_and_eval('$pc')
 | |
| 
 | |
|     return not (start_pc == end_pc)
 | |
| 
 | |
| 
 | |
| def check_break(sym_name):
 | |
|     "Setup breakpoint, continue and check we stopped."
 | |
|     sym, ok = gdb.lookup_symbol(sym_name)
 | |
|     bp = gdb.Breakpoint(sym_name)
 | |
| 
 | |
|     gdb.execute("c")
 | |
| 
 | |
|     # hopefully we came back
 | |
|     end_pc = gdb.parse_and_eval('$pc')
 | |
|     print ("%s == %s %d" % (end_pc, sym.value(), bp.hit_count))
 | |
|     bp.delete()
 | |
| 
 | |
|     # can we test we hit bp?
 | |
|     return end_pc == sym.value()
 | |
| 
 | |
| 
 | |
| # We need to do hbreak manually as the python interface doesn't export it
 | |
| def check_hbreak(sym_name):
 | |
|     "Setup hardware breakpoint, continue and check we stopped."
 | |
|     sym, ok = gdb.lookup_symbol(sym_name)
 | |
|     gdb.execute("hbreak %s" % (sym_name))
 | |
|     gdb.execute("c")
 | |
| 
 | |
|     # hopefully we came back
 | |
|     end_pc = gdb.parse_and_eval('$pc')
 | |
|     print ("%s == %s" % (end_pc, sym.value()))
 | |
| 
 | |
|     if end_pc == sym.value():
 | |
|         gdb.execute("d 1")
 | |
|         return True
 | |
|     else:
 | |
|         return False
 | |
| 
 | |
| 
 | |
| class WatchPoint(gdb.Breakpoint):
 | |
| 
 | |
|     def get_wpstr(self, sym_name):
 | |
|         "Setup sym and wp_str for given symbol."
 | |
|         self.sym, ok = gdb.lookup_symbol(sym_name)
 | |
|         wp_addr = gdb.parse_and_eval(sym_name).address
 | |
|         self.wp_str = '*(%(type)s)(&%(address)s)' % dict(
 | |
|             type = wp_addr.type, address = sym_name)
 | |
| 
 | |
|         return(self.wp_str)
 | |
| 
 | |
|     def __init__(self, sym_name, type):
 | |
|         wp_str = self.get_wpstr(sym_name)
 | |
|         super(WatchPoint, self).__init__(wp_str, gdb.BP_WATCHPOINT, type)
 | |
| 
 | |
|     def stop(self):
 | |
|         end_pc = gdb.parse_and_eval('$pc')
 | |
|         print ("HIT WP @ %s" % (end_pc))
 | |
|         return True
 | |
| 
 | |
| 
 | |
| def do_one_watch(sym, wtype, text):
 | |
| 
 | |
|     wp = WatchPoint(sym, wtype)
 | |
|     gdb.execute("c")
 | |
|     report_str = "%s for %s (%s)" % (text, sym, wp.sym.value())
 | |
| 
 | |
|     if wp.hit_count > 0:
 | |
|         report(True, report_str)
 | |
|         wp.delete()
 | |
|     else:
 | |
|         report(False, report_str)
 | |
| 
 | |
| 
 | |
| def check_watches(sym_name):
 | |
|     "Watch a symbol for any access."
 | |
| 
 | |
|     # Should hit for any read
 | |
|     do_one_watch(sym_name, gdb.WP_ACCESS, "awatch")
 | |
| 
 | |
|     # Again should hit for reads
 | |
|     do_one_watch(sym_name, gdb.WP_READ, "rwatch")
 | |
| 
 | |
|     # Finally when it is written
 | |
|     do_one_watch(sym_name, gdb.WP_WRITE, "watch")
 | |
| 
 | |
| 
 | |
| class CatchBreakpoint(gdb.Breakpoint):
 | |
|     def __init__(self, sym_name):
 | |
|         super(CatchBreakpoint, self).__init__(sym_name)
 | |
|         self.sym, ok = gdb.lookup_symbol(sym_name)
 | |
| 
 | |
|     def stop(self):
 | |
|         end_pc = gdb.parse_and_eval('$pc')
 | |
|         print ("CB: %s == %s" % (end_pc, self.sym.value()))
 | |
|         if end_pc == self.sym.value():
 | |
|             report(False, "Hit final catchpoint")
 | |
| 
 | |
| 
 | |
| def run_test():
 | |
|     "Run through the tests one by one"
 | |
| 
 | |
|     print ("Checking we can step the first few instructions")
 | |
|     step_ok = 0
 | |
|     for i in range(3):
 | |
|         if check_step():
 | |
|             step_ok += 1
 | |
| 
 | |
|     report(step_ok == 3, "single step in boot code")
 | |
| 
 | |
|     print ("Checking HW breakpoint works")
 | |
|     break_ok = check_hbreak("kernel_init")
 | |
|     report(break_ok, "hbreak @ kernel_init")
 | |
| 
 | |
|     # Can't set this up until we are in the kernel proper
 | |
|     # if we make it to run_init_process we've over-run and
 | |
|     # one of the tests failed
 | |
|     print ("Setup catch-all for run_init_process")
 | |
|     cbp = CatchBreakpoint("run_init_process")
 | |
|     cpb2 = CatchBreakpoint("try_to_run_init_process")
 | |
| 
 | |
|     print ("Checking Normal breakpoint works")
 | |
|     break_ok = check_break("wait_for_completion")
 | |
|     report(break_ok, "break @ wait_for_completion")
 | |
| 
 | |
|     print ("Checking watchpoint works")
 | |
|     check_watches("system_state")
 | |
| 
 | |
| #
 | |
| # This runs as the script it sourced (via -x)
 | |
| #
 | |
| 
 | |
| try:
 | |
|     print ("Connecting to remote")
 | |
|     gdb.execute("target remote localhost:1234")
 | |
| 
 | |
|     # These are not very useful in scripts
 | |
|     gdb.execute("set pagination off")
 | |
|     gdb.execute("set confirm off")
 | |
| 
 | |
|     # Run the actual tests
 | |
|     run_test()
 | |
| 
 | |
| except:
 | |
|     print ("GDB Exception: %s" % (sys.exc_info()[0]))
 | |
|     failcount += 1
 | |
|     import code
 | |
|     code.InteractiveConsole(locals=globals()).interact()
 | |
|     raise
 | |
| 
 | |
| # Finally kill the inferior and exit gdb with a count of failures
 | |
| gdb.execute("kill")
 | |
| exit(failcount)
 |