forked from qt-creator/qt-creator
Debugger[New CDB]: Get rid of postfix '2' in file names/classes.
This commit is contained in:
126
src/plugins/debugger/cdb/bytearrayinputstream.cpp
Normal file
126
src/plugins/debugger/cdb/bytearrayinputstream.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** No Commercial Usage
|
||||
**
|
||||
** This file contains pre-release code and may not be distributed.
|
||||
** You may use this file in accordance with the terms and conditions
|
||||
** contained in the Technology Preview License Agreement accompanying
|
||||
** this package.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "bytearrayinputstream.h"
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
ByteArrayInputStream::ByteArrayInputStream(QByteArray &ba) :
|
||||
m_target(ba), m_integerBase(10), m_hexPrefix(false), m_width(0)
|
||||
{
|
||||
}
|
||||
|
||||
void ByteArrayInputStream::appendSeparator(char c)
|
||||
{
|
||||
if (!m_target.isEmpty() && !m_target.endsWith(c))
|
||||
m_target.append(c);
|
||||
}
|
||||
|
||||
void hexPrefixOn(ByteArrayInputStream &bs)
|
||||
{
|
||||
bs.setHexPrefix(true);
|
||||
}
|
||||
|
||||
void hexPrefixOff(ByteArrayInputStream &bs)
|
||||
{
|
||||
bs.setHexPrefix(false);
|
||||
}
|
||||
|
||||
void hex(ByteArrayInputStream &bs)
|
||||
{
|
||||
bs.setIntegerBase(16);
|
||||
}
|
||||
|
||||
void dec(ByteArrayInputStream &bs)
|
||||
{
|
||||
bs.setIntegerBase(10);
|
||||
}
|
||||
|
||||
void blankSeparator(ByteArrayInputStream &bs)
|
||||
{
|
||||
bs.appendSeparator();
|
||||
}
|
||||
|
||||
QByteArray trimFront(QByteArray in)
|
||||
{
|
||||
if (in.isEmpty())
|
||||
return in;
|
||||
const int size = in.size();
|
||||
int pos = 0;
|
||||
for ( ; pos < size && isspace(in.at(pos)); pos++) ;
|
||||
if (pos)
|
||||
in.remove(0, pos);
|
||||
return in;
|
||||
}
|
||||
|
||||
QByteArray trimBack(QByteArray in)
|
||||
{
|
||||
if (in.isEmpty())
|
||||
return in;
|
||||
const int size = in.size();
|
||||
int pos = size - 1;
|
||||
for ( ; pos >= 0 && isspace(in.at(pos)); pos--) ;
|
||||
if (pos != size - 1)
|
||||
in.truncate(pos + 1);
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
// Simplify: replace tabs, find all occurrences
|
||||
// of 2 blanks, check further up for blanks and remove that bit.
|
||||
QByteArray simplify(const QByteArray &inIn)
|
||||
{
|
||||
if (inIn.isEmpty())
|
||||
return inIn;
|
||||
QByteArray in = trimFront(trimBack(inIn));
|
||||
in.replace('\t', ' ');
|
||||
in.replace('\n', ' ');
|
||||
in.replace('\r', ' ');
|
||||
const QByteArray twoBlanks = " ";
|
||||
while (true) {
|
||||
const int pos = in.indexOf(twoBlanks);
|
||||
if (pos != -1) {
|
||||
const int size = in.size();
|
||||
int endPos = pos + twoBlanks.size();
|
||||
for ( ; endPos < size && in.at(endPos) == ' '; endPos++) ;
|
||||
in.remove(pos + 1, endPos - pos - 1);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
112
src/plugins/debugger/cdb/bytearrayinputstream.h
Normal file
112
src/plugins/debugger/cdb/bytearrayinputstream.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** No Commercial Usage
|
||||
**
|
||||
** This file contains pre-release code and may not be distributed.
|
||||
** You may use this file in accordance with the terms and conditions
|
||||
** contained in the Technology Preview License Agreement accompanying
|
||||
** this package.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef BYTEARRAYINPUTSTREAM_H
|
||||
#define BYTEARRAYINPUTSTREAM_H
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QString>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class ByteArrayInputStream
|
||||
{
|
||||
Q_DISABLE_COPY(ByteArrayInputStream)
|
||||
public:
|
||||
typedef void (ModifierFunc)(ByteArrayInputStream &s);
|
||||
|
||||
explicit ByteArrayInputStream(QByteArray &ba);
|
||||
|
||||
ByteArrayInputStream &operator<<(char a) { m_target.append(a); return *this; }
|
||||
ByteArrayInputStream &operator<<(const QByteArray &a) { m_target.append(a); return *this; }
|
||||
ByteArrayInputStream &operator<<(const char *a) { m_target.append(a); return *this; }
|
||||
ByteArrayInputStream &operator<<(const QString &a) { m_target.append(a.toLatin1()); return *this; }
|
||||
|
||||
ByteArrayInputStream &operator<<(int i) { appendInt(i); return *this; }
|
||||
ByteArrayInputStream &operator<<(unsigned i) { appendInt(i); return *this; }
|
||||
ByteArrayInputStream &operator<<(quint64 i) { appendInt(i); return *this; }
|
||||
ByteArrayInputStream &operator<<(qint64 i) { appendInt(i); return *this; }
|
||||
|
||||
// Stream a modifier by invoking it
|
||||
ByteArrayInputStream &operator<<(ModifierFunc mf) { mf(*this); return *this; }
|
||||
|
||||
void setHexPrefix(bool hp) { m_hexPrefix = hp; }
|
||||
bool hexPrefix() const { return m_hexPrefix; }
|
||||
void setIntegerBase(int b) { m_integerBase = b; }
|
||||
int integerBase() const { return m_integerBase; }
|
||||
// Append a separator if required (target does not end with it)
|
||||
void appendSeparator(char c = ' ');
|
||||
|
||||
private:
|
||||
template <class IntType> void appendInt(IntType i);
|
||||
|
||||
QByteArray &m_target;
|
||||
int m_integerBase;
|
||||
bool m_hexPrefix;
|
||||
int m_width;
|
||||
};
|
||||
|
||||
template <class IntType>
|
||||
void ByteArrayInputStream::appendInt(IntType i)
|
||||
{
|
||||
const bool hexPrefix = m_integerBase == 16 && m_hexPrefix;
|
||||
if (hexPrefix)
|
||||
m_target.append("0x");
|
||||
const QByteArray n = QByteArray::number(i, m_integerBase);
|
||||
if (m_width > 0) {
|
||||
int pad = m_width - n.size();
|
||||
if (hexPrefix)
|
||||
pad -= 2;
|
||||
if (pad > 0)
|
||||
m_target.append(QByteArray(pad, '0'));
|
||||
}
|
||||
m_target.append(n);
|
||||
}
|
||||
|
||||
// Streamable modifiers for ByteArrayInputStream
|
||||
void hexPrefixOn(ByteArrayInputStream &bs);
|
||||
void hexPrefixOff(ByteArrayInputStream &bs);
|
||||
void hex(ByteArrayInputStream &bs);
|
||||
void dec(ByteArrayInputStream &bs);
|
||||
void blankSeparator(ByteArrayInputStream &bs);
|
||||
|
||||
// Bytearray parse helpers
|
||||
QByteArray trimFront(QByteArray in);
|
||||
QByteArray trimBack(QByteArray in);
|
||||
QByteArray simplify(const QByteArray &inIn);
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // BYTEARRAYINPUTSTREAM_H
|
||||
16
src/plugins/debugger/cdb/cdb.pri
Normal file
16
src/plugins/debugger/cdb/cdb.pri
Normal file
@@ -0,0 +1,16 @@
|
||||
HEADERS += $$PWD/cdbengine.h \
|
||||
cdb/bytearrayinputstream.h \
|
||||
cdb/cdbparsehelpers.h \
|
||||
cdb/cdboptions.h \
|
||||
cdb/cdboptionspage.h
|
||||
|
||||
SOURCES += $$PWD/cdbengine.cpp \
|
||||
cdb/bytearrayinputstream.cpp \
|
||||
cdb/cdbparsehelpers.cpp \
|
||||
cdb/cdboptions.cpp \
|
||||
cdb/cdboptionspage.cpp
|
||||
|
||||
FORMS += cdb/cdboptionspagewidget.ui
|
||||
|
||||
INCLUDEPATH*=$$PWD
|
||||
DEPENDPATH*=$$PWD
|
||||
1988
src/plugins/debugger/cdb/cdbengine.cpp
Normal file
1988
src/plugins/debugger/cdb/cdbengine.cpp
Normal file
File diff suppressed because it is too large
Load Diff
215
src/plugins/debugger/cdb/cdbengine.h
Normal file
215
src/plugins/debugger/cdb/cdbengine.h
Normal file
@@ -0,0 +1,215 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** No Commercial Usage
|
||||
**
|
||||
** This file contains pre-release code and may not be distributed.
|
||||
** You may use this file in accordance with the terms and conditions
|
||||
** contained in the Technology Preview License Agreement accompanying
|
||||
** this package.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef DEBUGGER_CDBENGINE_H
|
||||
#define DEBUGGER_CDBENGINE_H
|
||||
|
||||
#include "debuggerengine.h"
|
||||
|
||||
#include <QtCore/QSharedPointer>
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QTime>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class DisassemblerAgent;
|
||||
struct CdbBuiltinCommand;
|
||||
struct CdbExtensionCommand;
|
||||
struct CdbOptions;
|
||||
class ByteArrayInputStream;
|
||||
|
||||
class CdbEngine : public Debugger::DebuggerEngine
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
typedef QSharedPointer<CdbOptions> OptionsPtr;
|
||||
|
||||
enum CommandFlags { QuietCommand = 0x1 };
|
||||
// Flag bits for a sequence of commands
|
||||
enum CommandSequenceFlags {
|
||||
CommandListStack = 0x1,
|
||||
CommandListThreads = 0x2,
|
||||
CommandListRegisters = 0x4,
|
||||
CommandListModules = 0x8
|
||||
};
|
||||
|
||||
typedef QSharedPointer<CdbBuiltinCommand> CdbBuiltinCommandPtr;
|
||||
typedef QSharedPointer<CdbExtensionCommand> CdbExtensionCommandPtr;
|
||||
typedef void (CdbEngine::*BuiltinCommandHandler)(const CdbBuiltinCommandPtr &);
|
||||
typedef void (CdbEngine::*ExtensionCommandHandler)(const CdbExtensionCommandPtr &);
|
||||
|
||||
explicit CdbEngine(const DebuggerStartParameters &sp, const OptionsPtr &options);
|
||||
virtual ~CdbEngine();
|
||||
// Factory function that returns 0 if the debug engine library cannot be found.
|
||||
|
||||
virtual void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos);
|
||||
virtual void setupEngine();
|
||||
virtual void setupInferior();
|
||||
virtual void runEngine();
|
||||
virtual void shutdownInferior();
|
||||
virtual void shutdownEngine();
|
||||
virtual void detachDebugger();
|
||||
virtual void updateWatchData(const WatchData &data,
|
||||
const WatchUpdateFlags & flags = WatchUpdateFlags());
|
||||
virtual unsigned debuggerCapabilities() const;
|
||||
virtual void setRegisterValue(int regnr, const QString &value);
|
||||
|
||||
virtual void executeStep();
|
||||
virtual void executeStepOut();
|
||||
virtual void executeNext();
|
||||
virtual void executeStepI();
|
||||
virtual void executeNextI();
|
||||
|
||||
virtual void continueInferior();
|
||||
virtual void interruptInferior();
|
||||
|
||||
virtual void executeRunToLine(const QString &fileName, int lineNumber);
|
||||
virtual void executeRunToFunction(const QString &functionName);
|
||||
virtual void executeJumpToLine(const QString &fileName, int lineNumber);
|
||||
virtual void assignValueInDebugger(const WatchData *w, const QString &expr, const QVariant &value);
|
||||
virtual void executeDebuggerCommand(const QString &command);
|
||||
|
||||
virtual void activateFrame(int index);
|
||||
virtual void selectThread(int index);
|
||||
|
||||
virtual bool stateAcceptsBreakpointChanges() const;
|
||||
virtual bool acceptsBreakpoint(BreakpointId id) const;
|
||||
virtual void attemptBreakpointSynchronization();
|
||||
|
||||
virtual void fetchDisassembler(DisassemblerAgent *agent);
|
||||
virtual void fetchMemory(MemoryAgent *, QObject *, quint64 addr, quint64 length);
|
||||
|
||||
virtual void reloadModules();
|
||||
virtual void loadSymbols(const QString &moduleName);
|
||||
virtual void loadAllSymbols();
|
||||
virtual void requestModuleSymbols(const QString &moduleName);
|
||||
|
||||
virtual void reloadRegisters();
|
||||
virtual void reloadSourceFiles();
|
||||
virtual void reloadFullStack();
|
||||
|
||||
static QString extensionLibraryName(bool is64Bit);
|
||||
|
||||
private slots:
|
||||
void readyReadStandardOut();
|
||||
void readyReadStandardError();
|
||||
void processError();
|
||||
void processFinished();
|
||||
void postCommand(const QByteArray &cmd, unsigned flags);
|
||||
void postBuiltinCommand(const QByteArray &cmd,
|
||||
unsigned flags,
|
||||
BuiltinCommandHandler handler,
|
||||
unsigned nextCommandFlag = 0,
|
||||
const QVariant &cookie = QVariant());
|
||||
|
||||
void postExtensionCommand(const QByteArray &cmd,
|
||||
const QByteArray &arguments,
|
||||
unsigned flags,
|
||||
ExtensionCommandHandler handler,
|
||||
unsigned nextCommandFlag = 0,
|
||||
const QVariant &cookie = QVariant());
|
||||
|
||||
void postCommandSequence(unsigned mask);
|
||||
void operateByInstructionTriggered(bool);
|
||||
|
||||
private:
|
||||
enum SpecialStopMode { NoSpecialStop, SpecialStopSynchronizeBreakpoints };
|
||||
|
||||
bool commandsPending() const;
|
||||
void handleExtensionMessage(char t, int token, const QByteArray &what, const QByteArray &message);
|
||||
bool doSetupEngine(QString *errorMessage);
|
||||
void handleSessionAccessible(unsigned long cdbExState);
|
||||
void handleSessionInaccessible(unsigned long cdbExState);
|
||||
void handleSessionIdle(const QByteArray &message);
|
||||
void doInterruptInferior(SpecialStopMode sm);
|
||||
void doContinueInferior();
|
||||
inline void parseOutputLine(QByteArray line);
|
||||
inline bool isCdbProcessRunning() const { return m_process.state() != QProcess::NotRunning; }
|
||||
bool canInterruptInferior() const;
|
||||
void syncOperateByInstruction(bool operateByInstruction);
|
||||
|
||||
// Builtin commands
|
||||
void dummyHandler(const CdbBuiltinCommandPtr &);
|
||||
void handleStackTrace(const CdbExtensionCommandPtr &);
|
||||
void handleRegisters(const CdbBuiltinCommandPtr &);
|
||||
void handleDisassembler(const CdbBuiltinCommandPtr &);
|
||||
void handleJumpToLineAddressResolution(const CdbBuiltinCommandPtr &);
|
||||
// Extension commands
|
||||
void handleThreads(const CdbExtensionCommandPtr &);
|
||||
void handlePid(const CdbExtensionCommandPtr &reply);
|
||||
void handleLocals(const CdbExtensionCommandPtr &reply);
|
||||
void handleExpandLocals(const CdbExtensionCommandPtr &reply);
|
||||
void handleRegisters(const CdbExtensionCommandPtr &reply);
|
||||
void handleModules(const CdbExtensionCommandPtr &reply);
|
||||
void handleMemory(const CdbExtensionCommandPtr &);
|
||||
|
||||
QString normalizeFileName(const QString &f);
|
||||
void updateLocalVariable(const QByteArray &iname);
|
||||
int elapsedLogTime() const;
|
||||
void addLocalsOptions(ByteArrayInputStream &s) const;
|
||||
|
||||
const QByteArray m_creatorExtPrefix;
|
||||
const QByteArray m_tokenPrefix;
|
||||
const OptionsPtr m_options;
|
||||
|
||||
QProcess m_process;
|
||||
QByteArray m_outputBuffer;
|
||||
unsigned long m_inferiorPid;
|
||||
// Debugger accessible (expecting commands)
|
||||
bool m_accessible;
|
||||
SpecialStopMode m_specialStopMode;
|
||||
int m_nextCommandToken;
|
||||
int m_nextBreakpointNumber;
|
||||
QList<CdbBuiltinCommandPtr> m_builtinCommandQueue;
|
||||
int m_currentBuiltinCommandIndex; // Current command whose output is recorded.
|
||||
QList<CdbExtensionCommandPtr> m_extensionCommandQueue;
|
||||
QMap<QString, QString> m_normalizedFileCache;
|
||||
const QByteArray m_extensionCommandPrefixBA; // Library name used as prefix
|
||||
bool m_operateByInstructionPending; // Creator operate by instruction action changed.
|
||||
bool m_operateByInstruction;
|
||||
bool m_notifyEngineShutdownOnTermination;
|
||||
bool m_hasDebuggee;
|
||||
QTime m_logTime;
|
||||
mutable int m_elapsedLogTime;
|
||||
QByteArray m_extensionMessageBuffer;
|
||||
bool m_sourceStepInto;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_CDBENGINE_H
|
||||
231
src/plugins/debugger/cdb/cdboptions.cpp
Normal file
231
src/plugins/debugger/cdb/cdboptions.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** No Commercial Usage
|
||||
**
|
||||
** This file contains pre-release code and may not be distributed.
|
||||
** You may use this file in accordance with the terms and conditions
|
||||
** contained in the Technology Preview License Agreement accompanying
|
||||
** this package.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "cdboptions.h"
|
||||
#include "cdbengine.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
# include <utils/winutils.h>
|
||||
#endif
|
||||
|
||||
#include <QtCore/QSettings>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QCoreApplication>
|
||||
|
||||
static const char settingsGroupC[] = "CDB2";
|
||||
static const char enabledKeyC[] = "Enabled";
|
||||
static const char pathKeyC[] = "Path";
|
||||
static const char symbolPathsKeyC[] = "SymbolPaths";
|
||||
static const char sourcePathsKeyC[] = "SourcePaths";
|
||||
static const char breakEventKeyC[] = "BreakEvent";
|
||||
static const char is64bitKeyC[] = "64bit";
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
CdbOptions::CdbOptions() :
|
||||
enabled(false), is64bit(false)
|
||||
{
|
||||
}
|
||||
|
||||
QString CdbOptions::settingsGroup()
|
||||
{
|
||||
return QLatin1String(settingsGroupC);
|
||||
}
|
||||
|
||||
void CdbOptions::clearExecutable()
|
||||
{
|
||||
is64bit = enabled = false;
|
||||
executable.clear();
|
||||
}
|
||||
|
||||
void CdbOptions::clear()
|
||||
{
|
||||
clearExecutable();
|
||||
symbolPaths.clear();
|
||||
sourcePaths.clear();
|
||||
}
|
||||
|
||||
static inline QString msgAutoDetectFail(bool is64Bit, const QString &executable,
|
||||
const QString &extLib)
|
||||
{
|
||||
return QCoreApplication::translate("Debugger::Cdb::CdbOptions",
|
||||
"Auto-detection of the new CDB debugging engine (%1bit) failed:\n"
|
||||
"Debugger executable: %2\n"
|
||||
"Extension library : %3 not present.\n").arg(is64Bit ? 64 : 32).
|
||||
arg(QDir::toNativeSeparators(executable), QDir::toNativeSeparators(extLib));
|
||||
}
|
||||
|
||||
static inline QString msgAutoDetect(bool is64Bit, const QString &executable,
|
||||
const QString &extLib,
|
||||
const QStringList &symbolPaths)
|
||||
{
|
||||
return QCoreApplication::translate("Debugger::Cdb::CdbOptions",
|
||||
"The new CDB debugging engine (%1bit) has been set up automatically:\n"
|
||||
"Debugger executable: %2\n"
|
||||
"Extension library : %3\n"
|
||||
"Symbol paths : %4\n").arg(is64Bit ? 64 : 32).
|
||||
arg(QDir::toNativeSeparators(executable), QDir::toNativeSeparators(extLib),
|
||||
symbolPaths.join(QString(QLatin1Char(';'))));
|
||||
}
|
||||
|
||||
QStringList CdbOptions::oldEngineSymbolPaths(const QSettings *s)
|
||||
{
|
||||
return s->value(QLatin1String("CDB/SymbolPaths")).toStringList();
|
||||
}
|
||||
|
||||
bool CdbOptions::autoDetect(const QSettings *s)
|
||||
{
|
||||
QString autoExecutable;
|
||||
bool auto64Bit;
|
||||
// Check installation and existence of the extension library
|
||||
CdbOptions::autoDetectExecutable(&autoExecutable, &auto64Bit);
|
||||
if (autoExecutable.isEmpty())
|
||||
return false;
|
||||
const QString extLib = CdbEngine::extensionLibraryName(auto64Bit);
|
||||
if (!QFileInfo(extLib).isFile()) {
|
||||
const QString failMsg = msgAutoDetectFail(auto64Bit, autoExecutable, extLib);
|
||||
qWarning("%s", qPrintable(failMsg));
|
||||
clearExecutable();
|
||||
return false;
|
||||
}
|
||||
enabled = true;
|
||||
is64bit = auto64Bit;
|
||||
executable = autoExecutable;
|
||||
// Is there a symbol path from an old install? Use that
|
||||
if (symbolPaths.empty())
|
||||
symbolPaths = CdbOptions::oldEngineSymbolPaths(s);
|
||||
const QString msg = msgAutoDetect(is64bit, QDir::toNativeSeparators(executable),
|
||||
QDir::toNativeSeparators(extLib), symbolPaths);
|
||||
qWarning("%s", qPrintable(msg));
|
||||
return true;
|
||||
}
|
||||
|
||||
void CdbOptions::fromSettings(QSettings *s)
|
||||
{
|
||||
clear();
|
||||
// Is this the first time we are called ->
|
||||
// try to find automatically
|
||||
const QString keyRoot = QLatin1String(settingsGroupC) + QLatin1Char('/');
|
||||
const QString enabledKey = keyRoot + QLatin1String(enabledKeyC);
|
||||
// First-time autodetection: Write back parameters
|
||||
const bool firstTime = !s->contains(enabledKey);
|
||||
if (firstTime && autoDetect(s)) {
|
||||
toSettings(s);
|
||||
return;
|
||||
}
|
||||
enabled = s->value(enabledKey, false).toBool();
|
||||
is64bit = s->value(keyRoot + QLatin1String(is64bitKeyC), is64bit).toBool();
|
||||
executable = s->value(keyRoot + QLatin1String(pathKeyC), executable).toString();
|
||||
symbolPaths = s->value(keyRoot + QLatin1String(symbolPathsKeyC), QStringList()).toStringList();
|
||||
sourcePaths = s->value(keyRoot + QLatin1String(sourcePathsKeyC), QStringList()).toStringList();
|
||||
breakEvents = s->value(keyRoot + QLatin1String(breakEventKeyC), QStringList()).toStringList();
|
||||
}
|
||||
|
||||
void CdbOptions::toSettings(QSettings *s) const
|
||||
{
|
||||
s->beginGroup(QLatin1String(settingsGroupC));
|
||||
s->setValue(QLatin1String(enabledKeyC), enabled);
|
||||
s->setValue(QLatin1String(pathKeyC), executable);
|
||||
s->setValue(QLatin1String(is64bitKeyC), is64bit);
|
||||
s->setValue(QLatin1String(symbolPathsKeyC), symbolPaths);
|
||||
s->setValue(QLatin1String(sourcePathsKeyC), sourcePaths);
|
||||
s->setValue(QLatin1String(breakEventKeyC), breakEvents);
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
bool CdbOptions::equals(const CdbOptions &rhs) const
|
||||
{
|
||||
return enabled == rhs.enabled && is64bit == rhs.is64bit
|
||||
&& executable == rhs.executable
|
||||
&& symbolPaths == rhs.symbolPaths
|
||||
&& sourcePaths == rhs.sourcePaths
|
||||
&& breakEvents == rhs.breakEvents;
|
||||
}
|
||||
|
||||
bool CdbOptions::autoDetectExecutable(QString *outPath, bool *is64bitIn /* = 0 */,
|
||||
QStringList *checkedDirectories /* = 0 */)
|
||||
{
|
||||
// Look for $ProgramFiles/"Debugging Tools For Windows <bit-idy>/cdb.exe" and its
|
||||
// " (x86)", " (x64)" variations.
|
||||
static const char *postFixes[] = {" (x64)", " 64-bit", " (x86)", " (x32)" };
|
||||
enum { first32bitIndex = 2 };
|
||||
|
||||
if (checkedDirectories)
|
||||
checkedDirectories->clear();
|
||||
|
||||
outPath->clear();
|
||||
const QByteArray programDirB = qgetenv("ProgramFiles");
|
||||
if (programDirB.isEmpty())
|
||||
return false;
|
||||
|
||||
const QString programDir = QString::fromLocal8Bit(programDirB) + QLatin1Char('/');
|
||||
const QString installDir = QLatin1String("Debugging Tools For Windows");
|
||||
const QString executable = QLatin1String("/cdb.exe");
|
||||
|
||||
QString path = programDir + installDir;
|
||||
if (checkedDirectories)
|
||||
checkedDirectories->push_back(path);
|
||||
const QFileInfo fi(path + executable);
|
||||
// Plain system installation
|
||||
if (fi.isFile() && fi.isExecutable()) {
|
||||
*outPath = fi.absoluteFilePath();
|
||||
if (is64bitIn)
|
||||
#ifdef Q_OS_WIN
|
||||
*is64bitIn = Utils::winIs64BitSystem();
|
||||
#else
|
||||
*is64bitIn = false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
// Try the post fixes
|
||||
const int rootLength = path.size();
|
||||
for (unsigned i = 0; i < sizeof(postFixes)/sizeof(const char*); i++) {
|
||||
path.truncate(rootLength);
|
||||
path += QLatin1String(postFixes[i]);
|
||||
if (checkedDirectories)
|
||||
checkedDirectories->push_back(path);
|
||||
const QFileInfo fi2(path + executable);
|
||||
if (fi2.isFile() && fi2.isExecutable()) {
|
||||
if (is64bitIn)
|
||||
*is64bitIn = i < first32bitIndex;
|
||||
*outPath = fi2.absoluteFilePath();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
85
src/plugins/debugger/cdb/cdboptions.h
Normal file
85
src/plugins/debugger/cdb/cdboptions.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** No Commercial Usage
|
||||
**
|
||||
** This file contains pre-release code and may not be distributed.
|
||||
** You may use this file in accordance with the terms and conditions
|
||||
** contained in the Technology Preview License Agreement accompanying
|
||||
** this package.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CDBSETTINGS_H
|
||||
#define CDBSETTINGS_H
|
||||
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QSettings;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
struct CdbOptions
|
||||
{
|
||||
public:
|
||||
CdbOptions();
|
||||
|
||||
bool isValid() const { return enabled && !executable.isEmpty(); }
|
||||
|
||||
void clearExecutable();
|
||||
void clear();
|
||||
|
||||
void fromSettings(QSettings *s); // Writes parameters on first-time autodetect
|
||||
bool autoDetect(const QSettings *s);
|
||||
void toSettings(QSettings *s) const;
|
||||
|
||||
bool equals(const CdbOptions &rhs) const;
|
||||
|
||||
static bool autoDetectExecutable(QString *outPath, bool *is64bit = 0,
|
||||
QStringList *checkedDirectories = 0);
|
||||
|
||||
static QString settingsGroup();
|
||||
static QStringList oldEngineSymbolPaths(const QSettings *s);
|
||||
|
||||
bool enabled;
|
||||
bool is64bit;
|
||||
QString executable;
|
||||
QStringList symbolPaths;
|
||||
QStringList sourcePaths;
|
||||
// Events to break on (Command 'sxe' with abbreviation and optional parameter)
|
||||
QStringList breakEvents;
|
||||
};
|
||||
|
||||
inline bool operator==(const CdbOptions &s1, const CdbOptions &s2)
|
||||
{ return s1.equals(s2); }
|
||||
inline bool operator!=(const CdbOptions &s1, const CdbOptions &s2)
|
||||
{ return !s1.equals(s2); }
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // CDBSETTINGS_H
|
||||
450
src/plugins/debugger/cdb/cdboptionspage.cpp
Normal file
450
src/plugins/debugger/cdb/cdboptionspage.cpp
Normal file
@@ -0,0 +1,450 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** No Commercial Usage
|
||||
**
|
||||
** This file contains pre-release code and may not be distributed.
|
||||
** You may use this file in accordance with the terms and conditions
|
||||
** contained in the Technology Preview License Agreement accompanying
|
||||
** this package.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "cdboptionspage.h"
|
||||
#include "cdboptions.h"
|
||||
#include "debuggerconstants.h"
|
||||
#include "cdbengine.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
# include <utils/winutils.h>
|
||||
#endif
|
||||
#include <utils/synchronousprocess.h>
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QTextStream>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtGui/QMessageBox>
|
||||
#include <QtGui/QLineEdit>
|
||||
#include <QtGui/QDesktopServices>
|
||||
|
||||
static const char *dgbToolsDownloadLink32C = "http://www.microsoft.com/whdc/devtools/debugging/installx86.Mspx";
|
||||
static const char *dgbToolsDownloadLink64C = "http://www.microsoft.com/whdc/devtools/debugging/install64bit.Mspx";
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
struct EventsDescription {
|
||||
const char *abbreviation;
|
||||
bool hasParameter;
|
||||
const char *description;
|
||||
};
|
||||
|
||||
// Parameters of the "sxe" command
|
||||
const EventsDescription eventDescriptions[] =
|
||||
{
|
||||
{"eh", false, QT_TRANSLATE_NOOP("Debugger::Cdb::CdbBreakEventWidget",
|
||||
"C++ exception")},
|
||||
{"ct", false, QT_TRANSLATE_NOOP("Debugger::Cdb::CdbBreakEventWidget",
|
||||
"Thread creation")},
|
||||
{"et", false, QT_TRANSLATE_NOOP("Debugger::Cdb::CdbBreakEventWidget",
|
||||
"Thread exit")},
|
||||
{"ld", true, QT_TRANSLATE_NOOP("Debugger::Cdb::CdbBreakEventWidget",
|
||||
"Load Module:")},
|
||||
{"ud", true, QT_TRANSLATE_NOOP("Debugger::Cdb::CdbBreakEventWidget",
|
||||
"Unload Module:")},
|
||||
{"out", true, QT_TRANSLATE_NOOP("Debugger::Cdb::CdbBreakEventWidget",
|
||||
"Output:")}
|
||||
};
|
||||
|
||||
static inline int indexOfEvent(const QString &abbrev)
|
||||
{
|
||||
const size_t eventCount = sizeof(eventDescriptions) / sizeof(EventsDescription);
|
||||
for (size_t e = 0; e < eventCount; e++)
|
||||
if (abbrev == QLatin1String(eventDescriptions[e].abbreviation))
|
||||
return int(e);
|
||||
return -1;
|
||||
}
|
||||
|
||||
CdbBreakEventWidget::CdbBreakEventWidget(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
// 1 column with checkboxes only,
|
||||
// further columns with checkbox + parameter
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
QVBoxLayout *leftLayout = new QVBoxLayout;
|
||||
QFormLayout *parameterLayout = 0;
|
||||
mainLayout->addLayout(leftLayout);
|
||||
const size_t eventCount = sizeof(eventDescriptions) / sizeof(EventsDescription);
|
||||
for (size_t e = 0; e < eventCount; e++) {
|
||||
QCheckBox *cb = new QCheckBox(tr(eventDescriptions[e].description));
|
||||
QLineEdit *le = 0;
|
||||
if (eventDescriptions[e].hasParameter) {
|
||||
if (!parameterLayout) {
|
||||
parameterLayout = new QFormLayout;
|
||||
mainLayout->addSpacerItem(new QSpacerItem(20, 0, QSizePolicy::MinimumExpanding, QSizePolicy::Ignored));
|
||||
mainLayout->addLayout(parameterLayout);
|
||||
}
|
||||
le = new QLineEdit;
|
||||
parameterLayout->addRow(cb, le);
|
||||
if (parameterLayout->count() >= 4) // New column
|
||||
parameterLayout = 0;
|
||||
} else {
|
||||
leftLayout->addWidget(cb);
|
||||
}
|
||||
m_checkBoxes.push_back(cb);
|
||||
m_lineEdits.push_back(le);
|
||||
}
|
||||
setLayout(mainLayout);
|
||||
}
|
||||
|
||||
void CdbBreakEventWidget::clear()
|
||||
{
|
||||
foreach (QLineEdit *l, m_lineEdits) {
|
||||
if (l)
|
||||
l->clear();
|
||||
}
|
||||
foreach (QCheckBox *c, m_checkBoxes)
|
||||
c->setChecked(false);
|
||||
}
|
||||
|
||||
void CdbBreakEventWidget::setBreakEvents(const QStringList &l)
|
||||
{
|
||||
clear();
|
||||
// Split the list of ("eh", "out:MyOutput")
|
||||
foreach (const QString &evt, l) {
|
||||
const int colonPos = evt.indexOf(QLatin1Char(':'));
|
||||
const QString abbrev = colonPos != -1 ? evt.mid(0, colonPos) : evt;
|
||||
const int index = indexOfEvent(abbrev);
|
||||
if (index != -1)
|
||||
m_checkBoxes.at(index)->setChecked(true);
|
||||
if (colonPos != -1 && m_lineEdits.at(index))
|
||||
m_lineEdits.at(index)->setText(evt.mid(colonPos + 1));
|
||||
}
|
||||
}
|
||||
|
||||
QString CdbBreakEventWidget::filterText(int i) const
|
||||
{
|
||||
return m_lineEdits.at(i) ? m_lineEdits.at(i)->text() : QString();
|
||||
}
|
||||
|
||||
QStringList CdbBreakEventWidget::breakEvents() const
|
||||
{
|
||||
// Compile a list of ("eh", "out:MyOutput")
|
||||
QStringList rc;
|
||||
const int eventCount = sizeof(eventDescriptions) / sizeof(EventsDescription);
|
||||
for (int e = 0; e < eventCount; e++) {
|
||||
if (m_checkBoxes.at(e)->isChecked()) {
|
||||
const QString filter = filterText(e);
|
||||
QString s = QLatin1String(eventDescriptions[e].abbreviation);
|
||||
if (!filter.isEmpty()) {
|
||||
s += QLatin1Char(':');
|
||||
s += filter;
|
||||
}
|
||||
rc.push_back(s);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline QString msgPathConfigNote()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
const bool is64bit = Utils::winIs64BitSystem();
|
||||
#else
|
||||
const bool is64bit = false;
|
||||
#endif
|
||||
const QString link = is64bit ? QLatin1String(dgbToolsDownloadLink64C) : QLatin1String(dgbToolsDownloadLink32C);
|
||||
//: Label text for path configuration. %2 is "x-bit version".
|
||||
return CdbOptionsPageWidget::tr(
|
||||
"<html><body><p>Specify the path to the "
|
||||
"<a href=\"%1\">Windows Console Debugger executable</a>"
|
||||
" (%2) here.</p>"
|
||||
"</body></html>").arg(link, (is64bit ? CdbOptionsPageWidget::tr("64-bit version")
|
||||
: CdbOptionsPageWidget::tr("32-bit version")));
|
||||
}
|
||||
|
||||
CdbOptionsPageWidget::CdbOptionsPageWidget(QWidget *parent) :
|
||||
QWidget(parent), m_breakEventWidget(new CdbBreakEventWidget),
|
||||
m_reportTimer(0)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
m_ui.noteLabel->setText(msgPathConfigNote());
|
||||
m_ui.noteLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
connect(m_ui.noteLabel, SIGNAL(linkActivated(QString)), this, SLOT(downLoadLinkActivated(QString)));
|
||||
|
||||
m_ui.pathChooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
|
||||
m_ui.pathChooser->addButton(tr("Autodetect"), this, SLOT(autoDetect()));
|
||||
m_ui.cdbPathGroupBox->installEventFilter(this);
|
||||
QVBoxLayout *eventLayout = new QVBoxLayout;
|
||||
eventLayout->addWidget(m_breakEventWidget);
|
||||
m_ui.eventGroupBox->setLayout(eventLayout);
|
||||
}
|
||||
|
||||
void CdbOptionsPageWidget::setOptions(CdbOptions &o)
|
||||
{
|
||||
m_ui.pathChooser->setPath(o.executable);
|
||||
m_ui.is64BitCheckBox->setChecked(o.is64bit);
|
||||
m_ui.cdbPathGroupBox->setChecked(o.enabled);
|
||||
setSymbolPaths(o.symbolPaths);
|
||||
m_ui.sourcePathListEditor->setPathList(o.sourcePaths);
|
||||
m_breakEventWidget->setBreakEvents(o.breakEvents);
|
||||
}
|
||||
|
||||
bool CdbOptionsPageWidget::is64Bit() const
|
||||
{
|
||||
return m_ui.is64BitCheckBox->isChecked();
|
||||
}
|
||||
|
||||
QString CdbOptionsPageWidget::path() const
|
||||
{
|
||||
return m_ui.pathChooser->path();
|
||||
}
|
||||
|
||||
CdbOptions CdbOptionsPageWidget::options() const
|
||||
{
|
||||
CdbOptions rc;
|
||||
rc.executable = path();
|
||||
rc.enabled = m_ui.cdbPathGroupBox->isChecked();
|
||||
rc.is64bit = is64Bit();
|
||||
rc.symbolPaths = symbolPaths();
|
||||
rc.sourcePaths = m_ui.sourcePathListEditor->pathList();
|
||||
rc.breakEvents = m_breakEventWidget->breakEvents();
|
||||
return rc;
|
||||
}
|
||||
|
||||
QStringList CdbOptionsPageWidget::symbolPaths() const
|
||||
{
|
||||
return m_ui.symbolPathListEditor->pathList();
|
||||
}
|
||||
|
||||
void CdbOptionsPageWidget::setSymbolPaths(const QStringList &s)
|
||||
{
|
||||
m_ui.symbolPathListEditor->setPathList(s);
|
||||
}
|
||||
|
||||
void CdbOptionsPageWidget::hideReportLabel()
|
||||
{
|
||||
m_ui.reportLabel->clear();
|
||||
m_ui.reportLabel->setVisible(false);
|
||||
}
|
||||
|
||||
void CdbOptionsPageWidget::autoDetect()
|
||||
{
|
||||
QString executable;
|
||||
QStringList checkedDirectories;
|
||||
bool is64bit;
|
||||
const bool ok = CdbOptions::autoDetectExecutable(&executable, &is64bit, &checkedDirectories);
|
||||
m_ui.cdbPathGroupBox->setChecked(ok);
|
||||
if (ok) {
|
||||
m_ui.is64BitCheckBox->setChecked(is64bit);
|
||||
m_ui.pathChooser->setPath(executable);
|
||||
QString report;
|
||||
// Now check for the extension library as well.
|
||||
const bool allOk = checkInstallation(executable, is64Bit(), &report);
|
||||
setReport(report, allOk);
|
||||
// On this occasion, if no symbol paths are specified, check for an
|
||||
// old CDB installation
|
||||
if (symbolPaths().isEmpty())
|
||||
setSymbolPaths(CdbOptions::oldEngineSymbolPaths(Core::ICore::instance()->settings()));
|
||||
} else {
|
||||
const QString msg = tr("\"Debugging Tools for Windows\" could not be found.");
|
||||
const QString details = tr("Checked:\n%1").arg(checkedDirectories.join(QString(QLatin1Char('\n'))));
|
||||
QMessageBox msbBox(QMessageBox::Information, tr("Autodetection"), msg, QMessageBox::Ok, this);
|
||||
msbBox.setDetailedText(details);
|
||||
msbBox.exec();
|
||||
}
|
||||
}
|
||||
|
||||
void CdbOptionsPageWidget::setReport(const QString &msg, bool success)
|
||||
{
|
||||
// Hide label after some interval
|
||||
if (!m_reportTimer) {
|
||||
m_reportTimer = new QTimer(this);
|
||||
m_reportTimer->setSingleShot(true);
|
||||
connect(m_reportTimer, SIGNAL(timeout()), this, SLOT(hideReportLabel()));
|
||||
} else {
|
||||
if (m_reportTimer->isActive())
|
||||
m_reportTimer->stop();
|
||||
}
|
||||
m_reportTimer->setInterval(success ? 10000 : 20000);
|
||||
m_reportTimer->start();
|
||||
|
||||
m_ui.reportLabel->setText(msg);
|
||||
m_ui.reportLabel->setStyleSheet(success ? QString() : QString::fromAscii("background-color : 'red'"));
|
||||
m_ui.reportLabel->setVisible(true);
|
||||
}
|
||||
|
||||
void CdbOptionsPageWidget::downLoadLinkActivated(const QString &link)
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl(link));
|
||||
}
|
||||
|
||||
QString CdbOptionsPageWidget::searchKeywords() const
|
||||
{
|
||||
QString rc;
|
||||
QTextStream(&rc) << m_ui.pathLabel->text() << ' ' << m_ui.symbolPathLabel->text()
|
||||
<< ' ' << m_ui.sourcePathLabel->text();
|
||||
rc.remove(QLatin1Char('&'));
|
||||
return rc;
|
||||
}
|
||||
|
||||
static QString cdbVersion(const QString &executable)
|
||||
{
|
||||
QProcess cdb;
|
||||
cdb.start(executable, QStringList(QLatin1String("-version")));
|
||||
cdb.closeWriteChannel();
|
||||
if (!cdb.waitForStarted())
|
||||
return QString();
|
||||
if (!cdb.waitForFinished()) {
|
||||
Utils::SynchronousProcess::stopProcess(cdb);
|
||||
return QString();
|
||||
}
|
||||
return QString::fromLocal8Bit(cdb.readAllStandardOutput());
|
||||
}
|
||||
|
||||
bool CdbOptionsPageWidget::checkInstallation(const QString &executable,
|
||||
bool is64Bit, QString *message)
|
||||
{
|
||||
// 1) Check on executable
|
||||
unsigned checkedItems = 0;
|
||||
QString rc;
|
||||
if (executable.isEmpty()) {
|
||||
message->append(tr("No cdb executable specified.\n"));
|
||||
} else {
|
||||
const QString version = cdbVersion(executable);
|
||||
if (version.isEmpty()) {
|
||||
message->append(tr("Unable to determine version of %1.\n").
|
||||
arg(executable));
|
||||
} else {
|
||||
message->append(tr("Version: %1").arg(version));
|
||||
checkedItems++;
|
||||
}
|
||||
}
|
||||
|
||||
// 2) Check on extension library
|
||||
const QFileInfo extensionFi(CdbEngine::extensionLibraryName(is64Bit));
|
||||
if (extensionFi.isFile()) {
|
||||
message->append(tr("Extension library: %1, built: %3.\n").
|
||||
arg(QDir::toNativeSeparators(extensionFi.absoluteFilePath())).
|
||||
arg(extensionFi.lastModified().toString(Qt::SystemLocaleShortDate)));
|
||||
checkedItems++;
|
||||
} else {
|
||||
message->append("Extension library not found.\n");
|
||||
}
|
||||
return checkedItems == 2u;
|
||||
}
|
||||
|
||||
bool CdbOptionsPageWidget::eventFilter(QObject *o, QEvent *e)
|
||||
{
|
||||
if (o != m_ui.cdbPathGroupBox || e->type() != QEvent::ToolTip)
|
||||
return QWidget::eventFilter(o, e);
|
||||
QString message;
|
||||
checkInstallation(path(), is64Bit(), &message);
|
||||
m_ui.cdbPathGroupBox->setToolTip(message);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ---------- CdbOptionsPage
|
||||
|
||||
CdbOptionsPage *CdbOptionsPage::m_instance = 0;
|
||||
|
||||
CdbOptionsPage::CdbOptionsPage() :
|
||||
m_options(new CdbOptions)
|
||||
{
|
||||
CdbOptionsPage::m_instance = this;
|
||||
m_options->fromSettings(Core::ICore::instance()->settings());
|
||||
}
|
||||
|
||||
CdbOptionsPage::~CdbOptionsPage()
|
||||
{
|
||||
CdbOptionsPage::m_instance = 0;
|
||||
}
|
||||
|
||||
QString CdbOptionsPage::settingsId()
|
||||
{
|
||||
return QLatin1String("F.Cda"); // before old CDB
|
||||
}
|
||||
|
||||
QString CdbOptionsPage::displayName() const
|
||||
{
|
||||
return tr("CDB");
|
||||
}
|
||||
|
||||
QString CdbOptionsPage::category() const
|
||||
{
|
||||
return QLatin1String(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY);
|
||||
}
|
||||
|
||||
QString CdbOptionsPage::displayCategory() const
|
||||
{
|
||||
return QCoreApplication::translate("Debugger", Debugger::Constants::DEBUGGER_SETTINGS_TR_CATEGORY);
|
||||
}
|
||||
|
||||
QIcon CdbOptionsPage::categoryIcon() const
|
||||
{
|
||||
return QIcon(QLatin1String(Debugger::Constants::DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON));
|
||||
}
|
||||
|
||||
QWidget *CdbOptionsPage::createPage(QWidget *parent)
|
||||
{
|
||||
m_widget = new CdbOptionsPageWidget(parent);
|
||||
m_widget->setOptions(*m_options);
|
||||
if (m_searchKeywords.isEmpty())
|
||||
m_searchKeywords = m_widget->searchKeywords();
|
||||
return m_widget;
|
||||
}
|
||||
|
||||
void CdbOptionsPage::apply()
|
||||
{
|
||||
if (!m_widget)
|
||||
return;
|
||||
const CdbOptions newOptions = m_widget->options();
|
||||
if (*m_options != newOptions) {
|
||||
*m_options = newOptions;
|
||||
m_options->toSettings(Core::ICore::instance()->settings());
|
||||
}
|
||||
}
|
||||
|
||||
void CdbOptionsPage::finish()
|
||||
{
|
||||
}
|
||||
|
||||
bool CdbOptionsPage::matches(const QString &s) const
|
||||
{
|
||||
return m_searchKeywords.contains(s, Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
CdbOptionsPage *CdbOptionsPage::instance()
|
||||
{
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
142
src/plugins/debugger/cdb/cdboptionspage.h
Normal file
142
src/plugins/debugger/cdb/cdboptionspage.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** No Commercial Usage
|
||||
**
|
||||
** This file contains pre-release code and may not be distributed.
|
||||
** You may use this file in accordance with the terms and conditions
|
||||
** contained in the Technology Preview License Agreement accompanying
|
||||
** this package.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CDBSETTINGSPAGE_H
|
||||
#define CDBSETTINGSPAGE_H
|
||||
|
||||
#include "cdboptions.h"
|
||||
|
||||
#include <coreplugin/dialogs/ioptionspage.h>
|
||||
#include "ui_cdboptionspagewidget.h"
|
||||
|
||||
#include <QtGui/QWidget>
|
||||
#include <QtCore/QPointer>
|
||||
#include <QtCore/QSharedPointer>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QTimer;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
// Widget displaying a list of break events for the 'sxe' command
|
||||
// with a checkbox to enable 'break' and optionally a QLineEdit for
|
||||
// events with parameters (like 'out:Needle').
|
||||
class CdbBreakEventWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CdbBreakEventWidget(QWidget *parent = 0);
|
||||
|
||||
void setBreakEvents(const QStringList &l);
|
||||
QStringList breakEvents() const;
|
||||
|
||||
private:
|
||||
QString filterText(int i) const;
|
||||
void clear();
|
||||
|
||||
QList<QCheckBox*> m_checkBoxes;
|
||||
QList<QLineEdit*> m_lineEdits;
|
||||
};
|
||||
|
||||
class CdbOptionsPageWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CdbOptionsPageWidget(QWidget *parent);
|
||||
|
||||
void setOptions(CdbOptions &o);
|
||||
CdbOptions options() const;
|
||||
|
||||
QString searchKeywords() const;
|
||||
|
||||
virtual bool eventFilter(QObject *, QEvent *);
|
||||
|
||||
private slots:
|
||||
void autoDetect();
|
||||
void downLoadLinkActivated(const QString &);
|
||||
void hideReportLabel();
|
||||
|
||||
private:
|
||||
QStringList symbolPaths() const;
|
||||
void setSymbolPaths(const QStringList &s);
|
||||
void setReport(const QString &, bool success);
|
||||
inline bool is64Bit() const;
|
||||
inline QString path() const;
|
||||
|
||||
static bool checkInstallation(const QString &executable, bool is64Bit,
|
||||
QString *message);
|
||||
|
||||
Ui::CdbOptionsPageWidget m_ui;
|
||||
CdbBreakEventWidget *m_breakEventWidget;
|
||||
QTimer *m_reportTimer;
|
||||
};
|
||||
|
||||
class CdbOptionsPage : public Core::IOptionsPage
|
||||
{
|
||||
Q_DISABLE_COPY(CdbOptionsPage)
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CdbOptionsPage();
|
||||
virtual ~CdbOptionsPage();
|
||||
|
||||
static CdbOptionsPage *instance();
|
||||
|
||||
// IOptionsPage
|
||||
virtual QString id() const { return settingsId(); }
|
||||
virtual QString displayName() const;
|
||||
virtual QString category() const;
|
||||
virtual QString displayCategory() const;
|
||||
QIcon categoryIcon() const;
|
||||
|
||||
virtual QWidget *createPage(QWidget *parent);
|
||||
virtual void apply();
|
||||
virtual void finish();
|
||||
virtual bool matches(const QString &) const;
|
||||
|
||||
static QString settingsId();
|
||||
|
||||
QSharedPointer<CdbOptions> options() const { return m_options; }
|
||||
|
||||
private:
|
||||
static CdbOptionsPage *m_instance;
|
||||
const QSharedPointer<CdbOptions> m_options;
|
||||
QPointer<CdbOptionsPageWidget> m_widget;
|
||||
QString m_searchKeywords;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // CDBSETTINGSPAGE_H
|
||||
143
src/plugins/debugger/cdb/cdboptionspagewidget.ui
Normal file
143
src/plugins/debugger/cdb/cdboptionspagewidget.ui
Normal file
@@ -0,0 +1,143 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Debugger::Internal::CdbOptionsPageWidget</class>
|
||||
<widget class="QWidget" name="Debugger::Cdb::CdbOptionsPageWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>347</width>
|
||||
<height>358</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="cdbPathGroupBox">
|
||||
<property name="title">
|
||||
<string extracomment="Placeholder">CDB</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="pathLabel">
|
||||
<property name="text">
|
||||
<string>Path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="Utils::PathChooser" name="pathChooser" native="true"/>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="noteLabel">
|
||||
<property name="text">
|
||||
<string notr="true" extracomment="Placeholder">Note: bla, blah</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="is64BitCheckBox">
|
||||
<property name="text">
|
||||
<string>64 bit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="pathGroupBox">
|
||||
<property name="title">
|
||||
<string>Debugger Paths</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="symbolPathLabel">
|
||||
<property name="text">
|
||||
<string>Symbol paths:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="Debugger::Internal::CdbSymbolPathListEditor" name="symbolPathListEditor" native="true"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="sourcePathLabel">
|
||||
<property name="text">
|
||||
<string>Source paths:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="Utils::PathListEditor" name="sourcePathListEditor" native="true"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="eventGroupBox">
|
||||
<property name="title">
|
||||
<string>Break on:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="reportLabel">
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Utils::PathChooser</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">utils/pathchooser.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Utils::PathListEditor</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">utils/pathlisteditor.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Debugger::Internal::CdbSymbolPathListEditor</class>
|
||||
<extends>QWidget</extends>
|
||||
<header location="global">cdbsymbolpathlisteditor.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
276
src/plugins/debugger/cdb/cdbparsehelpers.cpp
Normal file
276
src/plugins/debugger/cdb/cdbparsehelpers.cpp
Normal file
@@ -0,0 +1,276 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** No Commercial Usage
|
||||
**
|
||||
** This file contains pre-release code and may not be distributed.
|
||||
** You may use this file in accordance with the terms and conditions
|
||||
** contained in the Technology Preview License Agreement accompanying
|
||||
** this package.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "cdbparsehelpers.h"
|
||||
#include "breakpoint.h"
|
||||
#include "threadshandler.h"
|
||||
#include "registerhandler.h"
|
||||
#include "bytearrayinputstream.h"
|
||||
#include "gdb/gdbmi.h"
|
||||
#ifdef Q_OS_WIN
|
||||
# include "shared/dbgwinutils.h"
|
||||
#endif
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <cctype>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
// Convert breakpoint in CDB syntax.
|
||||
QByteArray cdbAddBreakpointCommand(const BreakpointParameters &bpIn, bool oneshot, int id)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
const BreakpointParameters bp = fixWinMSVCBreakpoint(bpIn);
|
||||
#else
|
||||
const BreakpointParameters bp = bpIn;
|
||||
#endif
|
||||
|
||||
QByteArray rc;
|
||||
ByteArrayInputStream str(rc);
|
||||
|
||||
if (bp.threadSpec >= 0)
|
||||
str << '~' << bp.threadSpec << ' ';
|
||||
|
||||
str << (bp.type == Watchpoint ? "ba" : "bp");
|
||||
if (id >= 0)
|
||||
str << id;
|
||||
str << ' ';
|
||||
if (oneshot)
|
||||
str << "/1 ";
|
||||
switch (bp.type) {
|
||||
case UnknownType:
|
||||
case BreakpointAtCatch:
|
||||
case BreakpointAtThrow:
|
||||
case BreakpointAtMain:
|
||||
QTC_ASSERT(false, return QByteArray(); )
|
||||
break;
|
||||
case BreakpointByAddress:
|
||||
str << hex << hexPrefixOn << bp.address << hexPrefixOff << dec;
|
||||
break;
|
||||
case BreakpointByFunction:
|
||||
str << bp.functionName;
|
||||
break;
|
||||
case BreakpointByFileAndLine:
|
||||
str << '`' << QDir::toNativeSeparators(bp.fileName) << ':' << bp.lineNumber << '`';
|
||||
break;
|
||||
case Watchpoint:
|
||||
str << "rw 1 " << hex << hexPrefixOn << bp.address << hexPrefixOff << dec;
|
||||
break;
|
||||
}
|
||||
if (bp.ignoreCount)
|
||||
str << ' ' << bp.ignoreCount;
|
||||
// Condition currently unsupported.
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Fix a CDB integer value: '00000000`0012a290' -> '12a290', '0n10' ->'10'
|
||||
QByteArray fixCdbIntegerValue(QByteArray t, bool stripLeadingZeros, int *basePtr /* = 0 */)
|
||||
{
|
||||
if (t.isEmpty())
|
||||
return t;
|
||||
int base = 16;
|
||||
// Prefixes
|
||||
if (t.startsWith("0x")) {
|
||||
t.remove(0, 2);
|
||||
} else if (t.startsWith("0n")) {
|
||||
base = 10;
|
||||
t.remove(0, 2);
|
||||
}
|
||||
if (base == 16 && t.size() >= 9 && t.at(8) == '`')
|
||||
t.remove(8, 1);
|
||||
if (stripLeadingZeros) { // Strip all but last '0'
|
||||
const int last = t.size() - 1;
|
||||
int pos = 0;
|
||||
for ( ; pos < last && t.at(pos) == '0'; pos++) ;
|
||||
if (pos)
|
||||
t.remove(0, pos);
|
||||
}
|
||||
if (basePtr)
|
||||
*basePtr = base;
|
||||
return t;
|
||||
}
|
||||
|
||||
// Convert a CDB integer value: '00000000`0012a290' -> '12a290', '0n10' ->'10'
|
||||
QVariant cdbIntegerValue(const QByteArray &t)
|
||||
{
|
||||
int base;
|
||||
const QByteArray fixed = fixCdbIntegerValue(t, false, &base);
|
||||
bool ok;
|
||||
const QVariant converted = base == 16 ?
|
||||
fixed.toULongLong(&ok, base) :
|
||||
fixed.toLongLong(&ok, base);
|
||||
QTC_ASSERT(ok, return QVariant(); )
|
||||
return converted;
|
||||
}
|
||||
|
||||
/* \code
|
||||
0:002> ~ [Debugger-Id] Id: <hex pid> <hex tid> Suspends count thread environment block add state name
|
||||
0 Id: 133c.1374 Suspend: 1 Teb: 000007ff`fffdd000 Unfrozen
|
||||
. 2 Id: 133c.1160 Suspend: 1 Teb: 000007ff`fffd9000 Unfrozen "QThread"
|
||||
3 Id: 133c.38c Suspend: 1 Teb: 000007ff`fffd7000 Unfrozen "QThread"
|
||||
\endcode */
|
||||
|
||||
static inline bool parseThread(QByteArray line, ThreadData *thread, bool *current)
|
||||
{
|
||||
*current = false;
|
||||
if (line.size() < 5)
|
||||
return false;
|
||||
*current = line.at(0) == '.';
|
||||
if (current)
|
||||
line[0] = ' ';
|
||||
const QList<QByteArray> tokens = simplify(line).split(' ');
|
||||
if (tokens.size() < 8 || tokens.at(1) != "Id:")
|
||||
return false;
|
||||
switch (tokens.size()) { // fallthru intended
|
||||
case 9:
|
||||
thread->name = QString::fromLocal8Bit(tokens.at(8));
|
||||
case 8:
|
||||
thread->state = QString::fromLocal8Bit(tokens.at(7));
|
||||
case 3: {
|
||||
const QByteArray &pidTid = tokens.at(2);
|
||||
const int dotPos = pidTid.indexOf('.');
|
||||
if (dotPos != -1)
|
||||
thread->targetId = QLatin1String("0x") + QString::fromAscii(pidTid.mid(dotPos + 1));
|
||||
}
|
||||
case 1:
|
||||
thread->id = tokens.at(0).toInt();
|
||||
break;
|
||||
} // switch size
|
||||
return true;
|
||||
}
|
||||
|
||||
QString debugByteArray(const QByteArray &a)
|
||||
{
|
||||
QString rc;
|
||||
const int size = a.size();
|
||||
rc.reserve(size * 2);
|
||||
QTextStream str(&rc);
|
||||
for (int i = 0; i < size; i++) {
|
||||
const unsigned char uc = (unsigned char)(a.at(i));
|
||||
switch (uc) {
|
||||
case 0:
|
||||
str << "\\0";
|
||||
break;
|
||||
case '\n':
|
||||
str << "\\n";
|
||||
break;
|
||||
case '\t':
|
||||
str << "\\t";
|
||||
break;
|
||||
case '\r':
|
||||
str << "\\r";
|
||||
break;
|
||||
default:
|
||||
if (uc >=32 && uc < 128) {
|
||||
str << a.at(i);
|
||||
} else {
|
||||
str << '<' << unsigned(uc) << '>';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
QString StringFromBase64EncodedUtf16(const QByteArray &a)
|
||||
{
|
||||
QByteArray utf16 = QByteArray::fromBase64(a);
|
||||
utf16.append('\0');
|
||||
utf16.append('\0');
|
||||
return QString::fromUtf16(reinterpret_cast<const unsigned short *>(utf16.constData()));
|
||||
}
|
||||
|
||||
WinException::WinException() :
|
||||
exceptionCode(0), exceptionFlags(0), exceptionAddress(0),
|
||||
info1(0),info2(0), firstChance(false), lineNumber(0)
|
||||
{
|
||||
}
|
||||
|
||||
void WinException::fromGdbMI(const GdbMi &gdbmi)
|
||||
{
|
||||
exceptionCode = gdbmi.findChild("exceptionCode").data().toUInt();
|
||||
exceptionFlags = gdbmi.findChild("exceptionFlags").data().toUInt();
|
||||
exceptionAddress = gdbmi.findChild("exceptionAddress").data().toULongLong();
|
||||
firstChance = gdbmi.findChild("firstChance").data() != "0";
|
||||
const GdbMi ginfo1 = gdbmi.findChild("exceptionInformation0");
|
||||
if (ginfo1.isValid()) {
|
||||
info1 = ginfo1.data().toULongLong();
|
||||
const GdbMi ginfo2 = gdbmi.findChild("exceptionInformation1");
|
||||
if (ginfo2.isValid())
|
||||
info2 = ginfo1.data().toULongLong();
|
||||
}
|
||||
const GdbMi gLineNumber = gdbmi.findChild("exceptionLine");
|
||||
if (gLineNumber.isValid()) {
|
||||
lineNumber = gLineNumber.data().toInt();
|
||||
file = gdbmi.findChild("exceptionFile").data();
|
||||
}
|
||||
function = gdbmi.findChild("exceptionFunction").data();
|
||||
}
|
||||
|
||||
QString WinException::toString(bool includeLocation) const
|
||||
{
|
||||
QString rc;
|
||||
QTextStream str(&rc);
|
||||
#ifdef Q_OS_WIN
|
||||
formatWindowsException(exceptionCode, exceptionAddress,
|
||||
exceptionFlags, info1, info2, str);
|
||||
#endif
|
||||
if (includeLocation) {
|
||||
if (lineNumber) {
|
||||
str << " at " << QLatin1String(file) << ':' << lineNumber;
|
||||
} else {
|
||||
if (!function.isEmpty())
|
||||
str << " in " << QLatin1String(function);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug s, const WinException &e)
|
||||
{
|
||||
QDebug nsp = s.nospace();
|
||||
nsp << "code=" << e.exceptionCode << ",flags=" << e.exceptionFlags
|
||||
<< ",address=0x" << QString::number(e.exceptionAddress, 16)
|
||||
<< ",firstChance=" << e.firstChance;
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
89
src/plugins/debugger/cdb/cdbparsehelpers.h
Normal file
89
src/plugins/debugger/cdb/cdbparsehelpers.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
** No Commercial Usage
|
||||
**
|
||||
** This file contains pre-release code and may not be distributed.
|
||||
** You may use this file in accordance with the terms and conditions
|
||||
** contained in the Technology Preview License Agreement accompanying
|
||||
** this package.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef CDBPARSEHELPERS_H
|
||||
#define CDBPARSEHELPERS_H
|
||||
|
||||
#include <QtCore/QtGlobal>
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QByteArray>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QVariant;
|
||||
class QDebug;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
class BreakpointData;
|
||||
class BreakpointParameters;
|
||||
struct ThreadData;
|
||||
class Register;
|
||||
class GdbMi;
|
||||
|
||||
// Convert breakpoint in CDB syntax.
|
||||
QByteArray cdbAddBreakpointCommand(const BreakpointParameters &d, bool oneshot = false, int id = -1);
|
||||
|
||||
// Convert a CDB integer value: '00000000`0012a290' -> '12a290', '0n10' ->'10'
|
||||
QByteArray fixCdbIntegerValue(QByteArray t, bool stripLeadingZeros = false, int *basePtr = 0);
|
||||
// Convert a CDB integer value into quint64 or int64
|
||||
QVariant cdbIntegerValue(const QByteArray &t);
|
||||
|
||||
QString debugByteArray(const QByteArray &a);
|
||||
QString StringFromBase64EncodedUtf16(const QByteArray &a);
|
||||
|
||||
// Model EXCEPTION_RECORD + firstchance
|
||||
struct WinException
|
||||
{
|
||||
WinException();
|
||||
void fromGdbMI(const GdbMi &);
|
||||
QString toString(bool includeLocation = false) const;
|
||||
|
||||
unsigned exceptionCode;
|
||||
unsigned exceptionFlags;
|
||||
quint64 exceptionAddress;
|
||||
quint64 info1;
|
||||
quint64 info2;
|
||||
bool firstChance;
|
||||
QByteArray file;
|
||||
int lineNumber;
|
||||
QByteArray function;
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug s, const WinException &e);
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // CDBPARSEHELPERS_H
|
||||
Reference in New Issue
Block a user