Merge branch 'master' of git@scm.dev.nokia.troll.no:creator/mainline

This commit is contained in:
dt
2009-07-24 16:27:46 +02:00
18 changed files with 420 additions and 68 deletions

4
dist/changes-1.3.0 vendored
View File

@@ -15,6 +15,8 @@ Debugging
* CDB: Added more types to the dumpers (QSharedPointer, QVector, common * CDB: Added more types to the dumpers (QSharedPointer, QVector, common
* QMap/QSet types), dereference reference parameters * QMap/QSet types), dereference reference parameters
* CDB: Simplified display of STL types in the locals window * CDB: Simplified display of STL types in the locals window
* CDB: Fixed thread handling
* CDB: Added internal dumpers for string types for debugger crashes
* Improved QObject dumping, print out QRect/QSize, enumerations and flags * Improved QObject dumping, print out QRect/QSize, enumerations and flags
General: General:
@@ -24,6 +26,7 @@ General:
Editing: Editing:
* Added support for text editor color schemes * Added support for text editor color schemes
* Added highlighting of uses of the symbol under the cursor * Added highlighting of uses of the symbol under the cursor
* Added completion of include directives
* Added the option to turn off marking of text changes * Added the option to turn off marking of text changes
Project support: Project support:
@@ -39,3 +42,4 @@ Wizards
* Added version control checkout wizards * Added version control checkout wizards
* Added a license header template setting * Added a license header template setting
* Added a wizard for Qt Designer custom widgets * Added a wizard for Qt Designer custom widgets
* Added a gitorious clone wizard

View File

@@ -1386,6 +1386,12 @@ void CppCodeCompletion::completions(QList<TextEditor::CompletionItem> *completio
else if (length > 0) { else if (length > 0) {
const QString key = m_editor->textAt(m_startPosition, length); const QString key = m_editor->textAt(m_startPosition, length);
/* Close on the trailing slash for include completion, to enable the slash to
* trigger a new completion list. */
if ((m_completionOperator == T_STRING_LITERAL ||
m_completionOperator == T_ANGLE_STRING_LITERAL) && key.endsWith(QLatin1Char('/')))
return;
if (m_completionOperator != T_LPAREN) { if (m_completionOperator != T_LPAREN) {
/* /*
* This code builds a regular expression in order to more intelligently match * This code builds a regular expression in order to more intelligently match

View File

@@ -1177,8 +1177,11 @@ void CdbDebugEngine::selectThread(int index)
ThreadsHandler *threadsHandler = m_d->m_debuggerManagerAccess->threadsHandler(); ThreadsHandler *threadsHandler = m_d->m_debuggerManagerAccess->threadsHandler();
threadsHandler->setCurrentThread(index); threadsHandler->setCurrentThread(index);
m_d->m_currentThreadId = index; const int newThreadId = threadsHandler->threads().at(index).id;
m_d->updateStackTrace(); if (newThreadId != m_d->m_currentThreadId) {
m_d->m_currentThreadId = threadsHandler->threads().at(index).id;
m_d->updateStackTrace();
}
} }
void CdbDebugEngine::attemptBreakpointSynchronization() void CdbDebugEngine::attemptBreakpointSynchronization()
@@ -1223,7 +1226,7 @@ bool CdbDebugEnginePrivate::attemptBreakpointSynchronization(QString *errorMessa
m_cif.debugSymbols, m_cif.debugSymbols,
m_debuggerManagerAccess->breakHandler(), m_debuggerManagerAccess->breakHandler(),
errorMessage, &warnings); errorMessage, &warnings);
if (const int warningsCount = warnings.size()) if (const int warningsCount = warnings.size())
for (int w = 0; w < warningsCount; w++) for (int w = 0; w < warningsCount; w++)
m_engine->warning(warnings.at(w)); m_engine->warning(warnings.at(w));
return ok; return ok;
@@ -1390,6 +1393,16 @@ void CdbDebugEnginePrivate::notifyCrashed()
m_dumper->disable(); m_dumper->disable();
} }
static int threadIndexById(const ThreadsHandler *threadsHandler, int id)
{
const QList<ThreadData> threads = threadsHandler->threads();
const int count = threads.count();
for (int i = 0; i < count; i++)
if (threads.at(i).id == id)
return i;
return -1;
}
void CdbDebugEnginePrivate::handleDebugEvent() void CdbDebugEnginePrivate::handleDebugEvent()
{ {
if (debugCDB) if (debugCDB)
@@ -1401,10 +1414,15 @@ void CdbDebugEnginePrivate::handleDebugEvent()
m_breakEventMode = BreakEventHandle; m_breakEventMode = BreakEventHandle;
switch (mode) { switch (mode) {
case BreakEventHandle: case BreakEventHandle: {
m_debuggerManagerAccess->notifyInferiorStopped(); m_debuggerManagerAccess->notifyInferiorStopped();
updateThreadList(); m_currentThreadId = updateThreadList();
ThreadsHandler *threadsHandler = m_debuggerManagerAccess->threadsHandler();
const int threadIndex = threadIndexById(threadsHandler, m_currentThreadId);
if (threadIndex != -1)
threadsHandler->setCurrentThread(threadIndex);
updateStackTrace(); updateStackTrace();
}
break; break;
case BreakEventIgnoreOnce: case BreakEventIgnoreOnce:
m_engine->startWatchTimer(); m_engine->startWatchTimer();
@@ -1430,7 +1448,7 @@ void CdbDebugEnginePrivate::setDebuggeeHandles(HANDLE hDebuggeeProcess, HANDLE
m_hDebuggeeThread = hDebuggeeThread; m_hDebuggeeThread = hDebuggeeThread;
} }
void CdbDebugEnginePrivate::updateThreadList() ULONG CdbDebugEnginePrivate::updateThreadList()
{ {
if (debugCDB) if (debugCDB)
qDebug() << Q_FUNC_INFO << m_hDebuggeeProcess; qDebug() << Q_FUNC_INFO << m_hDebuggeeProcess;
@@ -1439,25 +1457,25 @@ void CdbDebugEnginePrivate::updateThreadList()
QList<ThreadData> threads; QList<ThreadData> threads;
bool success = false; bool success = false;
QString errorMessage; QString errorMessage;
ULONG currentThreadId = 0;
do { do {
ULONG numberOfThreads; ULONG threadCount;
HRESULT hr= m_cif.debugSystemObjects->GetNumberThreads(&numberOfThreads); HRESULT hr= m_cif.debugSystemObjects->GetNumberThreads(&threadCount);
if (FAILED(hr)) { if (FAILED(hr)) {
errorMessage= msgComFailed("GetNumberThreads", hr); errorMessage= msgComFailed("GetNumberThreads", hr);
break; break;
} }
const ULONG maxThreadIds = 256; // Get ids and index of current
ULONG threadIds[maxThreadIds]; if (threadCount) {
ULONG biggestThreadId = qMin(maxThreadIds, numberOfThreads - 1); m_cif.debugSystemObjects->GetCurrentThreadId(&currentThreadId);
hr = m_cif.debugSystemObjects->GetThreadIdsByIndex(0, biggestThreadId, threadIds, 0); QVector<ULONG> threadIds(threadCount);
if (FAILED(hr)) { hr = m_cif.debugSystemObjects->GetThreadIdsByIndex(0, threadCount, &(*threadIds.begin()), 0);
errorMessage= msgComFailed("GetThreadIdsByIndex", hr); if (FAILED(hr)) {
break; errorMessage= msgComFailed("GetThreadIdsByIndex", hr);
} break;
for (ULONG threadId = 0; threadId <= biggestThreadId; ++threadId) { }
ThreadData thread; for (ULONG i = 0; i < threadCount; i++)
thread.id = threadId; threads.push_back(ThreadData(threadIds.at(i)));
threads.append(thread);
} }
th->setThreads(threads); th->setThreads(threads);
@@ -1465,6 +1483,7 @@ void CdbDebugEnginePrivate::updateThreadList()
} while (false); } while (false);
if (!success) if (!success)
m_engine->warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage)); m_engine->warning(msgFunctionFailed(Q_FUNC_INFO, errorMessage));
return currentThreadId;
} }
void CdbDebugEnginePrivate::updateStackTrace() void CdbDebugEnginePrivate::updateStackTrace()

View File

@@ -115,7 +115,7 @@ struct CdbDebugEnginePrivate
bool isDebuggeeRunning() const { return m_watchTimer != -1; } bool isDebuggeeRunning() const { return m_watchTimer != -1; }
void handleDebugEvent(); void handleDebugEvent();
void updateThreadList(); ULONG updateThreadList();
void updateStackTrace(); void updateStackTrace();
void updateModules(); void updateModules();

View File

@@ -40,7 +40,7 @@
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
enum { OwnerNewItem, OwnerSymbolGroup, OwnerDumper }; enum { OwnerNewItem, OwnerSymbolGroup, OwnerSymbolGroupDumper , OwnerDumper };
typedef QSharedPointer<CdbDumperHelper> SharedPointerCdbDumperHelper; typedef QSharedPointer<CdbDumperHelper> SharedPointerCdbDumperHelper;
typedef QList<WatchData> WatchDataList; typedef QList<WatchData> WatchDataList;
@@ -216,6 +216,12 @@ WatchHandleDumperInserter &WatchHandleDumperInserter::operator=(WatchData &wd)
wd.source = OwnerDumper; wd.source = OwnerDumper;
return *this; return *this;
} }
// Expanded by internal dumper? : ok
if (wd.source == OwnerSymbolGroupDumper) {
m_wh->insertData(wd);
return *this;
}
// Try library dumpers.
switch (m_dumper->dumpType(wd, true, OwnerDumper, &m_dumperResult, &errorMessage)) { switch (m_dumper->dumpType(wd, true, OwnerDumper, &m_dumperResult, &errorMessage)) {
case CdbDumperHelper::DumpOk: case CdbDumperHelper::DumpOk:
if (debugCDBWatchHandling) if (debugCDBWatchHandling)
@@ -258,13 +264,15 @@ bool CdbStackFrameContext::populateModelInitially(WatchHandler *wh, QString *err
qDebug() << "populateModelInitially dumpers=" << m_useDumpers; qDebug() << "populateModelInitially dumpers=" << m_useDumpers;
// Recurse down items that are initially expanded in the view, stop processing for // Recurse down items that are initially expanded in the view, stop processing for
// dumper items. // dumper items.
const CdbSymbolGroupRecursionContext rctx(m_symbolContext, OwnerSymbolGroupDumper,
m_dumper->comInterfaces()->debugDataSpaces);
const bool rc = m_useDumpers ? const bool rc = m_useDumpers ?
CdbSymbolGroupContext::populateModelInitially(m_symbolContext, CdbSymbolGroupContext::populateModelInitially(rctx,
WatchHandleDumperInserter(wh, m_dumper), WatchHandleDumperInserter(wh, m_dumper),
WatchHandlerExpandedPredicate(wh), WatchHandlerExpandedPredicate(wh),
isDumperPredicate, isDumperPredicate,
errorMessage) : errorMessage) :
CdbSymbolGroupContext::populateModelInitially(m_symbolContext, CdbSymbolGroupContext::populateModelInitially(rctx,
WatchHandlerModelInserter(wh), WatchHandlerModelInserter(wh),
WatchHandlerExpandedPredicate(wh), WatchHandlerExpandedPredicate(wh),
falsePredicate, falsePredicate,
@@ -279,9 +287,11 @@ bool CdbStackFrameContext::completeData(const WatchData &incompleteLocal,
if (debugCDBWatchHandling) if (debugCDBWatchHandling)
qDebug() << ">completeData src=" << incompleteLocal.source << incompleteLocal.toString(); qDebug() << ">completeData src=" << incompleteLocal.source << incompleteLocal.toString();
const CdbSymbolGroupRecursionContext rctx(m_symbolContext, OwnerSymbolGroupDumper,
m_dumper->comInterfaces()->debugDataSpaces);
// Expand symbol group items, recurse one level from desired item // Expand symbol group items, recurse one level from desired item
if (!m_useDumpers) { if (!m_useDumpers) {
return CdbSymbolGroupContext::completeData(m_symbolContext, incompleteLocal, return CdbSymbolGroupContext::completeData(rctx, incompleteLocal,
WatchHandlerModelInserter(wh), WatchHandlerModelInserter(wh),
MatchINamePredicate(incompleteLocal.iname), MatchINamePredicate(incompleteLocal.iname),
falsePredicate, falsePredicate,
@@ -311,7 +321,7 @@ bool CdbStackFrameContext::completeData(const WatchData &incompleteLocal,
} }
// Expand symbol group items, recurse one level from desired item // Expand symbol group items, recurse one level from desired item
return CdbSymbolGroupContext::completeData(m_symbolContext, incompleteLocal, return CdbSymbolGroupContext::completeData(rctx, incompleteLocal,
WatchHandleDumperInserter(wh, m_dumper), WatchHandleDumperInserter(wh, m_dumper),
MatchINamePredicate(incompleteLocal.iname), MatchINamePredicate(incompleteLocal.iname),
isDumperPredicate, isDumperPredicate,

View File

@@ -33,15 +33,22 @@
#include "watchutils.h" #include "watchutils.h"
#include <QtCore/QTextStream> #include <QtCore/QTextStream>
#include <QtCore/QCoreApplication>
#include <QtCore/QRegExp> #include <QtCore/QRegExp>
enum { debug = 0 }; enum { debug = 0 };
enum { debugInternalDumpers = 0 };
static inline QString msgSymbolNotFound(const QString &s) static inline QString msgSymbolNotFound(const QString &s)
{ {
return QString::fromLatin1("The symbol '%1' could not be found.").arg(s); return QString::fromLatin1("The symbol '%1' could not be found.").arg(s);
} }
static inline QString msgOutOfScope()
{
return QCoreApplication::translate("SymbolGroup", "Out of scope");
}
static inline bool isTopLevelSymbol(const DEBUG_SYMBOL_PARAMETERS &p) static inline bool isTopLevelSymbol(const DEBUG_SYMBOL_PARAMETERS &p)
{ {
return p.ParentSymbol == DEBUG_ANY_ID; return p.ParentSymbol == DEBUG_ANY_ID;
@@ -102,6 +109,16 @@ static inline QString getSymbolString(IDebugSymbolGroup2 *sg,
namespace Debugger { namespace Debugger {
namespace Internal { namespace Internal {
CdbSymbolGroupRecursionContext::CdbSymbolGroupRecursionContext(CdbSymbolGroupContext *ctx,
int ido,
CIDebugDataSpaces *ds) :
context(ctx),
internalDumperOwner(ido),
dataspaces(ds)
{
}
static inline CdbSymbolGroupContext::SymbolState getSymbolState(const DEBUG_SYMBOL_PARAMETERS &p) static inline CdbSymbolGroupContext::SymbolState getSymbolState(const DEBUG_SYMBOL_PARAMETERS &p)
{ {
if (p.SubElements == 0u) if (p.SubElements == 0u)
@@ -419,6 +436,13 @@ WatchData CdbSymbolGroupContext::symbolAt(unsigned long index) const
return wd; return wd;
} }
WatchData CdbSymbolGroupContext::dumpSymbolAt(CIDebugDataSpaces *ds, unsigned long index)
{
WatchData rc = symbolAt(index);
dump(ds, &rc);
return rc;
}
bool CdbSymbolGroupContext::assignValue(const QString &iname, const QString &value, bool CdbSymbolGroupContext::assignValue(const QString &iname, const QString &value,
QString *newValue, QString *errorMessage) QString *newValue, QString *errorMessage)
{ {
@@ -561,5 +585,189 @@ bool CdbSymbolGroupContext::debugValueToInteger(const DEBUG_VALUE &dv, qint64 *v
return false; return false;
} }
/* The special type dumpers have an integer return code meaning:
* 0: ok
* 1: Dereferencing or retrieving memory failed, this is out of scope,
* do not try to query further.
* > 1: A structural error was encountered, that is, the implementation
* of the class changed (Qt or say, a different STL implementation).
* Visibly warn about it.
* To add further types, have a look at the toString() output of the
* symbol group. */
static QString msgStructuralError(const QString &type, int code)
{
return QString::fromLatin1("Warning: Internal dumper for '%1' failed with %2.").arg(type).arg(code);
}
static inline bool isStdStringOrPointer(const QString &type)
{
#define STD_WSTRING "std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >"
#define STD_STRING "std::basic_string<char,std::char_traits<char>,std::allocator<char> >"
return type.endsWith(QLatin1String(STD_STRING))
|| type.endsWith(QLatin1String(STD_STRING" *"))
|| type.endsWith(QLatin1String(STD_WSTRING))
|| type.endsWith(QLatin1String(STD_WSTRING" *"));
#undef STD_WSTRING
#undef STD_STRING
}
CdbSymbolGroupContext::DumperResult
CdbSymbolGroupContext::dump(CIDebugDataSpaces *ds, WatchData *wd)
{
DumperResult rc = DumperNotHandled;
do {
// Is this a previously detected Null-Pointer?
if (wd->isHasChildrenKnown() && !wd->hasChildren)
break;
// QString
if (wd->type.endsWith(QLatin1String("QString")) || wd->type.endsWith(QLatin1String("QString *"))) {
const int drc = dumpQString(ds, wd);
switch (drc) {
case 0:
rc = DumperOk;
break;
case 1:
rc = DumperError;
break;
default:
qWarning("%s\n", qPrintable(msgStructuralError(wd->type, drc)));
rc = DumperNotHandled;
break;
}
}
// StdString
if (isStdStringOrPointer(wd->type)) {
const int drc = dumpStdString(wd);
switch (drc) {
case 0:
rc = DumperOk;
break;
case 1:
rc = DumperError;
break;
default:
qWarning("%s\n", qPrintable(msgStructuralError(wd->type, drc)));
rc = DumperNotHandled;
break;
}
}
} while (false);
if (debugInternalDumpers)
qDebug() << "CdbSymbolGroupContext::dump" << rc << wd->toString();
return rc;
}
// Get integer value of symbol group
static inline bool getIntValue(CIDebugSymbolGroup *sg, int index, int *value)
{
const QString valueS = getSymbolString(sg, &IDebugSymbolGroup2::GetSymbolValueTextWide, index);
bool ok;
*value = valueS.toInt(&ok);
return ok;
}
// Get pointer value of symbol group ("0xAAB")
static inline bool getPointerValue(CIDebugSymbolGroup *sg, int index, quint64 *value)
{
*value = 0;
QString valueS = getSymbolString(sg, &IDebugSymbolGroup2::GetSymbolValueTextWide, index);
if (!valueS.startsWith(QLatin1String("0x")))
return false;
valueS.remove(0, 2);
bool ok;
*value = valueS.toULongLong(&ok, 16);
return ok;
}
int CdbSymbolGroupContext::dumpQString(CIDebugDataSpaces *ds, WatchData *wd)
{
const int maxLength = 40;
QString errorMessage;
unsigned long stringIndex;
if (!lookupPrefix(wd->iname, &stringIndex))
return 1;
// Expand string and it's "d" (step over 'static null')
if (!expandSymbol(wd->iname, stringIndex, &errorMessage))
return 2;
const unsigned long dIndex = stringIndex + 4;
if (!expandSymbol(wd->iname, dIndex, &errorMessage))
return 3;
const unsigned long sizeIndex = dIndex + 3;
const unsigned long arrayIndex = dIndex + 4;
// Get size and pointer
int size;
if (!getIntValue(m_symbolGroup, sizeIndex, &size))
return 4;
quint64 array;
if (!getPointerValue(m_symbolGroup, arrayIndex, &array))
return 5;
// Fetch
const bool truncated = size > maxLength;
if (truncated)
size = maxLength;
const QChar doubleQuote = QLatin1Char('"');
QString value(doubleQuote);
if (size) {
// Should this ever be a remote debugger, need to check byte order.
unsigned short *buf = new unsigned short[size + 1];
unsigned long bytesRead;
const HRESULT hr = ds->ReadVirtual(array, buf, size * sizeof(unsigned short), &bytesRead);
if (FAILED(hr)) {
delete [] buf;
return 1;
}
buf[bytesRead / sizeof(unsigned short)] = 0;
value += QString::fromUtf16(buf);
delete [] buf;
if (truncated)
value += QLatin1String("...");
}
value += doubleQuote;
wd->setValue(value);
wd->setHasChildren(false);
return 0;
}
int CdbSymbolGroupContext::dumpStdString(WatchData *wd)
{
const int maxLength = 40;
QString errorMessage;
unsigned long stringIndex;
if (!lookupPrefix(wd->iname, &stringIndex))
return 1;
// Expand string ->string_val->_bx.
if (!expandSymbol(wd->iname, stringIndex, &errorMessage))
return 1;
const unsigned long bxIndex = stringIndex + 3;
if (!expandSymbol(wd->iname, bxIndex, &errorMessage))
return 2;
// Check if size is something sane
const int sizeIndex = stringIndex + 6;
int size;
if (!getIntValue(m_symbolGroup, sizeIndex, &size))
return 3;
if (size < 0)
return 1;
// Just copy over the value of the buf[]-array, which should be the string
const QChar doubleQuote = QLatin1Char('"');
const int bufIndex = stringIndex + 4;
QString bufValue = getSymbolString(m_symbolGroup, &IDebugSymbolGroup2::GetSymbolValueTextWide, bufIndex);
const int quotePos = bufValue.indexOf(doubleQuote);
if (quotePos == -1)
return 1;
bufValue.remove(0, quotePos);
if (bufValue.size() > maxLength) {
bufValue.truncate(maxLength);
bufValue += QLatin1String("...\"");
}
wd->setValue(bufValue);
wd->setHasChildren(false);
return 0;
}
} // namespace Internal } // namespace Internal
} // namespace Debugger } // namespace Debugger

View File

@@ -46,6 +46,7 @@ namespace Internal {
class WatchData; class WatchData;
class WatchHandler; class WatchHandler;
struct CdbSymbolGroupRecursionContext;
/* A thin wrapper around the IDebugSymbolGroup2 interface which represents /* A thin wrapper around the IDebugSymbolGroup2 interface which represents
* a flat list of symbols using an index (for example, belonging to a stack * a flat list of symbols using an index (for example, belonging to a stack
@@ -73,7 +74,7 @@ class CdbSymbolGroupContext
public: public:
~CdbSymbolGroupContext(); ~CdbSymbolGroupContext();
static CdbSymbolGroupContext *create(const QString &prefix, static CdbSymbolGroupContext *create(const QString &prefix,
CIDebugSymbolGroup *symbolGroup, CIDebugSymbolGroup *symbolGroup,
QString *errorMessage); QString *errorMessage);
QString prefix() const { return m_prefix; } QString prefix() const { return m_prefix; }
@@ -87,7 +88,7 @@ public:
// to terminate processing after insertion of an item (if the calling // to terminate processing after insertion of an item (if the calling
// routine wants to insert another subtree). // routine wants to insert another subtree).
template <class OutputIterator, class RecursionPredicate, class IgnorePredicate> template <class OutputIterator, class RecursionPredicate, class IgnorePredicate>
static bool populateModelInitially(CdbSymbolGroupContext *sg, static bool populateModelInitially(const CdbSymbolGroupRecursionContext &ctx,
OutputIterator it, OutputIterator it,
RecursionPredicate recursionPredicate, RecursionPredicate recursionPredicate,
IgnorePredicate ignorePredicate, IgnorePredicate ignorePredicate,
@@ -99,7 +100,7 @@ public:
// to terminate processing after insertion of an item (if the calling // to terminate processing after insertion of an item (if the calling
// routine wants to insert another subtree). // routine wants to insert another subtree).
template <class OutputIterator, class RecursionPredicate, class IgnorePredicate> template <class OutputIterator, class RecursionPredicate, class IgnorePredicate>
static bool completeData (CdbSymbolGroupContext *sg, static bool completeData (const CdbSymbolGroupRecursionContext &ctx,
WatchData incompleteLocal, WatchData incompleteLocal,
OutputIterator it, OutputIterator it,
RecursionPredicate recursionPredicate, RecursionPredicate recursionPredicate,
@@ -108,9 +109,19 @@ public:
// Retrieve child symbols of prefix as a sequence of WatchData. // Retrieve child symbols of prefix as a sequence of WatchData.
template <class OutputIterator> template <class OutputIterator>
bool getChildSymbols(const QString &prefix, OutputIterator it, QString *errorMessage); bool getChildSymbols(const QString &prefix, OutputIterator it, QString *errorMessage)
{ return getDumpChildSymbols(0, prefix, 0, it, errorMessage); }
// Retrieve child symbols of prefix as a sequence of WatchData.
// Is CIDebugDataSpaces is != 0, try internal dumper and set owner
template <class OutputIterator>
bool getDumpChildSymbols(CIDebugDataSpaces *ds, const QString &prefix,
int dumpedOwner,
OutputIterator it, QString *errorMessage);
WatchData symbolAt(unsigned long index) const; WatchData symbolAt(unsigned long index) const;
// Run the internal dumpers on the symbol
WatchData dumpSymbolAt(CIDebugDataSpaces *ds, unsigned long index);
bool lookupPrefix(const QString &prefix, unsigned long *index) const; bool lookupPrefix(const QString &prefix, unsigned long *index) const;
enum SymbolState { LeafSymbol, ExpandedSymbol, CollapsedSymbol }; enum SymbolState { LeafSymbol, ExpandedSymbol, CollapsedSymbol };
@@ -127,6 +138,10 @@ public:
// format an array of unsigned longs as "0x323, 0x2322, ..." // format an array of unsigned longs as "0x323, 0x2322, ..."
static QString hexFormatArray(const unsigned short *array, int size); static QString hexFormatArray(const unsigned short *array, int size);
// Dump
enum DumperResult { DumperOk, DumperError, DumperNotHandled };
DumperResult dump(CIDebugDataSpaces *ds, WatchData *wd);
private: private:
typedef QMap<QString, unsigned long> NameIndexMap; typedef QMap<QString, unsigned long> NameIndexMap;
@@ -140,8 +155,11 @@ private:
unsigned long *parentId, unsigned long *parentId,
QString *errorMessage); QString *errorMessage);
bool expandSymbol(const QString &prefix, unsigned long index, QString *errorMessage); bool expandSymbol(const QString &prefix, unsigned long index, QString *errorMessage);
void populateINameIndexMap(const QString &prefix, unsigned long parentId, unsigned long start, unsigned long count); void populateINameIndexMap(const QString &prefix, unsigned long parentId, unsigned long start, unsigned long count);
QString symbolINameAt(unsigned long index) const; QString symbolINameAt(unsigned long index) const;
int dumpQString(CIDebugDataSpaces *ds, WatchData *wd);
int dumpStdString(WatchData *wd);
inline DEBUG_SYMBOL_PARAMETERS *symbolParameters() { return &(*m_symbolParameters.begin()); } inline DEBUG_SYMBOL_PARAMETERS *symbolParameters() { return &(*m_symbolParameters.begin()); }
inline const DEBUG_SYMBOL_PARAMETERS *symbolParameters() const { return &(*m_symbolParameters.constBegin()); } inline const DEBUG_SYMBOL_PARAMETERS *symbolParameters() const { return &(*m_symbolParameters.constBegin()); }
@@ -155,6 +173,16 @@ private:
int m_unnamedSymbolNumber; int m_unnamedSymbolNumber;
}; };
// A convenience struct to save parameters for the model recursion.
struct CdbSymbolGroupRecursionContext {
explicit CdbSymbolGroupRecursionContext(CdbSymbolGroupContext *ctx, int internalDumperOwner, CIDebugDataSpaces *ds);
CdbSymbolGroupContext *context;
int internalDumperOwner;
CIDebugDataSpaces *dataspaces;
};
// Helper to a sequence of WatchData into a list. // Helper to a sequence of WatchData into a list.
class WatchDataBackInserter class WatchDataBackInserter
{ {

View File

@@ -48,18 +48,32 @@ enum { debugSgRecursion = 0 };
} }
template <class OutputIterator> template <class OutputIterator>
bool CdbSymbolGroupContext::getChildSymbols(const QString &prefix, OutputIterator it, QString *errorMessage) bool CdbSymbolGroupContext::getDumpChildSymbols(CIDebugDataSpaces *ds, const QString &prefix,
int dumpedOwner,
OutputIterator it, QString *errorMessage)
{ {
unsigned long start; unsigned long start;
unsigned long parentId; unsigned long parentId;
if (!getChildSymbolsPosition(prefix, &start, &parentId, errorMessage)) if (!getChildSymbolsPosition(prefix, &start, &parentId, errorMessage))
return false; return false;
// Skip over expanded children // Skip over expanded children. Internal dumping might expand
const unsigned long end = m_symbolParameters.size(); // children, so, re-evaluate size in end condition.
for (unsigned long s = start; s < end; ++s) { for (int s = start; s < m_symbolParameters.size(); ++s) {
const DEBUG_SYMBOL_PARAMETERS &p = m_symbolParameters.at(s); const DEBUG_SYMBOL_PARAMETERS &p = m_symbolParameters.at(s);
if (p.ParentSymbol == parentId && isSymbolDisplayable(p)) { if (p.ParentSymbol == parentId && isSymbolDisplayable(p)) {
*it = symbolAt(s); WatchData wd = symbolAt(s);
// Run internal dumper, mark ownership
if (ds) {
switch (dump(ds, &wd)) {
case DumperOk:
case DumperError: // Not initialized yet, do not run other dumpers
wd.source = dumpedOwner;
break;
case DumperNotHandled:
break;
}
}
*it = wd;
++it; ++it;
} }
} }
@@ -73,7 +87,7 @@ bool CdbSymbolGroupContext::getChildSymbols(const QString &prefix, OutputIterato
// (expand icon), though (ignore for simplicity). // (expand icon), though (ignore for simplicity).
template <class OutputIterator, class RecursionPredicate, class IgnorePredicate> template <class OutputIterator, class RecursionPredicate, class IgnorePredicate>
bool insertSymbolRecursion(WatchData wd, bool insertSymbolRecursion(WatchData wd,
CdbSymbolGroupContext *sg, const CdbSymbolGroupRecursionContext &ctx,
OutputIterator it, OutputIterator it,
RecursionPredicate recursionPredicate, RecursionPredicate recursionPredicate,
IgnorePredicate ignorePredicate, IgnorePredicate ignorePredicate,
@@ -110,13 +124,16 @@ bool insertSymbolRecursion(WatchData wd,
return true; return true;
QList<WatchData> watchList; QList<WatchData> watchList;
// This implicitly enforces expansion // This implicitly enforces expansion
if (!sg->getChildSymbols(wd.iname, WatchDataBackInserter(watchList), errorMessage)) if (!ctx.context->getDumpChildSymbols(ctx.dataspaces,
wd.iname,
ctx.internalDumperOwner,
WatchDataBackInserter(watchList), errorMessage))
return false; return false;
const int childCount = watchList.size(); const int childCount = watchList.size();
for (int c = 0; c < childCount; c++) { for (int c = 0; c < childCount; c++) {
const WatchData &cwd = watchList.at(c); const WatchData &cwd = watchList.at(c);
if (wd.isValid()) { // We sometimes get empty names for deeply nested data if (wd.isValid()) { // We sometimes get empty names for deeply nested data
if (!insertSymbolRecursion(cwd, sg, it, recursionPredicate, ignorePredicate, errorMessage)) if (!insertSymbolRecursion(cwd, ctx, it, recursionPredicate, ignorePredicate, errorMessage))
return false; return false;
} else { } else {
const QString msg = QString::fromLatin1("WARNING: Skipping invalid child symbol #%2 (type %3) of '%4'."). const QString msg = QString::fromLatin1("WARNING: Skipping invalid child symbol #%2 (type %3) of '%4'.").
@@ -128,7 +145,7 @@ bool insertSymbolRecursion(WatchData wd,
} }
template <class OutputIterator, class RecursionPredicate, class IgnorePredicate> template <class OutputIterator, class RecursionPredicate, class IgnorePredicate>
bool CdbSymbolGroupContext::populateModelInitially(CdbSymbolGroupContext *sg, bool CdbSymbolGroupContext::populateModelInitially(const CdbSymbolGroupRecursionContext &ctx,
OutputIterator it, OutputIterator it,
RecursionPredicate recursionPredicate, RecursionPredicate recursionPredicate,
IgnorePredicate ignorePredicate, IgnorePredicate ignorePredicate,
@@ -139,17 +156,20 @@ bool CdbSymbolGroupContext::populateModelInitially(CdbSymbolGroupContext *sg,
// Insert root items // Insert root items
QList<WatchData> watchList; QList<WatchData> watchList;
if (!sg->getChildSymbols(sg->prefix(), WatchDataBackInserter(watchList), errorMessage)) CdbSymbolGroupContext *sg = ctx.context;
if (!sg->getDumpChildSymbols(ctx.dataspaces, sg->prefix(),
ctx.internalDumperOwner,
WatchDataBackInserter(watchList), errorMessage))
return false; return false;
// Insert data // Insert data
foreach(const WatchData &wd, watchList) foreach(const WatchData &wd, watchList)
if (!insertSymbolRecursion(wd, sg, it, recursionPredicate, ignorePredicate, errorMessage)) if (!insertSymbolRecursion(wd, ctx, it, recursionPredicate, ignorePredicate, errorMessage))
return false; return false;
return true; return true;
} }
template <class OutputIterator, class RecursionPredicate, class IgnorePredicate> template <class OutputIterator, class RecursionPredicate, class IgnorePredicate>
bool CdbSymbolGroupContext::completeData(CdbSymbolGroupContext *sg, bool CdbSymbolGroupContext::completeData(const CdbSymbolGroupRecursionContext &ctx,
WatchData incompleteLocal, WatchData incompleteLocal,
OutputIterator it, OutputIterator it,
RecursionPredicate recursionPredicate, RecursionPredicate recursionPredicate,
@@ -160,7 +180,7 @@ bool CdbSymbolGroupContext::completeData(CdbSymbolGroupContext *sg,
qDebug().nospace() << "###>CdbSymbolGroupContext::completeData" << ' ' << incompleteLocal.iname << '\n'; qDebug().nospace() << "###>CdbSymbolGroupContext::completeData" << ' ' << incompleteLocal.iname << '\n';
// If the symbols are already expanded in the context, they will be re-inserted, // If the symbols are already expanded in the context, they will be re-inserted,
// which is not handled for simplicity. // which is not handled for simplicity.
if (!insertSymbolRecursion(incompleteLocal, sg, it, recursionPredicate, ignorePredicate, errorMessage)) if (!insertSymbolRecursion(incompleteLocal, ctx, it, recursionPredicate, ignorePredicate, errorMessage))
return false; return false;
return true; return true;
} }

View File

@@ -103,6 +103,7 @@ private:
struct ThreadData struct ThreadData
{ {
ThreadData(int threadId = 0) : id(threadId) {}
int id; int id;
}; };

View File

@@ -567,21 +567,24 @@ QList<WatchData> QtDumperResult::toWatchData(int source) const
wchild.valuedisabled = dchild.valuedisabled; wchild.valuedisabled = dchild.valuedisabled;
wchild.setValue(decodeData(dchild.value, dchild.valueEncoded)); wchild.setValue(decodeData(dchild.value, dchild.valueEncoded));
} }
wchild.setType(dchild.type.isEmpty() ? childType : dchild.type);
wchild.setAddress(dchild.address); wchild.setAddress(dchild.address);
// Child overrides. // The type setter sets hasChildren for known types.
const int effectiveChildChildCount = dchild.childCount == -1 ? childChildCount : dchild.childCount; wchild.setType(dchild.type.isEmpty() ? childType : dchild.type);
switch (effectiveChildChildCount) { if (wchild.isHasChildrenNeeded()) {
// Child overrides.
const int effectiveChildChildCount = dchild.childCount == -1 ? childChildCount : dchild.childCount;
switch (effectiveChildChildCount) {
case -1: case -1:
wchild.setChildrenNeeded(); wchild.setChildrenNeeded();
wchild.setHasChildrenNeeded(); wchild.setHasChildrenNeeded();
break; break;
case 0: case 0:
wchild.setHasChildren(false); wchild.setHasChildren(false);
break; break;
default: default:
wchild.setHasChildren(true); wchild.setHasChildren(true);
break; break;
}
} }
} }
} }

View File

@@ -129,7 +129,7 @@ void CompletionSupport::autoComplete_helper(ITextEditable *editor, bool forced,
m_startPosition = m_completionCollector->startCompletion(editor); m_startPosition = m_completionCollector->startCompletion(editor);
completionItems = getCompletions(); completionItems = getCompletions();
QTC_ASSERT(m_startPosition != -1 || completionItems.size() == 0, return); QTC_ASSERT(!(m_startPosition == -1 && completionItems.size() > 0), return);
if (completionItems.isEmpty()) { if (completionItems.isEmpty()) {
cleanupCompletions(); cleanupCompletions();

View File

@@ -396,7 +396,8 @@ void Adapter::handleGdbResponse(const QByteArray &response)
else if (response == "!") { else if (response == "!") {
sendGdbAckMessage(); sendGdbAckMessage();
sendGdbMessage("OK", "extended mode enabled"); sendGdbMessage("", "extended mode not enabled");
//sendGdbMessage("OK", "extended mode enabled");
} }
else if (response.startsWith("?")) { else if (response.startsWith("?")) {
@@ -537,7 +538,11 @@ void Adapter::handleGdbResponse(const QByteArray &response)
#endif #endif
bool ok = false; bool ok = false;
uint registerNumber = response.mid(1).toInt(&ok, 16); uint registerNumber = response.mid(1).toInt(&ok, 16);
if (registerNumber < RegisterCount) { if (registerNumber == RegisterPSGdb) {
QByteArray ba;
appendInt(&ba, m_snapshot.registers[RegisterPSTrk]);
sendGdbMessage(ba.toHex(), "read processor status register");
} else if (registerNumber < RegisterCount) {
QByteArray ba; QByteArray ba;
appendInt(&ba, m_snapshot.registers[registerNumber]); appendInt(&ba, m_snapshot.registers[registerNumber]);
sendGdbMessage(ba.toHex(), "read single known register"); sendGdbMessage(ba.toHex(), "read single known register");
@@ -641,6 +646,16 @@ void Adapter::handleGdbResponse(const QByteArray &response)
// // vCont[;action[:thread-id]]...' // // vCont[;action[:thread-id]]...'
//} //}
else if (response.startsWith("vKill")) {
// kill
sendGdbAckMessage();
QByteArray ba;
appendByte(&ba, 0); // Sub-command: Delete Process
appendInt(&ba, m_session.pid);
sendTrkMessage(0x41, 0, ba, "Delete process"); // Delete Item
sendGdbMessageAfterSync("", "process killed");
}
else { else {
logMessage("FIXME unknown: " + response); logMessage("FIXME unknown: " + response);
} }
@@ -882,7 +897,8 @@ void Adapter::handleResult(const TrkResult &result)
// uint tid = extractInt(data + 8); // ThreadID: 4 bytes // uint tid = extractInt(data + 8); // ThreadID: 4 bytes
//logMessage(prefix << " ADDR: " << addr << " PID: " << pid << " TID: " << tid); //logMessage(prefix << " ADDR: " << addr << " PID: " << pid << " TID: " << tid);
sendTrkAck(result.token); sendTrkAck(result.token);
sendGdbMessage("S11", "Target stopped"); //sendGdbMessage("S11", "Target stopped");
sendGdbMessage("S05", "Target stopped");
break; break;
} }
case 0x91: { // Notify Exception (obsolete) case 0x91: { // Notify Exception (obsolete)
@@ -1059,8 +1075,10 @@ void Adapter::handleAndReportReadRegisters(const TrkResult &result)
// [80 0B 00 00 00 00 00 C9 24 FF BC 00 00 00 00 00 // [80 0B 00 00 00 00 00 C9 24 FF BC 00 00 00 00 00
// 60 00 00 00 00 00 00 78 67 79 70 00 00 00 00 00...] // 60 00 00 00 00 00 00 78 67 79 70 00 00 00 00 00...]
const char *data = result.data.data(); const char *data = result.data.data();
for (int i = 0; i < RegisterCount; ++i) for (int i = 0; i < RegisterCount; ++i) {
m_snapshot.registers[i] = extractInt(data + 4 * i); m_snapshot.registers[i] = extractInt(data + 4 * i);
//qDebug() << i << hexNumber(m_snapshot.registers[i], 8);
}
//QByteArray ba = result.data.toHex(); //QByteArray ba = result.data.toHex();
QByteArray ba; QByteArray ba;

View File

@@ -10,6 +10,7 @@ trkservername="TRKSERVER-${userid}";
gdbserverip=127.0.0.1 gdbserverip=127.0.0.1
gdbserverport=$[2222 + ${userid}] gdbserverport=$[2222 + ${userid}]
memorydump=TrkDump-78-6a-40-00.bin memorydump=TrkDump-78-6a-40-00.bin
memorydump=TrkDump-78-6a-40-00-BigEndian.bin
fuser -n tcp -k ${gdbserverport} fuser -n tcp -k ${gdbserverport}
rm /tmp/${trkservername} rm /tmp/${trkservername}

View File

@@ -0,0 +1,23 @@
#include <QtCore>
int main(int argc, char *argv[])
{
QFile file1(argv[1]);
file1.open(QIODevice::ReadOnly);
QByteArray ba = file1.readAll();
file1.close();
for (int i = 0; i < ba.size(); i += 4) {
char c = ba[i]; ba[i] = ba[i + 3]; ba[i + 3] = c;
c = ba[i + 1]; ba[i + 1] = ba[i + 2]; ba[i + 2] = c;
}
QFile file2(argv[2]);
file2.open(QIODevice::WriteOnly);
file2.write(ba);
file2.close();
}

View File

@@ -0,0 +1,9 @@
TEMPLATE = app
QT = core
HEADERS += \
SOURCES += \
swapendian.cpp

View File

@@ -1,7 +1,8 @@
TEMPLATE = subdirs TEMPLATE = subdirs
SUBDIRS = trkserver adapter SUBDIRS = trkserver adapter swapendian
trkserver.file = trkserver.pro trkserver.file = trkserver.pro
adapter.file = adapter.pro adapter.file = adapter.pro
swapendian.file = swapendian.pro

View File

@@ -88,13 +88,13 @@ Inferior::Inferior()
registers[7] = 0x00000000; registers[7] = 0x00000000;
registers[8] = 0x00000012; registers[8] = 0x00000012;
registers[9] = 0x00000040; registers[9] = 0x00000040;
registers[10] = 0xC82AF210; registers[10] = 0xC82AF210;
registers[11] = 0x00000000; registers[11] = 0x00000000;
registers[12] = 0xC8000548; registers[12] = 0xC8000548;
registers[13] = 0x00403ED0; registers[13] = 0x00403ED0;
registers[14] = 0x786A6BD8; registers[14] = 0x786A6BD8;
registers[15] = 0x786A4CC8; registers[15] = 0x786A4CC8;
//registers[25] = 0x68000010; registers[16] = 0x68000010; // that's reg 25 on chip?
} }
class TrkServer : public QObject class TrkServer : public QObject
@@ -238,9 +238,7 @@ void TrkServer::handleAdapterMessage(const TrkResult &result)
break; break;
} }
case 0x12: { // Read Registers case 0x12: { // Read Registers
appendByte(&data, 0x00); data.clear();
appendByte(&data, 0x00);
appendByte(&data, 0x00);
for (int i = 0; i < RegisterCount; ++i) for (int i = 0; i < RegisterCount; ++i)
appendInt(&data, m_inferior.registers[i], BigEndian); appendInt(&data, m_inferior.registers[i], BigEndian);
writeToAdapter(0x80, result.token, data); writeToAdapter(0x80, result.token, data);

View File

@@ -72,8 +72,11 @@ enum CodeMode
enum TargetConstants enum TargetConstants
{ {
RegisterCount = 16, RegisterCount = 17,
RegisterPC = 15, // Program counter RegisterPC = 15, // Program counter
RegisterPSGdb = 25, // gdb's view of the world
RegisterPSTrk = 16, // gdb's view of the world
MemoryChunkSize = 256 MemoryChunkSize = 256
}; };