forked from qt-creator/qt-creator
Merge branch 'master' of git@scm.dev.nokia.troll.no:creator/mainline
This commit is contained in:
4
dist/changes-1.3.0
vendored
4
dist/changes-1.3.0
vendored
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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(¤tThreadId);
|
||||||
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()
|
||||||
|
@@ -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();
|
||||||
|
|
||||||
|
@@ -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,
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
{
|
{
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -103,6 +103,7 @@ private:
|
|||||||
|
|
||||||
struct ThreadData
|
struct ThreadData
|
||||||
{
|
{
|
||||||
|
ThreadData(int threadId = 0) : id(threadId) {}
|
||||||
int id;
|
int id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
||||||
|
@@ -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;
|
||||||
|
@@ -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}
|
||||||
|
23
tests/manual/trk/swapendian.cpp
Normal file
23
tests/manual/trk/swapendian.cpp
Normal 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();
|
||||||
|
}
|
||||||
|
|
9
tests/manual/trk/swapendian.pro
Normal file
9
tests/manual/trk/swapendian.pro
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
TEMPLATE = app
|
||||||
|
|
||||||
|
QT = core
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
swapendian.cpp
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
|
@@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user