Commit 9a5908bf authored by hjk's avatar hjk
Browse files

debugger: small improvements to dumpers

Add a dumper for QStack. Also don't crash when accessing an uninitialized
pointer when the pointer looks bad to begin with.
parent b901b501
......@@ -47,6 +47,7 @@
#include <QtCore/QPointer>
#include <QtCore/QRect>
#include <QtCore/QRectF>
#include <QtCore/QStack>
#include <QtCore/QSize>
#include <QtCore/QSizeF>
#include <QtCore/QString>
......@@ -270,15 +271,45 @@ static bool startsWith(const char *s, const char *t)
return true;
}
static bool couldBePointer(const void *p)
{
// we assume valid pointer to be 4-aligned at least.
// So use this check only when this is guaranteed.
const quintptr d = quintptr(p);
qDebug() << "CHECKING : " << p << ((d & 3) == 0 && (d > 1000 || d == 0));
return (d & 3) == 0 && (d > 1000 || d == 0);
}
// Check memory for read access and provoke segfault if nothing else helps.
// On Windows, try to be less crash-prone by checking memory using WinAPI
#ifdef Q_OS_WIN
# define qCheckAccess(d) do { if (IsBadReadPtr(d, 1)) return; qProvokeSegFaultHelper = *(char*)d; } while (0)
# define qCheckPointer(d) do { if (d && IsBadReadPtr(d, 1)) return; if (d) qProvokeSegFaultHelper = *(char*)d; } while (0)
# define qCheckAccess(d) do { \
if (IsBadReadPtr(d, 1)) \
return; \
qProvokeSegFaultHelper = *(char*)d; \
} while (0)
# define qCheckPointer(d) do { \
if (d && IsBadReadPtr(d, 1)) \
return; \
if (d) qProvokeSegFaultHelper = *(char*)d; \
} while (0)
#else
# define qCheckAccess(d) do { qProvokeSegFaultHelper = *(char*)d; } while (0)
# define qCheckPointer(d) do { if (d) qProvokeSegFaultHelper = *(char*)d; } while (0)
# define qCheckAccess(d) do { \
if (!couldBePointer(d) && d != 0) \
return; \
qProvokeSegFaultHelper = *(char*)d; \
} while (0)
# define qCheckPointer(d) do { \
if (!couldBePointer(d)) \
return; \
if (d) \
qProvokeSegFaultHelper = *(char*)d; \
} while (0)
#endif
#ifdef QT_NAMESPACE
......@@ -848,6 +879,7 @@ static void qDumpUnknown(QDumper &d, const char *why = 0)
why = DUMPUNKNOWN_MESSAGE;
d.putItem("value", why);
d.putItem("type", d.outertype);
d.putItem("valuedisabled", "true");
d.putItem("numchild", "0", d.currentChildNumChild);
d.disarm();
}
......@@ -1143,6 +1175,7 @@ static void qDumpQAbstractItemModel(QDumper &d)
static void qDumpQByteArray(QDumper &d)
{
qCheckAccess(deref(d.data));
const QByteArray &ba = *reinterpret_cast<const QByteArray *>(d.data);
if (!ba.isEmpty()) {
......@@ -1408,10 +1441,11 @@ int hashOffset(bool optimizedIntKey, bool forKey, unsigned keySize, unsigned val
static void qDumpQHash(QDumper &d)
{
QHashData *h = *reinterpret_cast<QHashData *const*>(d.data);
qCheckAccess(deref(d.data));
const char *keyType = d.templateParameters[0];
const char *valueType = d.templateParameters[1];
QHashData *h = *reinterpret_cast<QHashData *const*>(d.data);
qCheckPointer(h->fakeNext);
qCheckPointer(h->buckets);
......@@ -1515,6 +1549,7 @@ static void qDumpQHashNode(QDumper &d)
#if USE_QT_GUI
static void qDumpQImage(QDumper &d)
{
qCheckAccess(deref(d.data));
const QImage &im = *reinterpret_cast<const QImage *>(d.data);
d.beginItem("value");
d.put("(").put(im.width()).put("x").put(im.height()).put(")");
......@@ -1556,20 +1591,17 @@ static void qDumpQImageData(QDumper &d)
static void qDumpQList(QDumper &d)
{
qCheckAccess(deref(d.data));
// This uses the knowledge that QList<T> has only a single member
// of type union { QListData p; QListData::Data *d; };
const QListData &ldata = *reinterpret_cast<const QListData*>(d.data);
const QListData::Data *pdata =
*reinterpret_cast<const QListData::Data* const*>(d.data);
qCheckAccess(pdata);
int nn = ldata.size();
if (nn < 0)
return;
if (nn > 0) {
qCheckAccess(ldata.d->array);
//qCheckAccess(ldata.d->array[0]);
//qCheckAccess(ldata.d->array[nn - 1]);
if (ldata.d->begin < 0)
return;
if (ldata.d->begin > ldata.d->end)
......@@ -1578,7 +1610,11 @@ static void qDumpQList(QDumper &d)
if (ldata.d->ref._q_value <= 0)
return;
#endif
qCheckAccess(ldata.d->array);
//qCheckAccess(ldata.d->array[0]);
//qCheckAccess(ldata.d->array[nn - 1]);
}
qCheckAccess(pdata);
int n = nn;
d.putItemCount("value", n);
......@@ -1635,6 +1671,7 @@ static void qDumpQList(QDumper &d)
static void qDumpQLinkedList(QDumper &d)
{
qCheckAccess(deref(d.data));
// This uses the knowledge that QLinkedList<T> has only a single member
// of type union { QLinkedListData *d; QLinkedListNode<T> *e; };
const QLinkedListData *ldata =
......@@ -1760,6 +1797,7 @@ static void qDumpQMapNode(QDumper &d)
static void qDumpQMap(QDumper &d)
{
qCheckAccess(deref(d.data));
QMapData *h = *reinterpret_cast<QMapData *const*>(d.data);
const char *keyType = d.templateParameters[0];
const char *valueType = d.templateParameters[1];
......@@ -1898,6 +1936,7 @@ static void qDumpQModelIndex(QDumper &d)
static void qDumpQObject(QDumper &d)
{
qCheckAccess(deref(d.data));
const QObject *ob = reinterpret_cast<const QObject *>(d.data);
const QMetaObject *mo = ob->metaObject();
d.putItem("value", ob->objectName());
......@@ -2147,6 +2186,7 @@ static void qDumpQVariant(QDumper &d, const QVariant *v)
static inline void qDumpQVariant(QDumper &d)
{
qCheckAccess(deref(d.data));
qDumpQVariant(d, reinterpret_cast<const QVariant *>(d.data));
}
......@@ -2772,6 +2812,7 @@ static void qDumpQSharedPointer(QDumper &d)
static void qDumpQString(QDumper &d)
{
qCheckAccess(deref(d.data));
const QString &str = *reinterpret_cast<const QString *>(d.data);
const int size = str.size();
......@@ -2796,6 +2837,7 @@ static void qDumpQString(QDumper &d)
static void qDumpQStringList(QDumper &d)
{
qCheckAccess(deref(d.data));
const QStringList &list = *reinterpret_cast<const QStringList *>(d.data);
int n = list.size();
if (n < 0)
......@@ -2827,6 +2869,7 @@ static void qDumpQStringList(QDumper &d)
static void qDumpQTextCodec(QDumper &d)
{
qCheckPointer(deref(d.data));
const QTextCodec &codec = *reinterpret_cast<const QTextCodec *>(d.data);
d.putItem("value", codec.name());
d.putItem("valueencoded", "1");
......@@ -2843,6 +2886,7 @@ static void qDumpQTextCodec(QDumper &d)
static void qDumpQVector(QDumper &d)
{
qCheckAccess(deref(d.data));
QVectorTypedData<int> *dummy = 0;
const unsigned typeddatasize = (char*)(&dummy->array) - (char*)dummy;
......@@ -3421,6 +3465,8 @@ static void handleProtocolVersion2and3(QDumper &d)
#ifndef QT_BOOTSTRAPPED
else if (isEqual(type, "QSet"))
qDumpQSet(d);
else if (isEqual(type, "QStack"))
qDumpQVector(d);
#if QT_VERSION >= 0x040500
else if (isEqual(type, "QSharedPointer"))
qDumpQSharedPointer(d);
......@@ -3596,6 +3642,7 @@ void *qDumpObjectData440(
"\""NS"QRectF\","
//"\""NS"QRegion\","
"\""NS"QSet\","
"\""NS"QStack\","
"\""NS"QString\","
"\""NS"QStringList\","
"\""NS"QTextCodec\","
......
......@@ -2907,7 +2907,8 @@ void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren)
WatchData data = data0;
// Avoid endless loops created by faulty dumpers
if (m_processedNames.contains(data.iname)) {
QString processedName = QString(_("%1-%2").arg(dumpChildren).arg(data.iname));
if (m_processedNames.contains(processedName)) {
emit gdbInputAvailable(LogStatus,
_("<Breaking endless loop for %1>").arg(data.iname));
data.setAllUnneeded();
......@@ -2916,7 +2917,7 @@ void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren)
insertData(data);
return;
}
m_processedNames.insert(data.iname);
m_processedNames.insert(processedName);
QByteArray params;
QStringList extraArgs;
......@@ -3427,7 +3428,7 @@ void GdbEngine::handleDebuggingHelperValue2(const GdbResultRecord &record,
WatchData childtemplate;
setWatchDataType(childtemplate, contents.findChild("childtype"));
setWatchDataChildCount(childtemplate, contents.findChild("childnumchild"));
//qDebug() << "DATA:" << data.toString();
//qDebug() << "CHILD TEMPLATE:" << childtemplate.toString();
qq->watchHandler()->insertData(data);
int i = 0;
......
......@@ -785,24 +785,26 @@ QtDumperHelper::Type QtDumperHelper::specialType(QString s)
} else {
s = s.mid(namespaceIndex + 2);
}
if (s == QLatin1String("QObject"))
return QObjectType;
if (s == QLatin1String("QWidget"))
return QWidgetType;
if (s == QLatin1String("QObjectSlot"))
return QObjectSlotType;
if (s == QLatin1String("QObjectSignal"))
return QObjectSignalType;
if (s == QLatin1String("QVector"))
return QVectorType;
if (s == QLatin1String("QAbstractItem"))
return QAbstractItemType;
if (s == QLatin1String("QMap"))
return QMapType;
if (s == QLatin1String("QMultiMap"))
return QMultiMapType;
if (s == QLatin1String("QMapNode"))
return QMapNodeType;
if (s == QLatin1String("QMultiMap"))
return QMultiMapType;
if (s == QLatin1String("QObject"))
return QObjectType;
if (s == QLatin1String("QObjectSignal"))
return QObjectSignalType;
if (s == QLatin1String("QObjectSlot"))
return QObjectSlotType;
if (s == QLatin1String("QStack"))
return QStackType;
if (s == QLatin1String("QVector"))
return QVectorType;
if (s == QLatin1String("QWidget"))
return QWidgetType;
return UnknownType;
}
......@@ -1458,6 +1460,7 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
break;
case SupportedType:
case QVectorType:
case QStackType:
case QObjectType:
case QWidgetType:
break;
......
......@@ -160,7 +160,7 @@ public:
// Below types require special handling
QAbstractItemType,
QObjectType, QWidgetType, QObjectSlotType, QObjectSignalType,
QVectorType, QMapType, QMultiMapType, QMapNodeType,
QVectorType, QMapType, QMultiMapType, QMapNodeType, QStackType,
StdVectorType, StdDequeType, StdSetType, StdMapType, StdStackType,
StdStringType
};
......
......@@ -36,6 +36,7 @@
#include <QtCore/QMap>
#include <QtCore/QPointer>
#include <QtCore/QString>
#include <QtCore/QStack>
#include <QtCore/QThread>
#include <QtCore/QVariant>
#include <QtCore/QVector>
......@@ -855,6 +856,30 @@ void testQStandardItemModel()
+i;
}
void testQStack()
{
QVector<int> bigv;
for (int i = 0; i < 10; ++i)
bigv.append(i);
QStack<int> big;
for (int i = 0; i < 10; ++i)
big.append(i);
QStack<Foo *> plist;
plist.append(new Foo(1));
plist.append(0);
plist.append(new Foo(2));
QStack<Foo> flist;
flist.append(1);
flist.append(2);
flist.append(3);
flist.append(4);
//flist.takeFirst();
//flist.takeFirst();
QStack<bool> vec;
vec.append(true);
vec.append(false);
}
void testQString()
{
QString str = "Hello ";
......@@ -1236,9 +1261,31 @@ public:
Foo *f;
};
void testUninitialized()
{
QString s;
QStringList sl;
QMap<int, int> mii;
QMap<QString, QString> mss;
QHash<int, int> hii;
QHash<QString, QString> hss;
QList<int> li;
QVector<int> vi;
QStack<int> si;
std::string ss;
std::map<int, int> smii;
std::map<std::string, std::string> smss;
std::list<int> sli;
std::list<std::string> ssl;
std::vector<int> svi;
std::stack<int> ssi;
}
int main(int argc, char *argv[])
{
testQStack();
testUninitialized();
testPointer();
testQFileInfo();
testObject1();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment