Debugger[TCF]: Parse \u-escapes in JSON correctly, report verbose

crash messages.
This commit is contained in:
Friedemann Kleint
2010-09-27 16:10:14 +02:00
parent e871b7e330
commit 83e1fcfd99
4 changed files with 41 additions and 8 deletions

View File

@@ -315,8 +315,9 @@ void TcfTrkGdbAdapter::tcftrkEvent(const TcfTrkEvent &e)
static_cast<const TcfTrkRunControlContextSuspendedEvent &>(e); static_cast<const TcfTrkRunControlContextSuspendedEvent &>(e);
const unsigned threadId = RunControlContext::threadIdFromTcdfId(se.id()); const unsigned threadId = RunControlContext::threadIdFromTcdfId(se.id());
const QString reason = QString::fromUtf8(se.reasonID()); const QString reason = QString::fromUtf8(se.reasonID());
showMessage(_("Reset snapshot (Thread 0x%1 stopped: '%2')"). const QString message = QString::fromUtf8(se.message()).replace(QLatin1String("\n"), QLatin1String(", "));
arg(threadId, 0, 16).arg(reason)); showMessage(_("Thread %1 stopped: '%2': %3").
arg(threadId).arg(reason, message), LogMisc);
// Stopped in a new thread: Add. // Stopped in a new thread: Add.
m_snapshot.reset(); m_snapshot.reset();
m_session.tid = threadId; m_session.tid = threadId;
@@ -1037,6 +1038,7 @@ void TcfTrkGdbAdapter::setupInferior()
void TcfTrkGdbAdapter::addThread(unsigned id) void TcfTrkGdbAdapter::addThread(unsigned id)
{ {
showMessage(QString::fromLatin1("Thread %1 reported").arg(id), LogMisc);
// Make thread known, register as main if it is the first one. // Make thread known, register as main if it is the first one.
if (m_snapshot.indexOfThread(id) == -1) { if (m_snapshot.indexOfThread(id) == -1) {
m_snapshot.addThread(id); m_snapshot.addThread(id);

View File

@@ -88,6 +88,7 @@ QByteArray JsonValue::parseNumber(const char *&from, const char *to)
QByteArray JsonValue::parseCString(const char *&from, const char *to) QByteArray JsonValue::parseCString(const char *&from, const char *to)
{ {
QByteArray result; QByteArray result;
const char * const fromSaved = from;
JDEBUG("parseCString: " << QByteArray(from, to - from)); JDEBUG("parseCString: " << QByteArray(from, to - from));
if (*from != '"') { if (*from != '"') {
qDebug() << "JSON Parse Error, double quote expected"; qDebug() << "JSON Parse Error, double quote expected";
@@ -105,7 +106,8 @@ QByteArray JsonValue::parseCString(const char *&from, const char *to)
if (*ptr == '\\') { if (*ptr == '\\') {
++ptr; ++ptr;
if (ptr == to) { if (ptr == to) {
qDebug() << "JSON Parse Error, unterminated backslash escape"; qWarning("JSON Parse Error, unterminated backslash escape in '%s'",
QByteArray(fromSaved, to - fromSaved).constData());
from = ptr; // So we don't hang from = ptr; // So we don't hang
return QByteArray(); return QByteArray();
} }
@@ -130,8 +132,24 @@ QByteArray JsonValue::parseCString(const char *&from, const char *to)
case 'v': *dst++ = '\v'; break; case 'v': *dst++ = '\v'; break;
case '"': *dst++ = '"'; break; case '"': *dst++ = '"'; break;
case '\\': *dst++ = '\\'; break; case '\\': *dst++ = '\\'; break;
default: case 'u': { // 4 digit hex escape as in '\u000a'
{ if (end - src < 4) {
qWarning("JSON Parse Error, too few hex digits in \\u-escape in '%s' obtained from '%s'",
result.constData(), QByteArray(fromSaved, to - fromSaved).constData());
return QByteArray();
}
bool ok;
const uchar prod = QByteArray(src, 4).toUInt(&ok, 16);
if (!ok) {
qWarning("JSON Parse Error, invalid hex digits in \\u-escape in '%s' obtained from '%s'",
result.constData(), QByteArray(fromSaved, to - fromSaved).constData());
return QByteArray();
}
*dst++ = prod;
src += 4;
}
break;
default: { // Up to 3 decimal digits: Not sure if this is supported in JSON?
int chars = 0; int chars = 0;
uchar prod = 0; uchar prod = 0;
forever { forever {
@@ -145,7 +163,8 @@ QByteArray JsonValue::parseCString(const char *&from, const char *to)
c = *src++; c = *src++;
} }
if (!chars) { if (!chars) {
qDebug() << "JSON Parse Error, unrecognized backslash escape"; qWarning("JSON Parse Error, unrecognized backslash escape in string '%s' obtained from '%s'",
result.constData(), QByteArray(fromSaved, to - fromSaved).constData());
return QByteArray(); return QByteArray();
} }
*dst++ = prod; *dst++ = prod;

View File

@@ -383,14 +383,20 @@ TcfTrkEvent *TcfTrkEvent::parseEvent(Services s, const QByteArray &nameBA, const
const QByteArray idBA = values.at(0).data(); const QByteArray idBA = values.at(0).data();
const quint64 pc = values.at(1).data().toULongLong(); const quint64 pc = values.at(1).data().toULongLong();
const QByteArray reasonBA = values.at(2).data(); const QByteArray reasonBA = values.at(2).data();
QByteArray messageBA;
// Module load: Special // Module load: Special
if (reasonBA == sharedLibrarySuspendReasonC) { if (reasonBA == sharedLibrarySuspendReasonC) {
ModuleLoadEventInfo info; ModuleLoadEventInfo info;
if (!info.parse(values.at(3))) if (!info.parse(values.at(3)))
return 0; return 0;
return new TcfTrkRunControlModuleLoadContextSuspendedEvent(idBA, reasonBA, pc, info); return new TcfTrkRunControlModuleLoadContextSuspendedEvent(idBA, reasonBA, pc, info);
} else {
// hash containing a 'message'-key with a verbose crash message.
if (values.at(3).type() == JsonValue::Object && values.at(3).childCount()
&& values.at(3).children().at(0).type() == JsonValue::String)
messageBA = values.at(3).children().at(0).data();
} }
return new TcfTrkRunControlContextSuspendedEvent(idBA, reasonBA, pc); return new TcfTrkRunControlContextSuspendedEvent(idBA, reasonBA, messageBA, pc);
} // "contextSuspended" } // "contextSuspended"
if (nameBA == "contextAdded") if (nameBA == "contextAdded")
return TcfTrkRunControlContextAddedEvent::parseEvent(values); return TcfTrkRunControlContextAddedEvent::parseEvent(values);
@@ -505,8 +511,9 @@ QString TcfTrkRunControlContextRemovedEvent::toString() const
// --------------- TcfTrkRunControlContextSuspendedEvent // --------------- TcfTrkRunControlContextSuspendedEvent
TcfTrkRunControlContextSuspendedEvent::TcfTrkRunControlContextSuspendedEvent(const QByteArray &id, TcfTrkRunControlContextSuspendedEvent::TcfTrkRunControlContextSuspendedEvent(const QByteArray &id,
const QByteArray &reason, const QByteArray &reason,
const QByteArray &message,
quint64 pc) : quint64 pc) :
TcfTrkIdEvent(RunControlSuspended, id), m_pc(pc), m_reason(reason) TcfTrkIdEvent(RunControlSuspended, id), m_pc(pc), m_reason(reason), m_message(message)
{ {
} }
@@ -524,6 +531,8 @@ void TcfTrkRunControlContextSuspendedEvent::format(QTextStream &str) const
str << "RunControl: '" << idString() << "' suspended at 0x" str << "RunControl: '" << idString() << "' suspended at 0x"
<< m_pc << ": '" << m_reason << "'."; << m_pc << ": '" << m_reason << "'.";
str.setIntegerBase(10); str.setIntegerBase(10);
if (!m_message.isEmpty())
str << " (" <<m_message << ')';
} }
QString TcfTrkRunControlContextSuspendedEvent::toString() const QString TcfTrkRunControlContextSuspendedEvent::toString() const

View File

@@ -262,12 +262,14 @@ public:
explicit TcfTrkRunControlContextSuspendedEvent(const QByteArray &id, explicit TcfTrkRunControlContextSuspendedEvent(const QByteArray &id,
const QByteArray &reason, const QByteArray &reason,
const QByteArray &message,
quint64 pc = 0); quint64 pc = 0);
virtual QString toString() const; virtual QString toString() const;
quint64 pc() const { return m_pc; } quint64 pc() const { return m_pc; }
QByteArray reasonID() const { return m_reason; } QByteArray reasonID() const { return m_reason; }
Reason reason() const; Reason reason() const;
QByteArray message() const { return m_message; }
protected: protected:
explicit TcfTrkRunControlContextSuspendedEvent(Type t, explicit TcfTrkRunControlContextSuspendedEvent(Type t,
@@ -279,6 +281,7 @@ protected:
private: private:
const quint64 m_pc; const quint64 m_pc;
const QByteArray m_reason; const QByteArray m_reason;
const QByteArray m_message;
}; };
// RunControlContextSuspended due to module load // RunControlContextSuspended due to module load