blob: ef667268d2c5ddc9527731171b6a7d38fe1edb15 [file] [log] [blame]
import pexpect, re, signal, sys, time
__all__ = [ 'expect_gdb', 'send_gdb','expect_rr', 'expect_list',
'restart_replay', 'interrupt_gdb', 'ok',
'failed', 'iterlines_both', 'last_match', 'get_exe_arch',
'get_gdb_version' ]
# Public API
def expect_gdb(what):
expect(gdb_rr, what)
def expect_list(pats):
return gdb_rr.expect_list(pats)
def expect_rr(what):
expect(gdb_rr, what)
def failed(why, e=None):
print('FAILED:', why)
if e:
print('exception:', e)
clean_up()
sys.exit(1)
def interrupt_gdb():
try:
gdb_rr.kill(signal.SIGINT)
except Exception as e:
failed('interrupting gdb', e)
expect_gdb('stopped.')
def iterlines_both():
return gdb_rr
def last_match():
return gdb_rr.match
# Restarts and continues execution
def restart_replay(event=0):
if event:
send_gdb('r %d'%(event))
else:
send_gdb('r')
# gdb may not prompt here. It's ok to send an unnecessary 'y'
# since there is no such command.
send_gdb('y')
# Wait to see 'stopped'. We don't want this to get buffered up
# so callers expecting a 'stopped' *after* replay has resumed
# get confused.
expect_rr('stopped')
send_gdb('c')
def send_gdb(what):
send(gdb_rr, "%s\n"%what)
def ok():
send_gdb('q')
send_gdb('y')
clean_up()
# Internal helpers
# Don't use python timeout. Use test-monitor timeout instead.
TIMEOUT_SEC = 10000
# gdb and rr are part of the same process tree, so they share
# stdin/stdout.
gdb_rr = None
def clean_up():
global gdb_rr
iterations = 0
while gdb_rr:
try:
# FIXME: without this sleep python freezes instead of exiting.
# The sleep has to be before BufferedRWPair.close()
time.sleep(0.1)
gdb_rr.close(force=1)
gdb_rr = None
except Exception as e:
if iterations < 5:
print("close() failed with '%s', retrying..."%e)
iterations = iterations + 1
else:
gdb_rr = None
def expect(prog, what):
try:
prog.expect(what)
except Exception as e:
failed('expecting "%s"'% (what), e)
def get_exe_arch():
send_gdb('show architecture')
expect_gdb(r'The target architecture is set (automatically|to "auto") \(currently "?([0-9a-z:-]+)"?\)\.?')
global gdb_rr
return gdb_rr.match.group(2)
def get_rr_cmd():
'''Return the command that should be used to invoke rr, as the tuple
(executable, array-of-args)'''
rrargs = sys.argv[1:]
return (rrargs[0], rrargs[1:])
def get_gdb_version():
'''Return the gdb version'''
send_gdb('python print(gdb.VERSION)')
expect_gdb(r'(\d+.\d+)')
global gdb_rr
return float(gdb_rr.match.group(1))
def send(prog, what):
try:
prog.send(what)
except Exception as e:
failed('sending "%s"'% (what), e)
def set_up():
global gdb_rr
try:
gdb_rr = pexpect.spawn(*get_rr_cmd(), codec_errors='ignore', timeout=TIMEOUT_SEC, encoding='utf-8', logfile=open('gdb_rr.log', 'w'))
gdb_rr.delaybeforesend = 0
expect_gdb('\(rr\)')
except Exception as e:
failed('initializing rr and gdb', e)
set_up()