debugger: add possibility to fake response packets to trigger error handling

Change-Id: Ieeb0daef594024b72e52c1180047835193e9341d
Reviewed-on: http://codereview.qt.nokia.com/340
Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
hjk
2011-06-06 18:17:51 +02:00
committed by hjk
parent 1ce1205666
commit 82272d9c22
2 changed files with 72 additions and 39 deletions

View File

@@ -338,17 +338,6 @@ void GdbEngine::handleResponse(const QByteArray &buff)
{
showMessage(QString::fromLocal8Bit(buff, buff.length()), LogOutput);
#if 0
static QTime lastTime;
qDebug() // << "#### start response handling #### "
<< lastTime.msecsTo(QTime::currentTime()) << "ms,"
<< "buf:" << buff.left(1500) << "..."
//<< "buf:" << buff
<< "size:" << buff.size();
lastTime = QTime::currentTime();
#else
//qDebug() << "buf:" << buff;
#endif
if (buff.isEmpty() || buff == "(gdb) ")
return;
@@ -357,19 +346,17 @@ void GdbEngine::handleResponse(const QByteArray &buff)
const char *inner;
int token = -1;
// token is a sequence of numbers
// Token is a sequence of numbers.
for (inner = from; inner != to; ++inner)
if (*inner < '0' || *inner > '9')
break;
if (from != inner) {
token = QByteArray(from, inner - from).toInt();
from = inner;
//qDebug() << "found token" << token;
}
// next char decides kind of response
// Next char decides kind of response.
const char c = *from++;
//qDebug() << "CODE:" << c;
switch (c) {
case '*':
case '+':
@@ -381,7 +368,6 @@ void GdbEngine::handleResponse(const QByteArray &buff)
break;
asyncClass += *from;
}
//qDebug() << "ASYNCCLASS" << asyncClass;
GdbMi result;
while (from != to) {
@@ -820,29 +806,41 @@ void GdbEngine::flushCommand(const GdbCommand &cmd0)
QTC_ASSERT(gdbProc()->state() == QProcess::Running, return;)
++currentToken();
const int token = ++currentToken();
GdbCommand cmd = cmd0;
cmd.postTime = QTime::currentTime();
m_cookieForToken[currentToken()] = cmd;
m_cookieForToken[token] = cmd;
if (cmd.flags & ConsoleCommand)
cmd.command = "-interpreter-exec console \"" + cmd.command + '"';
cmd.command = QByteArray::number(currentToken()) + cmd.command;
cmd.command = QByteArray::number(token) + cmd.command;
showMessage(_(cmd.command), LogInput);
m_gdbAdapter->write(cmd.command + "\r\n");
if (m_scheduledTestResponses.contains(token)) {
// Fake response for test cases.
QByteArray buffer = m_scheduledTestResponses.value(token);
buffer.replace("@TOKEN@", QByteArray::number(token));
m_scheduledTestResponses.remove(token);
showMessage(_("FAKING TEST RESPONSE (TOKEN: %2, RESPONSE: '%3')")
.arg(token).arg(_(buffer)));
QMetaObject::invokeMethod(this, "handleResponse",
Q_ARG(QByteArray, buffer));
} else {
m_gdbAdapter->write(cmd.command + "\r\n");
// Start Watchdog.
if (m_commandTimer.interval() <= 20000)
m_commandTimer.setInterval(commandTimeoutTime());
// The process can die for external reason between the "-gdb-exit" was
// sent and a response could be retrieved. We don't want the watchdog
// to bark in that case since the only possible outcome is a dead
// process anyway.
if (!cmd.command.endsWith("-gdb-exit"))
m_commandTimer.start();
// Start Watchdog.
if (m_commandTimer.interval() <= 20000)
m_commandTimer.setInterval(commandTimeoutTime());
// The process can die for external reason between the "-gdb-exit" was
// sent and a response could be retrieved. We don't want the watchdog
// to bark in that case since the only possible outcome is a dead
// process anyway.
if (!cmd.command.endsWith("-gdb-exit"))
m_commandTimer.start();
//if (cmd.flags & LosesChild)
// notifyInferiorIll();
//if (cmd.flags & LosesChild)
// notifyInferiorIll();
}
}
int GdbEngine::commandTimeoutTime() const
@@ -894,9 +892,9 @@ void GdbEngine::commandTimeout()
void GdbEngine::handleResultRecord(GdbResponse *response)
{
//qDebug() << "TOKEN:" << response.token
//qDebug() << "TOKEN:" << response->token
// << " ACCEPTABLE:" << m_oldestAcceptableToken;
//qDebug() << "\nRESULT" << response.token << response.toString();
//qDebug() << "\nRESULT" << response->token << response->toString();
int token = response->token;
if (token == -1)
@@ -1984,10 +1982,11 @@ void GdbEngine::executeStep()
showStatusMessage(tr("Step requested..."), 5000);
if (m_gdbAdapter->isTrkAdapter() && stackHandler()->stackSize() > 0)
postCommand("sal step,0x" + QByteArray::number(stackHandler()->topAddress(), 16));
if (isReverseDebugging())
if (isReverseDebugging()) {
postCommand("reverse-step", RunRequest, CB(handleExecuteStep));
else
} else {
postCommand("-exec-step", RunRequest, CB(handleExecuteStep));
}
}
void GdbEngine::handleExecuteStep(const GdbResponse &response)
@@ -2050,10 +2049,14 @@ void GdbEngine::executeNext()
showStatusMessage(tr("Step next requested..."), 5000);
if (m_gdbAdapter->isTrkAdapter() && stackHandler()->stackSize() > 0)
postCommand("sal next,0x" + QByteArray::number(stackHandler()->topAddress(), 16));
if (isReverseDebugging())
if (isReverseDebugging()) {
postCommand("reverse-next", RunRequest, CB(handleExecuteNext));
else
} else {
scheduleTestResponse(GdbTestNoBoundsOfCurrentFunction,
"@TOKEN@^error,msg=\"Warning:\\nCannot insert breakpoint -39.\\n"
" Error accessing memory address 0x11673fc: Input/output error.\\n\"");
postCommand("-exec-next", RunRequest, CB(handleExecuteNext));
}
}
void GdbEngine::handleExecuteNext(const GdbResponse &response)
@@ -2071,7 +2074,8 @@ void GdbEngine::handleExecuteNext(const GdbResponse &response)
}
QTC_ASSERT(state() == InferiorStopOk, qDebug() << state());
QByteArray msg = response.data.findChild("msg").data();
if (msg.startsWith("Cannot find bounds of current function")) {
if (msg.startsWith("Cannot find bounds of current function")
|| msg.contains("Error accessing memory address ")) {
if (!m_commandsToRunOnTemporaryBreak.isEmpty())
flushQueuedCommands();
notifyInferiorRunFailed();
@@ -4383,6 +4387,12 @@ bool checkGdbConfiguration(const DebuggerStartParameters &sp, ConfigurationCheck
bool GdbEngine::startGdb(const QStringList &args, const QString &settingsIdHint)
{
const QByteArray tests = qgetenv("QTC_DEBUGGER_TESTS");
foreach (const QByteArray &test, tests.split(','))
m_testCases.insert(test.toInt());
foreach (int test, m_testCases)
showMessage(_("ENABLING TEST CASE: " + QByteArray::number(test)));
gdbProc()->disconnect(); // From any previous runs
const DebuggerStartParameters &sp = startParameters();
@@ -4895,6 +4905,18 @@ bool GdbEngine::isQFatalBreakpoint(int bpnr) const
return bpnr && m_qFatalBreakpointNumber == bpnr;
}
void GdbEngine::scheduleTestResponse(int testCase, const QByteArray &response)
{
if (!m_testCases.contains(testCase))
return;
int token = currentToken() + 1;
showMessage(_("SCHEDULING TEST RESPONSE (CASE: %1, TOKEN: %2, RESPONSE: '%3')")
.arg(testCase).arg(token).arg(_(response)));
m_scheduledTestResponses[token] = response;
}
//
// Factory
//