Debugger: Somewhat more robust LLDB output parsing

Change-Id: Ia54d99df15240db4c56fe0ba6b6282319056f59f
Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
hjk
2013-04-03 15:08:35 +02:00
parent 3eb7c99f1e
commit df674a2add
2 changed files with 60 additions and 15 deletions

View File

@@ -78,6 +78,23 @@
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
static QByteArray quoteUnprintable(const QByteArray &ba)
{
QByteArray res;
char buf[10];
for (int i = 0, n = ba.size(); i != n; ++i) {
const unsigned char c = ba.at(i);
if (isprint(c)) {
res += c;
} else {
qsnprintf(buf, sizeof(buf) - 1, "\\%02x", int(c));
res += buf;
}
}
return res;
}
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////
// //
// LldbEngine // LldbEngine
@@ -124,14 +141,17 @@ void LldbEngine::postCommand(const QByteArray &command,
const char *callbackName, const char *callbackName,
const QVariant &cookie) const QVariant &cookie)
{ {
static int token = 0;
++token;
QTC_ASSERT(m_lldbProc.state() == QProcess::Running, notifyEngineIll()); QTC_ASSERT(m_lldbProc.state() == QProcess::Running, notifyEngineIll());
LldbCommand cmd; LldbCommand cmd;
cmd.command = command; cmd.command = command;
cmd.callback = callback; cmd.callback = callback;
cmd.callbackName = callbackName; cmd.callbackName = callbackName;
cmd.cookie = cookie; cmd.cookie = cookie;
cmd.token = token;
m_commands.enqueue(cmd); m_commands.enqueue(cmd);
showMessage(_(cmd.command), LogInput); showMessage(QString::number(token) + _(cmd.command), LogInput);
m_lldbProc.write(cmd.command + '\n'); m_lldbProc.write(cmd.command + '\n');
} }
@@ -600,28 +620,56 @@ void LldbEngine::readLldbStandardError()
//handleOutput(err); //handleOutput(err);
} }
static bool isEatable(char c)
{
return c == 10 || c == 13;
}
void LldbEngine::readLldbStandardOutput() void LldbEngine::readLldbStandardOutput()
{ {
QByteArray out = m_lldbProc.readAllStandardOutput(); QByteArray out = m_lldbProc.readAllStandardOutput();
showMessage(_("Lldb stdout: " + out)); showMessage(_("Lldb stdout: " + out));
qDebug() << "\nLLDB STDOUT" << out; qDebug("\nLLDB RAW STDOUT: '%s'", quoteUnprintable(out).constData());
handleOutput(out); // Remove embedded backspace characters
} int j = 1;
const int n = out.size();
for (int i = 1; i < n; ++i, ++j) {
const char c = out.at(i);
if (i != j)
out[j] = c;
if (c == 8)
j -= 2;
else if (isEatable(c))
--j;
}
if (j != n)
out.resize(j);
//qDebug("\n\nLLDB STDOUT: '%s'", quoteUnprintable(out).constData());
if (out.isEmpty())
return;
void LldbEngine::handleOutput(const QByteArray &data)
{
//qDebug() << "READ: " << data; //qDebug() << "READ: " << data;
m_inbuffer.append(data); if (out.startsWith(8)) {
qDebug() << "BUFFER FROM: '" << m_inbuffer << '\''; if (!m_inbuffer.isEmpty())
m_inbuffer.chop(1);
m_inbuffer.append(out.mid(1));
} else if (isEatable(out.at(0))) {
m_inbuffer.append(out.mid(1));
} else {
m_inbuffer.append(out);
}
qDebug("\nBUFFER FROM: '%s'", quoteUnprintable(m_inbuffer).constData());
while (true) { while (true) {
int pos = m_inbuffer.indexOf("(lldb)"); int pos = m_inbuffer.indexOf("(lldb)");
if (pos == -1) if (pos == -1)
break; break;
QByteArray response = m_inbuffer.left(pos).trimmed(); QByteArray response = m_inbuffer.left(pos).trimmed();
m_inbuffer = m_inbuffer.mid(pos + 6); m_inbuffer = m_inbuffer.mid(pos + 6);
qDebug("\nBUFFER RECOGNIZED: '%s'", quoteUnprintable(response).constData());
emit outputReady(response); emit outputReady(response);
} }
qDebug() << "BUFFER LEFT: '" << m_inbuffer << '\''; qDebug("\nBUFFER LEFT: '%s'", quoteUnprintable(m_inbuffer).constData());
//m_inbuffer.clear(); //m_inbuffer.clear();
} }
@@ -633,7 +681,7 @@ void LldbEngine::handleOutput2(const QByteArray &data)
QTC_ASSERT(!m_commands.isEmpty(), qDebug() << "RESPONSE: " << data; return); QTC_ASSERT(!m_commands.isEmpty(), qDebug() << "RESPONSE: " << data; return);
LldbCommand cmd = m_commands.dequeue(); LldbCommand cmd = m_commands.dequeue();
response.cookie = cmd.cookie; response.cookie = cmd.cookie;
qDebug() << "DEQUE: " << cmd.command << cmd.callbackName; qDebug("\nDEQUE: '%s' -> '%s'", cmd.command.constData(), cmd.callbackName);
if (cmd.callback) { if (cmd.callback) {
//qDebug() << "EXECUTING CALLBACK " << cmd.callbackName //qDebug() << "EXECUTING CALLBACK " << cmd.callbackName
// << " RESPONSE: " << response.data; // << " RESPONSE: " << response.data;

View File

@@ -121,7 +121,6 @@ private:
Q_SLOT void readLldbStandardError(); Q_SLOT void readLldbStandardError();
Q_SLOT void handleOutput2(const QByteArray &data); Q_SLOT void handleOutput2(const QByteArray &data);
void handleResponse(const QByteArray &ba); void handleResponse(const QByteArray &ba);
void handleOutput(const QByteArray &data);
void updateAll(); void updateAll();
void updateLocals(); void updateLocals();
void handleUpdateAll(const LldbResponse &response); void handleUpdateAll(const LldbResponse &response);
@@ -137,15 +136,13 @@ private:
struct LldbCommand struct LldbCommand
{ {
LldbCommand() LldbCommand() : callback(0), callbackName(0), token(0) {}
: callback(0), callbackName(0)
{}
LldbCommandCallback callback; LldbCommandCallback callback;
const char *callbackName; const char *callbackName;
QByteArray command; QByteArray command;
QVariant cookie; QVariant cookie;
//QTime postTime; int token;
}; };
void handleStop(const LldbResponse &response); void handleStop(const LldbResponse &response);