Fix for Bug 3671 - QEMU GDB stub listens on IPv6-only port on Windows 7
The connection string used by the GDB stub does not specify which
version of the Internet Protocol should be used by the port on
which it listens. On host platforms with IPv6 support, such as
Windows 7, this means that the stub listens on an IPv6-only port.
Since the GDB client uses IPv4, this means that the client cannot
connect to QEMU.
#
# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
# All rights reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Launch QEMU for SVP with a specified ROM image and core using a COM port for IO
# Uses Python's Popen class for process control.
# Test output is captured by invoking QEMU in -nographic mode. This redirects serial output to stdout which can then be PIPE'd
# using Popen.
# Tests which hang(or crash into the the crash debugger) are detected using a trivial 'watchdog'. IWBN to use e.g. 'select'
# with a timeout, but this won't work on Windoze, which only supports timeout's on sockets. If the watchdog timeouts out QEMU is killed.
# When the test suite runs to (recognizable) completion QEMU is killed. Unfortunately this appears to require an OS specific
# solution. NB unrecognized completion will result in the watchdog killing QEMU.
# QemuTestRunner collects output into LineTimeInfo objects. These record the time at which each line was received. The time can be used as a crude
# measure of how long a test took to execute.
# The raw data gathered from running the tests can be retrieved using GetResults. This returns a list of LineTimeInfo objects.
import sys
mswindows = (sys.platform == "win32")
# import the following so we can kill QEMU
if mswindows:
# import win32api
import signal
else:
import signal
import os
import time
import re
import subprocess
from subprocess import *
from stat import *
import watchdog
__all__ = ["QemuTestRunner"]
class LineTimeInfo(object):
def __init__(self, line, atime):
self.line = line
self.time = atime
def GetLine(self):
return self.line
def GetTime(self):
return self.time
class QemuTestRunner(object):
def __init__(self, qemupath, cpu, rompath, board = 'syborg', endOfTestFn=None, displayp=False, dataFile = None):
"""Create new QemuTestRunner instance."""
self.qemupath = qemupath
self.board = board
self.cpu = cpu
self.rompath = rompath
self.endOfTestFn = endOfTestFn
self.displayp = displayp
#self.cmd = qemupath + " -M syborg -cpu " + cpu + " -kernel " + rompath + " -nographic"
self.cmd = "%s -M %s -cpu %s -kernel %s -nographic" % (qemupath, board, cpu, rompath)
self.endOfTestPattern = re.compile('RUNTESTS: Completed test script')
self.lineTimeInfo = []
self.id = None
self.dataFile = dataFile
self.watchdog = watchdog.WatchDog(900, lambda : self.KillSim())
def Run(self):
self.lineTimeInfo = []
output = False
self.timeStarted = time.gmtime()
self.id = time.strftime("%d-%m%--%Y-%H-%M-%S", self.timeStarted)
if self.dataFile != None:
filename = self.dataFile + "-" + self.GetRunId() + "-data.txt"
self.dataFileName = filename
output = open(filename, 'wb')
p = Popen( self.cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE )
self.popen = p
stdin = p.stdin
stdout = p.stdout
stop = False
if self.displayp:
print >> sys.stdout, self.cmd
self.watchdog.Start()
try:
while p.poll() == None and not stop:
line = stdout.readline()
atime = time.clock()
self.watchdog.Reset()
if self.displayp and p.returncode == None:
print >> sys.stdout , line
if output and p.returncode == None:
print >> output , line
if p.returncode == None:
self.lineTimeInfo.append(LineTimeInfo(line, atime))
if self.endOfTestFn != None:
stop = self.endOfTestFn(line)
else:
stop = self.EndOfTestp(line)
finally:
self.timeEnded = time.gmtime()
self.watchdog.Stop()
if output:
output.close()
self.testSuiteFinished = stop;
if p.returncode == None:
self.KillSim()
return True
else:
return False
def GetDataFileName(self):
return self.dataFileName
def TestSuiteFinishedp(self):
return self.testSuiteFinished
def EndOfTestp(self, l):
return re.match(self.endOfTestPattern,l) != None
def KillSim(self):
# if mswindows:
# win32api.TerminateProcess(int(self.popen._handle), -1)
# else:
os.kill(slef.popen.pid, signal.SIGKILL)
def GetResults(self):
return self.lineTimeInfo
def GetRomName(self):
return self.rompath
def GetRunId(self):
return self.id
def GetSummary(self):
simStat = os.stat(self.qemupath)
simSummary = "QEMU Executable: %s size: %d creation time: %d\n" % (self.qemupath, simStat[ST_SIZE], simStat[ST_CTIME])
boardSummary ="Board: %s\n" % self.board
cpuSummary = "CPU: %s\n" % self.cpu
romStat = os.stat(self.rompath)
romSummary = "ROM image: %s size: %d creation date: %d\n" % (self.rompath, romStat[ST_SIZE], romStat[ST_CTIME])
timeFormat = "%d-%m%--%Y %H:%M:%S"
startTime = "Start time: " + time.strftime(timeFormat, self.timeStarted) + "\n"
endTime = "End time: " + time.strftime(timeFormat, self.timeEnded) + "\n"
status = "Testsuite did not complete\n"
if self.TestSuiteFinishedp():
status = "Testsuite completed\n"
return simSummary + boardSummary + cpuSummary + romSummary + startTime + endTime + status
def GetReportFileName(self):
return self.GetRomName() + "-" + self.GetRunId() + "-results-summary.txt"
class PseudoRunner(QemuTestRunner):
def __init__(self, input):
#self.qemupath = qemupath
#self.board = board
#self.cpu = cpu
#self.rompath = rompath
#self.endOfTestFn = endOfTestFn
#self.displayp = displayp
#self.cmd = qemupath + " -M syborg -cpu " + cpu + " -kernel " + rompath + " -nographic"
#self.endOfTestPattern = re.compile('RUNTESTS: Completed test script')
self.lineTimeInfo = []
#self.id = None
self.dataFile = input
for line in open(input):
self.lineTimeInfo.append(LineTimeInfo(line, 0))
def GetRomName(self):
return "Unknown"
def GetRunId(self):
return None
def GetSummary(self):
return ""
def GetReportFileName(self):
return "Runtest-Summary.txt"