forked from qt-creator/qt-creator
Debugger[TCF]: Parse \u-escapes in JSON correctly, report verbose
crash messages.
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user