Debugger[New CDB]: Get rid of postfix '2' in file names/classes.

This commit is contained in:
Friedemann Kleint
2011-01-11 11:22:55 +01:00
parent 46647f49d8
commit 7ff4b1fec2
15 changed files with 31 additions and 31 deletions

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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

View 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

View 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

View 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

View 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>

View 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

View 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