forked from qt-creator/qt-creator
Merge branch 'master' of scm.dev.nokia.troll.no:creator/mainline
This commit is contained in:
@@ -830,6 +830,11 @@ quint64 CoreEngine::getSourceLineAddress(const QString &file,
|
||||
return rc;
|
||||
}
|
||||
|
||||
void CoreEngine::outputVersion()
|
||||
{
|
||||
m_cif.debugControl->OutputVersionInformation(DEBUG_OUTCTL_ALL_CLIENTS);
|
||||
}
|
||||
|
||||
bool CoreEngine::autoDetectPath(QString *outPath,
|
||||
QStringList *checkedDirectories /* = 0 */)
|
||||
{
|
||||
|
||||
@@ -168,6 +168,9 @@ signals:
|
||||
// feature of the engine.
|
||||
void modulesLoaded();
|
||||
|
||||
public slots:
|
||||
void outputVersion();
|
||||
|
||||
protected:
|
||||
virtual void timerEvent(QTimerEvent* te);
|
||||
|
||||
|
||||
40
src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.cpp
Normal file
40
src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "maemodeploystep.h"
|
||||
|
||||
#include "maemodeploystepwidget.h"
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
namespace Qt4ProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
const QLatin1String MaemoDeployStep::Id("Qt4ProjectManager.MaemoDeployStep");
|
||||
|
||||
|
||||
MaemoDeployStep::MaemoDeployStep(ProjectExplorer::BuildConfiguration *bc)
|
||||
: BuildStep(bc, Id)
|
||||
{
|
||||
}
|
||||
|
||||
MaemoDeployStep::MaemoDeployStep(ProjectExplorer::BuildConfiguration *bc,
|
||||
MaemoDeployStep *other)
|
||||
: BuildStep(bc, other)
|
||||
{
|
||||
}
|
||||
|
||||
bool MaemoDeployStep::init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void MaemoDeployStep::run(QFutureInterface<bool> &fi)
|
||||
{
|
||||
fi.reportResult(true);
|
||||
}
|
||||
|
||||
BuildStepConfigWidget *MaemoDeployStep::createConfigWidget()
|
||||
{
|
||||
return new MaemoDeployStepWidget;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Qt4ProjectManager
|
||||
30
src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.h
Normal file
30
src/plugins/qt4projectmanager/qt-maemo/maemodeploystep.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef MAEMODEPLOYSTEP_H
|
||||
#define MAEMODEPLOYSTEP_H
|
||||
|
||||
#include <projectexplorer/buildstep.h>
|
||||
|
||||
namespace Qt4ProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
class MaemoDeployStep : public ProjectExplorer::BuildStep
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class MaemoDeployStepFactory;
|
||||
public:
|
||||
MaemoDeployStep(ProjectExplorer::BuildConfiguration *bc);
|
||||
|
||||
private:
|
||||
MaemoDeployStep(ProjectExplorer::BuildConfiguration *bc,
|
||||
MaemoDeployStep *other);
|
||||
virtual bool init();
|
||||
virtual void run(QFutureInterface<bool> &fi);
|
||||
virtual ProjectExplorer::BuildStepConfigWidget *createConfigWidget();
|
||||
virtual bool immutable() const { return true; }
|
||||
|
||||
static const QLatin1String Id;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Qt4ProjectManager
|
||||
|
||||
#endif // MAEMODEPLOYSTEP_H
|
||||
@@ -0,0 +1,82 @@
|
||||
#include "maemodeploystepfactory.h"
|
||||
|
||||
#include "maemodeploystep.h"
|
||||
|
||||
#include <projectexplorer/buildconfiguration.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <qt4projectmanager/qt4projectmanagerconstants.h>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
namespace Qt4ProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
MaemoDeployStepFactory::MaemoDeployStepFactory(QObject *parent)
|
||||
: IBuildStepFactory(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QStringList MaemoDeployStepFactory::availableCreationIds(BuildConfiguration *,
|
||||
BuildStep::Type) const
|
||||
{
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QString MaemoDeployStepFactory::displayNameForId(const QString &) const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool MaemoDeployStepFactory::canCreate(BuildConfiguration *,
|
||||
BuildStep::Type, const QString &) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
BuildStep *MaemoDeployStepFactory::create(BuildConfiguration *,
|
||||
BuildStep::Type, const QString &)
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool MaemoDeployStepFactory::canRestore(BuildConfiguration *parent,
|
||||
BuildStep::Type type, const QVariantMap &map) const
|
||||
{
|
||||
return canCreateInternally(parent, type, idFromMap(map));
|
||||
}
|
||||
|
||||
BuildStep *MaemoDeployStepFactory::restore(BuildConfiguration *parent,
|
||||
BuildStep::Type type, const QVariantMap &map)
|
||||
{
|
||||
Q_ASSERT(canRestore(parent, type, map));
|
||||
MaemoDeployStep * const step = new MaemoDeployStep(parent);
|
||||
if (!step->fromMap(map)) {
|
||||
delete step;
|
||||
return 0;
|
||||
}
|
||||
return step;
|
||||
}
|
||||
|
||||
bool MaemoDeployStepFactory::canClone(BuildConfiguration *parent,
|
||||
BuildStep::Type type, BuildStep *product) const
|
||||
{
|
||||
return canCreateInternally(parent, type, product->id());
|
||||
}
|
||||
|
||||
BuildStep *MaemoDeployStepFactory::clone(BuildConfiguration *parent,
|
||||
BuildStep::Type type, BuildStep *product)
|
||||
{
|
||||
Q_ASSERT(canClone(parent, type, product));
|
||||
return new MaemoDeployStep(parent, static_cast<MaemoDeployStep*>(product));
|
||||
}
|
||||
|
||||
bool MaemoDeployStepFactory::canCreateInternally(BuildConfiguration *parent,
|
||||
BuildStep::Type type, const QString &id) const
|
||||
{
|
||||
return type == BuildStep::Deploy && id == MaemoDeployStep::Id
|
||||
&& parent->target()->id() == Constants::MAEMO_DEVICE_TARGET_ID;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Qt4ProjectManager
|
||||
@@ -0,0 +1,49 @@
|
||||
#ifndef MAEMODEPLOYSTEPFACTORY_H
|
||||
#define MAEMODEPLOYSTEPFACTORY_H
|
||||
|
||||
#include <projectexplorer/buildstep.h>
|
||||
|
||||
namespace Qt4ProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
class MaemoDeployStepFactory : public ProjectExplorer::IBuildStepFactory
|
||||
{
|
||||
public:
|
||||
MaemoDeployStepFactory(QObject *parent);
|
||||
|
||||
virtual QStringList availableCreationIds(ProjectExplorer::BuildConfiguration *parent,
|
||||
ProjectExplorer::BuildStep::Type type) const;
|
||||
virtual QString displayNameForId(const QString &id) const;
|
||||
|
||||
virtual bool canCreate(ProjectExplorer::BuildConfiguration *parent,
|
||||
ProjectExplorer::BuildStep::Type type,
|
||||
const QString &id) const;
|
||||
virtual ProjectExplorer::BuildStep *
|
||||
create(ProjectExplorer::BuildConfiguration *parent,
|
||||
ProjectExplorer::BuildStep::Type type, const QString &id);
|
||||
|
||||
virtual bool canRestore(ProjectExplorer::BuildConfiguration *parent,
|
||||
ProjectExplorer::BuildStep::Type type,
|
||||
const QVariantMap &map) const;
|
||||
virtual ProjectExplorer::BuildStep *
|
||||
restore(ProjectExplorer::BuildConfiguration *parent,
|
||||
ProjectExplorer::BuildStep::Type type, const QVariantMap &map);
|
||||
|
||||
virtual bool canClone(ProjectExplorer::BuildConfiguration *parent,
|
||||
ProjectExplorer::BuildStep::Type type,
|
||||
ProjectExplorer::BuildStep *product) const;
|
||||
virtual ProjectExplorer::BuildStep *
|
||||
clone(ProjectExplorer::BuildConfiguration *parent,
|
||||
ProjectExplorer::BuildStep::Type type,
|
||||
ProjectExplorer::BuildStep *product);
|
||||
|
||||
private:
|
||||
bool canCreateInternally(ProjectExplorer::BuildConfiguration *parent,
|
||||
ProjectExplorer::BuildStep::Type type,
|
||||
const QString &id) const;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Qt4ProjectManager
|
||||
|
||||
#endif // MAEMODEPLOYSTEPFACTORY_H
|
||||
@@ -0,0 +1,34 @@
|
||||
#include "maemodeploystepwidget.h"
|
||||
#include "ui_maemodeploystepwidget.h"
|
||||
|
||||
namespace Qt4ProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
MaemoDeployStepWidget::MaemoDeployStepWidget() :
|
||||
ProjectExplorer::BuildStepConfigWidget(),
|
||||
ui(new Ui::MaemoDeployStepWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
MaemoDeployStepWidget::~MaemoDeployStepWidget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MaemoDeployStepWidget::init()
|
||||
{
|
||||
}
|
||||
|
||||
QString MaemoDeployStepWidget::summaryText() const
|
||||
{
|
||||
return tr("<b>Deploy to device</b> ");
|
||||
}
|
||||
|
||||
QString MaemoDeployStepWidget::displayName() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Qt4ProjectManager
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef MAEMODEPLOYSTEPWIDGET_H
|
||||
#define MAEMODEPLOYSTEPWIDGET_H
|
||||
|
||||
#include <projectexplorer/buildstep.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
class MaemoDeployStepWidget;
|
||||
}
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Qt4ProjectManager {
|
||||
namespace Internal {
|
||||
|
||||
class MaemoDeployStepWidget : public ProjectExplorer::BuildStepConfigWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MaemoDeployStepWidget();
|
||||
~MaemoDeployStepWidget();
|
||||
|
||||
private:
|
||||
virtual void init();
|
||||
virtual QString summaryText() const;
|
||||
virtual QString displayName() const;
|
||||
|
||||
Ui::MaemoDeployStepWidget *ui;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Qt4ProjectManager
|
||||
|
||||
#endif // MAEMODEPLOYSTEPWIDGET_H
|
||||
@@ -0,0 +1,21 @@
|
||||
<ui version="4.0">
|
||||
<author/>
|
||||
<comment/>
|
||||
<exportmacro/>
|
||||
<class>MaemoDeployStepWidget</class>
|
||||
<widget class="QWidget" name="MaemoDeployStepWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
</widget>
|
||||
<pixmapfunction/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "maemomanager.h"
|
||||
|
||||
#include "maemoconstants.h"
|
||||
#include "maemodeploystepfactory.h"
|
||||
#include "maemodeviceconfigurations.h"
|
||||
#include "maemopackagecreationfactory.h"
|
||||
#include "maemorunfactories.h"
|
||||
@@ -57,6 +58,7 @@ MaemoManager::MaemoManager()
|
||||
, m_runControlFactory(new MaemoRunControlFactory(this))
|
||||
, m_runConfigurationFactory(new MaemoRunConfigurationFactory(this))
|
||||
, m_packageCreationFactory(new MaemoPackageCreationFactory(this))
|
||||
, m_deployStepFactory(new MaemoDeployStepFactory(this))
|
||||
, m_settingsPage(new MaemoSettingsPage(this))
|
||||
{
|
||||
Q_ASSERT(!m_instance);
|
||||
@@ -69,6 +71,7 @@ MaemoManager::MaemoManager()
|
||||
pluginManager->addObject(m_runControlFactory);
|
||||
pluginManager->addObject(m_runConfigurationFactory);
|
||||
pluginManager->addObject(m_packageCreationFactory);
|
||||
pluginManager->addObject(m_deployStepFactory);
|
||||
pluginManager->addObject(m_settingsPage);
|
||||
}
|
||||
|
||||
@@ -77,6 +80,7 @@ MaemoManager::~MaemoManager()
|
||||
PluginManager *pluginManager = PluginManager::instance();
|
||||
pluginManager->removeObject(m_runControlFactory);
|
||||
pluginManager->removeObject(m_runConfigurationFactory);
|
||||
pluginManager->removeObject(m_deployStepFactory);
|
||||
pluginManager->removeObject(m_packageCreationFactory);
|
||||
pluginManager->removeObject(m_settingsPage);
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace Qt4ProjectManager {
|
||||
class QtVersion;
|
||||
namespace Internal {
|
||||
|
||||
class MaemoDeployStepFactory;
|
||||
class MaemoPackageCreationFactory;
|
||||
class MaemoRunControlFactory;
|
||||
class MaemoRunConfigurationFactory;
|
||||
@@ -67,6 +68,7 @@ private:
|
||||
MaemoRunControlFactory *m_runControlFactory;
|
||||
MaemoRunConfigurationFactory *m_runConfigurationFactory;
|
||||
MaemoPackageCreationFactory *m_packageCreationFactory;
|
||||
MaemoDeployStepFactory *m_deployStepFactory;
|
||||
MaemoSettingsPage *m_settingsPage;
|
||||
QemuRuntimeManager *m_qemuRuntimeManager;
|
||||
};
|
||||
|
||||
@@ -81,7 +81,10 @@ bool MaemoRunConfigurationFactory::canCreate(Target *parent,
|
||||
bool MaemoRunConfigurationFactory::canRestore(Target *parent,
|
||||
const QVariantMap &map) const
|
||||
{
|
||||
return canCreate(parent, ProjectExplorer::idFromMap(map));
|
||||
if (!qobject_cast<Qt4Target *>(parent))
|
||||
return false;
|
||||
return ProjectExplorer::idFromMap(map)
|
||||
.startsWith(QLatin1String(MAEMO_RC_ID));
|
||||
}
|
||||
|
||||
bool MaemoRunConfigurationFactory::canClone(Target *parent,
|
||||
|
||||
@@ -19,7 +19,10 @@ HEADERS += \
|
||||
$$PWD/profilewrapper.h \
|
||||
$$PWD/maemodeployables.h \
|
||||
$$PWD/maemodeployable.h \
|
||||
$$PWD/maemodeployablelistwidget.h
|
||||
$$PWD/maemodeployablelistwidget.h \
|
||||
$$PWD/maemodeploystep.h \
|
||||
$$PWD/maemodeploystepwidget.h \
|
||||
$$PWD/maemodeploystepfactory.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/maemoconfigtestdialog.cpp \
|
||||
@@ -40,13 +43,17 @@ SOURCES += \
|
||||
$$PWD/qemuruntimemanager.cpp \
|
||||
$$PWD/profilewrapper.cpp \
|
||||
$$PWD/maemodeployables.cpp \
|
||||
$$PWD/maemodeployablelistwidget.cpp
|
||||
$$PWD/maemodeployablelistwidget.cpp \
|
||||
$$PWD/maemodeploystep.cpp \
|
||||
$$PWD/maemodeploystepwidget.cpp \
|
||||
$$PWD/maemodeploystepfactory.cpp
|
||||
|
||||
FORMS += \
|
||||
$$PWD/maemoconfigtestdialog.ui \
|
||||
$$PWD/maemosettingswidget.ui \
|
||||
$$PWD/maemosshconfigdialog.ui \
|
||||
$$PWD/maemopackagecreationwidget.ui \
|
||||
$$PWD/maemodeployablelistwidget.ui
|
||||
$$PWD/maemodeployablelistwidget.ui \
|
||||
qt-maemo/maemodeploystepwidget.ui
|
||||
|
||||
RESOURCES += $$PWD/qt-maemo.qrc
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "qt4project.h"
|
||||
#include "qt4runconfiguration.h"
|
||||
#include "qt4projectmanagerconstants.h"
|
||||
#include "qt-maemo/maemodeploystep.h"
|
||||
#include "qt-maemo/maemopackagecreationstep.h"
|
||||
#include "qt-maemo/maemorunconfiguration.h"
|
||||
#include "qt-s60/s60devicerunconfiguration.h"
|
||||
@@ -285,7 +286,10 @@ Qt4BuildConfiguration *Qt4Target::addQt4BuildConfiguration(QString displayName,
|
||||
S60CreatePackageStep *packageStep = new S60CreatePackageStep(bc);
|
||||
bc->insertStep(ProjectExplorer::BuildStep::Deploy, 2, packageStep);
|
||||
} else if (id() == Constants::MAEMO_DEVICE_TARGET_ID) {
|
||||
bc->insertStep(ProjectExplorer::BuildStep::Deploy, 2, new MaemoPackageCreationStep(bc));
|
||||
bc->insertStep(ProjectExplorer::BuildStep::Deploy, 2,
|
||||
new MaemoPackageCreationStep(bc));
|
||||
// bc->insertStep(ProjectExplorer::BuildStep::Deploy, 2,
|
||||
// new MaemoDeployStep(bc));
|
||||
}
|
||||
|
||||
MakeStep* cleanStep = new MakeStep(bc);
|
||||
|
||||
@@ -34,17 +34,18 @@
|
||||
#include "debugeventcallback.h"
|
||||
#include "symbolgroupcontext.h"
|
||||
#include "stacktracecontext.h"
|
||||
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cerrno>
|
||||
|
||||
const char usage[] =
|
||||
"CDB command line test tool\n\n"
|
||||
"ccdb <Options>\n"
|
||||
"Options: -p engine path\n";
|
||||
"Options: -p engine path\n"
|
||||
" -c initial_command_file\n";
|
||||
|
||||
class PrintfOutputHandler : public CdbCore::DebugOutputBase
|
||||
{
|
||||
@@ -72,7 +73,8 @@ CdbApplication::~CdbApplication()
|
||||
|
||||
CdbApplication::InitResult CdbApplication::init()
|
||||
{
|
||||
if (!parseOptions()) {
|
||||
FILE *inputFile;
|
||||
if (!parseOptions(&inputFile)) {
|
||||
printf(usage);
|
||||
return InitUsageShown;
|
||||
}
|
||||
@@ -91,7 +93,7 @@ CdbApplication::InitResult CdbApplication::init()
|
||||
connect(m_engine.data(), SIGNAL(watchTimerDebugEvent()), this, SLOT(debugEvent()));
|
||||
std::printf("Succeded.\n");
|
||||
// Prompt
|
||||
m_promptThread = new CdbPromptThread(this);
|
||||
m_promptThread = new CdbPromptThread(inputFile, this);
|
||||
connect(m_promptThread, SIGNAL(finished()), this, SLOT(promptThreadTerminated()));
|
||||
connect(m_promptThread, SIGNAL(asyncCommand(int,QString)),
|
||||
this, SLOT(asyncCommand(int,QString)), Qt::QueuedConnection);
|
||||
@@ -99,7 +101,8 @@ CdbApplication::InitResult CdbApplication::init()
|
||||
this, SLOT(syncCommand(int,QString)), Qt::BlockingQueuedConnection);
|
||||
connect(m_promptThread, SIGNAL(executionCommand(int,QString)),
|
||||
this, SLOT(executionCommand(int,QString)), Qt::BlockingQueuedConnection);
|
||||
|
||||
connect(m_engine.data(), SIGNAL(watchTimerDebugEvent()), m_promptThread, SLOT(notifyDebugEvent()),
|
||||
Qt::QueuedConnection);
|
||||
m_promptThread->start();
|
||||
return InitOk;
|
||||
}
|
||||
@@ -113,23 +116,41 @@ void CdbApplication::promptThreadTerminated()
|
||||
quit();
|
||||
}
|
||||
|
||||
bool CdbApplication::parseOptions()
|
||||
bool CdbApplication::parseOptions(FILE **inputFile)
|
||||
{
|
||||
*inputFile = NULL;
|
||||
const QStringList args = QCoreApplication::arguments();
|
||||
const QStringList::const_iterator cend = args.constEnd();
|
||||
QStringList::const_iterator it = args.constBegin();
|
||||
for (++it; it != cend ; ++it) {
|
||||
const QString &a = *it;
|
||||
if (a == QLatin1String("-p")) {
|
||||
++it;
|
||||
if (it == cend) {
|
||||
std::fprintf(stderr, "Option -p is missing an argument.\n");
|
||||
if (a.startsWith(QLatin1Char('-')) && a.size() >= 2) {
|
||||
switch (a.at(1).toAscii()) {
|
||||
case 'p':
|
||||
++it;
|
||||
if (it == cend) {
|
||||
std::fprintf(stderr, "Option -p is missing an argument.\n");
|
||||
return false;
|
||||
}
|
||||
m_engineDll = *it;
|
||||
break;
|
||||
case 'c':
|
||||
++it;
|
||||
if (it == cend) {
|
||||
std::fprintf(stderr, "Option -c is missing an argument.\n");
|
||||
return false;
|
||||
}
|
||||
*inputFile = std::fopen( it->toLocal8Bit().constData(), "r");
|
||||
if (*inputFile == NULL) {
|
||||
std::fprintf(stderr, "Cannot open %s: %s\n", qPrintable(*it), std::strerror(errno));
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
std::fprintf(stderr, "Invalid option %s\n", qPrintable(a));
|
||||
return false;
|
||||
}
|
||||
m_engineDll = *it;
|
||||
} else {
|
||||
std::fprintf(stderr, "Invalid option %s\n", qPrintable(a));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -252,6 +273,11 @@ void CdbApplication::syncCommand(int command, const QString &arg)
|
||||
case Sync_PrintFrame:
|
||||
printFrame(arg);
|
||||
break;
|
||||
case Sync_OutputVersion:
|
||||
m_engine->outputVersion();
|
||||
break;
|
||||
case Sync_Python:
|
||||
break;
|
||||
case Unknown:
|
||||
std::printf("Executing '%s' in code level %d, syntax %d\n",
|
||||
qPrintable(arg), m_engine->codeLevel(), m_engine->expressionSyntax());
|
||||
@@ -286,7 +312,7 @@ void CdbApplication::executionCommand(int command, const QString &arg)
|
||||
}
|
||||
if (ok) {
|
||||
m_engine->startWatchTimer();
|
||||
m_stackTrace.reset();
|
||||
m_stackTrace = QSharedPointer<CdbCore::StackTraceContext>();
|
||||
} else {
|
||||
std::fprintf(stderr, "%s\n", qPrintable(errorMessage));
|
||||
}
|
||||
@@ -297,11 +323,17 @@ void CdbApplication::debugEvent()
|
||||
QString errorMessage;
|
||||
std::printf("Debug event\n");
|
||||
|
||||
CdbCore::StackTraceContext::ThreadIdFrameMap threads;
|
||||
QVector<CdbCore::Thread> threads;
|
||||
QVector<CdbCore::StackFrame> threadFrames;
|
||||
ULONG currentThreadId;
|
||||
if (CdbCore::StackTraceContext::getThreads(m_engine->interfaces(), &threads,
|
||||
¤tThreadId, &errorMessage)) {
|
||||
printf("%s\n", qPrintable(CdbCore::StackTraceContext::formatThreads(threads)));
|
||||
|
||||
if (CdbCore::StackTraceContext::getThreadList(m_engine->interfaces(), &threads, ¤tThreadId, &errorMessage)
|
||||
&& CdbCore::StackTraceContext::getStoppedThreadFrames(m_engine->interfaces(), currentThreadId, threads, &threadFrames, &errorMessage)) {
|
||||
const int count = threadFrames.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
printf("Thread #%02d ID %10d SYSID %10d %s\n", i,
|
||||
threads.at(i).id, threads.at(i).systemId, qPrintable(threadFrames.at(i).toString()));
|
||||
}
|
||||
} else {
|
||||
std::fprintf(stderr, "%s\n", qPrintable(errorMessage));
|
||||
}
|
||||
@@ -310,7 +342,7 @@ void CdbApplication::debugEvent()
|
||||
CdbCore::StackTraceContext::create(&m_engine->interfaces(),
|
||||
0xFFFF, &errorMessage);
|
||||
if (trace) {
|
||||
m_stackTrace.reset(trace);
|
||||
m_stackTrace = QSharedPointer<CdbCore::StackTraceContext>(trace);
|
||||
printf("%s\n", qPrintable(m_stackTrace->toString()));
|
||||
} else {
|
||||
std::fprintf(stderr, "%s\n", qPrintable(errorMessage));
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
#include <QtCore/QScopedPointer>
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace CdbCore {
|
||||
class CoreEngine;
|
||||
class StackTraceContext;
|
||||
@@ -65,13 +67,13 @@ private slots:
|
||||
void processAttached(void *handle);
|
||||
|
||||
private:
|
||||
bool parseOptions();
|
||||
bool parseOptions(FILE **inputFile);
|
||||
void printFrame(const QString &arg);
|
||||
quint64 addQueuedBreakPoint(const QString &arg, QString *errorMessage);
|
||||
|
||||
QString m_engineDll;
|
||||
QSharedPointer<CdbCore::CoreEngine> m_engine;
|
||||
QScopedPointer<CdbCore::StackTraceContext> m_stackTrace;
|
||||
QSharedPointer<CdbCore::StackTraceContext> m_stackTrace;
|
||||
CdbPromptThread *m_promptThread;
|
||||
QStringList m_queuedCommands;
|
||||
QStringList m_queuedBreakPoints;
|
||||
|
||||
@@ -29,13 +29,12 @@
|
||||
|
||||
#include "cdbpromptthread.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
static const char help[] =
|
||||
"Special commands:\n\n"
|
||||
"H Display Help\n"
|
||||
"q Quit\n"
|
||||
"V Output version\n"
|
||||
"E expression Evaluate C++expression\n"
|
||||
"S binary args Start binary\n"
|
||||
"I Interrupt\n"
|
||||
@@ -46,11 +45,17 @@ static const char help[] =
|
||||
"B Clear breakpoint queue\n"
|
||||
"L List breakpoints\n"
|
||||
"F <n> Print stack frame <n>, 0 being top\n"
|
||||
"P <cmd> Run Python command\n"
|
||||
"W Synchronous wait for debug event\n"
|
||||
"\nThe remaining commands are passed to CDB.\n";
|
||||
|
||||
CdbPromptThread::CdbPromptThread(QObject *parent) :
|
||||
QThread(parent)
|
||||
CdbPromptThread::CdbPromptThread(FILE *file, QObject *parent) :
|
||||
QThread(parent),
|
||||
m_waitingForDebugEvent(false),
|
||||
m_inputFile(file)
|
||||
{
|
||||
if (!m_inputFile)
|
||||
m_inputFile = stdin;
|
||||
}
|
||||
|
||||
void CdbPromptThread::run()
|
||||
@@ -60,9 +65,17 @@ void CdbPromptThread::run()
|
||||
QString cmd;
|
||||
char buf[bufSize];
|
||||
std::putc('>', stdout);
|
||||
// When reading from an input file, switch to stdin after reading it out
|
||||
while (true) {
|
||||
if (std::fgets(buf, bufSize, stdin) == NULL)
|
||||
break;
|
||||
if (std::fgets(buf, bufSize, m_inputFile) == NULL) {
|
||||
if (m_inputFile == stdin) {
|
||||
break;
|
||||
} else {
|
||||
fclose(m_inputFile);
|
||||
m_inputFile = stdin;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
cmd += QString::fromLatin1(buf);
|
||||
if (cmd.endsWith(QLatin1Char('\n'))) {
|
||||
cmd.truncate(cmd.size() - 1);
|
||||
@@ -72,6 +85,8 @@ void CdbPromptThread::run()
|
||||
}
|
||||
std::putc('>', stdout);
|
||||
}
|
||||
if (m_inputFile != stdin)
|
||||
fclose(m_inputFile);
|
||||
}
|
||||
|
||||
// Determine the command
|
||||
@@ -95,6 +110,12 @@ static Command evaluateCommand(const QString &cmdToken)
|
||||
return Execution_StartBinary;
|
||||
case 'F':
|
||||
return Sync_PrintFrame;
|
||||
case 'P':
|
||||
return Sync_Python;
|
||||
case 'V':
|
||||
return Sync_OutputVersion;
|
||||
case 'W':
|
||||
return WaitCommand;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -126,6 +147,12 @@ static Command parseCommand(QString *s)
|
||||
return rc;
|
||||
}
|
||||
|
||||
void CdbPromptThread::notifyDebugEvent()
|
||||
{
|
||||
if (m_waitingForDebugEvent)
|
||||
m_debugEventWaitCondition.wakeAll();
|
||||
}
|
||||
|
||||
bool CdbPromptThread::handleCommand(QString cmd)
|
||||
{
|
||||
if (cmd == QLatin1String("q"))
|
||||
@@ -135,6 +162,16 @@ bool CdbPromptThread::handleCommand(QString cmd)
|
||||
return true;
|
||||
}
|
||||
const Command c = parseCommand(&cmd);
|
||||
if (c == WaitCommand) {
|
||||
std::fputs("Waiting for debug event\n", stdout);
|
||||
m_debugEventMutex.lock();
|
||||
m_waitingForDebugEvent = true;
|
||||
m_debugEventWaitCondition.wait(&m_debugEventMutex);
|
||||
m_debugEventMutex.unlock();
|
||||
std::fputs("Debug event received\n", stdout);
|
||||
m_waitingForDebugEvent = false;
|
||||
return true;
|
||||
}
|
||||
if (c & AsyncCommand) {
|
||||
emit asyncCommand(c, cmd);
|
||||
return true;
|
||||
|
||||
@@ -31,6 +31,10 @@
|
||||
#define PROMPTTHREAD_H
|
||||
|
||||
#include <QtCore/QThread>
|
||||
#include <QtCore/QWaitCondition>
|
||||
#include <QtCore/QMutex>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
enum CommandTypeFlags {
|
||||
// Interrupt or something.
|
||||
@@ -51,18 +55,24 @@ enum Command {
|
||||
Sync_QueueBreakPoint = SyncCommand|3,
|
||||
Sync_ListBreakPoints = SyncCommand|4,
|
||||
Sync_PrintFrame = SyncCommand|5,
|
||||
Sync_OutputVersion = SyncCommand|6,
|
||||
Sync_Python = SyncCommand|7,
|
||||
Execution_Go = ExecutionCommand|1,
|
||||
Execution_StartBinary = ExecutionCommand|2
|
||||
Execution_StartBinary = ExecutionCommand|2,
|
||||
WaitCommand = 0xFFFF
|
||||
};
|
||||
|
||||
class CdbPromptThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CdbPromptThread(QObject *parent = 0);
|
||||
explicit CdbPromptThread(FILE *file, QObject *parent = 0);
|
||||
|
||||
virtual void run();
|
||||
|
||||
public slots:
|
||||
void notifyDebugEvent();
|
||||
|
||||
signals:
|
||||
void asyncCommand(int command, const QString &arg);
|
||||
void syncCommand(int command, const QString &arg);
|
||||
@@ -70,6 +80,10 @@ signals:
|
||||
|
||||
private:
|
||||
bool handleCommand(QString);
|
||||
QWaitCondition m_debugEventWaitCondition;
|
||||
QMutex m_debugEventMutex;
|
||||
bool m_waitingForDebugEvent;
|
||||
FILE *m_inputFile;
|
||||
};
|
||||
|
||||
#endif // PROMPTTHREAD_H
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
TEMPLATE = app
|
||||
TARGET =
|
||||
DEPENDPATH += .
|
||||
INCLUDEPATH += .
|
||||
|
||||
DEFINES +=
|
||||
|
||||
LIBS += Dbghelp.lib dbgeng.lib
|
||||
|
||||
HEADERS += mainwindow.h \
|
||||
debugger.h \
|
||||
outputcallback.h \
|
||||
windbgeventcallback.h \
|
||||
windbgthread.h
|
||||
FORMS += mainwindow.ui
|
||||
SOURCES += main.cpp mainwindow.cpp \
|
||||
debugger.cpp \
|
||||
outputcallback.cpp \
|
||||
windbgeventcallback.cpp \
|
||||
windbgthread.cpp
|
||||
@@ -1,305 +0,0 @@
|
||||
#include "debugger.h"
|
||||
#include "windbgthread.h"
|
||||
#include "outputcallback.h"
|
||||
#include "windbgeventcallback.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QTimerEvent>
|
||||
#include <QDebug>
|
||||
|
||||
Debugger::Debugger(QObject* parent)
|
||||
: QObject(parent),
|
||||
m_callbackEvent(this),
|
||||
m_watchTimer(-1),
|
||||
m_hDebuggeeProcess(0)
|
||||
{
|
||||
HRESULT hr;
|
||||
hr = DebugCreate( __uuidof(IDebugClient5), reinterpret_cast<void**>(&m_pDebugClient));
|
||||
if (FAILED(hr)) m_pDebugClient = 0;
|
||||
hr = DebugCreate( __uuidof(IDebugControl4), reinterpret_cast<void**>(&m_pDebugControl));
|
||||
if (FAILED(hr)) m_pDebugControl = 0;
|
||||
hr = DebugCreate( __uuidof(IDebugSystemObjects4), reinterpret_cast<void**>(&m_pDebugSystemObjects));
|
||||
if (FAILED(hr)) m_pDebugSystemObjects = 0;
|
||||
hr = DebugCreate( __uuidof(IDebugSymbols3), reinterpret_cast<void**>(&m_pDebugSymbols));
|
||||
if (FAILED(hr)) m_pDebugSymbols = 0;
|
||||
hr = DebugCreate( __uuidof(IDebugRegisters2), reinterpret_cast<void**>(&m_pDebugRegisters));
|
||||
if (FAILED(hr)) m_pDebugRegisters = 0;
|
||||
|
||||
m_pDebugClient->SetOutputCallbacks(&g_outputCallbacks);
|
||||
m_pDebugClient->SetEventCallbacks(&m_callbackEvent);
|
||||
}
|
||||
|
||||
Debugger::~Debugger()
|
||||
{
|
||||
killTimer(m_watchTimer);
|
||||
if (m_pDebugClient)
|
||||
m_pDebugClient->Release();
|
||||
if (m_pDebugControl)
|
||||
m_pDebugControl->Release();
|
||||
if (m_pDebugSystemObjects)
|
||||
m_pDebugSystemObjects->Release();
|
||||
if (m_pDebugSymbols)
|
||||
m_pDebugSymbols->Release();
|
||||
if (m_pDebugRegisters)
|
||||
m_pDebugRegisters->Release();
|
||||
}
|
||||
|
||||
void Debugger::timerEvent(QTimerEvent* te)
|
||||
{
|
||||
if (te->timerId() != m_watchTimer)
|
||||
return;
|
||||
|
||||
HRESULT hr;
|
||||
hr = m_pDebugControl->WaitForEvent(0, 1);
|
||||
switch (hr) {
|
||||
case S_OK:
|
||||
//qDebug() << "S_OK";
|
||||
//hr = m_pDebugControl->SetExecutionStatus(DEBUG_STATUS_BREAK);
|
||||
killTimer(m_watchTimer);
|
||||
m_watchTimer = -1;
|
||||
handleDebugEvent();
|
||||
break;
|
||||
case S_FALSE:
|
||||
//qDebug() << "S_FALSE";
|
||||
break;
|
||||
case E_PENDING:
|
||||
qDebug() << "S_PENDING";
|
||||
break;
|
||||
case E_UNEXPECTED:
|
||||
killTimer(m_watchTimer);
|
||||
m_watchTimer = -1;
|
||||
break;
|
||||
case E_FAIL:
|
||||
qDebug() << "E_FAIL";
|
||||
break;
|
||||
default:
|
||||
qDebug() << "asser welljuh";
|
||||
}
|
||||
}
|
||||
|
||||
void Debugger::openProcess(const QString& filename)
|
||||
{
|
||||
DEBUG_CREATE_PROCESS_OPTIONS dbgopts;
|
||||
memset(&dbgopts, 0, sizeof(dbgopts));
|
||||
dbgopts.CreateFlags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
QFileInfo fi(filename);
|
||||
m_pDebugSymbols->AppendImagePathWide(fi.absolutePath().replace('/','\\').utf16());
|
||||
//m_pDebugSymbols->AppendSymbolPathWide(fi.absolutePath().replace('/','\\').utf16());
|
||||
//m_pDebugSymbols->AppendSymbolPathWide(L"D:\\dev\\qt\\4.4.3\\lib");
|
||||
m_pDebugSymbols->SetSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_DEBUG | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS);
|
||||
//m_pDebugSymbols->AddSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS | SYMOPT_NO_IMAGE_SEARCH);
|
||||
|
||||
hr = m_pDebugClient->CreateProcess2Wide(NULL,
|
||||
const_cast<PWSTR>(filename.utf16()),
|
||||
&dbgopts,
|
||||
sizeof(dbgopts),
|
||||
NULL, // TODO: think about the initial directory
|
||||
NULL); // TODO: think about setting the environment
|
||||
if (FAILED(hr)) {
|
||||
qWarning("CreateProcess2Wide failed");
|
||||
return;
|
||||
}
|
||||
|
||||
m_watchTimer = startTimer(0);
|
||||
}
|
||||
|
||||
void Debugger::closeProcess()
|
||||
{
|
||||
m_pDebugClient->TerminateCurrentProcess();
|
||||
}
|
||||
|
||||
void Debugger::breakAtCurrentPosition()
|
||||
{
|
||||
if (!m_hDebuggeeProcess)
|
||||
return;
|
||||
if (!DebugBreakProcess(m_hDebuggeeProcess))
|
||||
qWarning("DebugBreakProcess failed.");
|
||||
}
|
||||
|
||||
void Debugger::continueProcess()
|
||||
{
|
||||
m_watchTimer = startTimer(0);
|
||||
}
|
||||
|
||||
void Debugger::handleDebugEvent()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
ULONG numberOfThreads;
|
||||
hr = m_pDebugSystemObjects->GetNumberThreads(&numberOfThreads);
|
||||
const ULONG maxThreadIds = 200;
|
||||
ULONG threadIds[maxThreadIds];
|
||||
ULONG biggestThreadId = qMin(maxThreadIds, numberOfThreads - 1);
|
||||
hr = m_pDebugSystemObjects->GetThreadIdsByIndex(0, biggestThreadId, threadIds, 0);
|
||||
for (ULONG threadId = 0; threadId <= biggestThreadId; ++threadId) {
|
||||
qDebug() << "dumping stack for thread" << threadId;
|
||||
|
||||
m_pDebugSystemObjects->SetCurrentThreadId(threadId);
|
||||
|
||||
ULONG64 frameOffset, instructionOffset, stackOffset;
|
||||
if (FAILED(m_pDebugRegisters->GetFrameOffset2(DEBUG_REGSRC_DEBUGGEE, &frameOffset)) ||
|
||||
FAILED(m_pDebugRegisters->GetInstructionOffset2(DEBUG_REGSRC_DEBUGGEE, &instructionOffset)) ||
|
||||
FAILED(m_pDebugRegisters->GetStackOffset2(DEBUG_REGSRC_DEBUGGEE, &stackOffset)))
|
||||
{
|
||||
frameOffset = instructionOffset = stackOffset = 0;
|
||||
}
|
||||
//frameOffset = instructionOffset = stackOffset = 0;
|
||||
|
||||
const ULONG numFrames = 100;
|
||||
ULONG numFramesFilled = 0;
|
||||
DEBUG_STACK_FRAME frames[numFrames];
|
||||
hr = m_pDebugControl->GetStackTrace(frameOffset, stackOffset, instructionOffset, frames, numFrames, &numFramesFilled);
|
||||
if (FAILED(hr))
|
||||
qDebug() << "GetStackTrace failed";
|
||||
|
||||
const size_t buflen = 1024;
|
||||
WCHAR wszBuf[buflen];
|
||||
for (ULONG i=0; i < numFramesFilled; ++i) {
|
||||
m_pDebugSymbols->GetNameByOffsetWide(frames[i].InstructionOffset, wszBuf, buflen, 0, 0);
|
||||
qDebug() << QString::fromUtf16(wszBuf);
|
||||
}
|
||||
|
||||
//m_pDebugSymbols->GetImagePathWide(wszBuf, buflen, 0);
|
||||
//qDebug() << "ImagePath" << QString::fromUtf16(wszBuf);
|
||||
//m_pDebugSymbols->GetSymbolPathWide(wszBuf, buflen, 0);
|
||||
//qDebug() << "SymbolPath" << QString::fromUtf16(wszBuf);
|
||||
|
||||
//m_pDebugControl->OutputStackTrace(DEBUG_OUTCTL_THIS_CLIENT, 0, 2, DEBUG_STACK_FRAME_ADDRESSES | DEBUG_STACK_COLUMN_NAMES | DEBUG_STACK_FRAME_NUMBERS);
|
||||
//m_pDebugControl->OutputStackTrace(DEBUG_OUTCTL_THIS_CLIENT, frames, numFramesFilled, DEBUG_STACK_SOURCE_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
void Debugger::handleCreateProcessEvent(DEBUG_EVENT* e)
|
||||
{
|
||||
//qDebug() << "CREATE_PROCESS_DEBUG_EVENT";
|
||||
//m_hDebuggeeProcess = e->u.CreateProcessInfo.hProcess;
|
||||
//m_hDebuggeeThread = e->u.CreateProcessInfo.hThread;
|
||||
//m_hDebuggeeImage = e->u.CreateProcessInfo.hFile;
|
||||
|
||||
//QFileInfo fi(m_pDbgProcess->processFileName());
|
||||
//BOOL bSuccess;
|
||||
//bSuccess = SymInitialize(m_hDebuggeeProcess, fi.absolutePath().utf16(), FALSE);
|
||||
//if (!bSuccess)
|
||||
// qWarning("SymInitialize failed");
|
||||
//else {
|
||||
// SymSetOptions(SYMOPT_DEBUG | SYMOPT_LOAD_LINES | SYMOPT_FAIL_CRITICAL_ERRORS);
|
||||
// if (!SymLoadModule64(m_hDebuggeeProcess, m_hDebuggeeImage, NULL, NULL, NULL, NULL))
|
||||
// qDebug() << "SymLoadModule64 failed w/ error code" << GetLastError();
|
||||
//}
|
||||
}
|
||||
|
||||
void Debugger::handleExceptionEvent(DEBUG_EVENT* e)
|
||||
{
|
||||
//BOOL bSuccess;
|
||||
//SuspendThread(m_hDebuggeeThread);
|
||||
|
||||
//CONTEXT context;
|
||||
//memset(&context, 0, sizeof(context));
|
||||
//context.ContextFlags = CONTEXT_ALL;
|
||||
//bSuccess = GetThreadContext(m_hDebuggeeThread, &context);
|
||||
//if (!bSuccess)
|
||||
// qDebug() << "GetThreadContext failed w/ error code" << GetLastError();
|
||||
//ResumeThread(m_hDebuggeeThread);
|
||||
|
||||
//STACKFRAME64 stackFrame;
|
||||
//stackFrame.AddrPC.Offset = context.Eip;
|
||||
//stackFrame.AddrPC.Mode = AddrModeFlat;
|
||||
//stackFrame.AddrFrame.Offset = context.Ebp;
|
||||
//stackFrame.AddrFrame.Mode = AddrModeFlat;
|
||||
//stackFrame.AddrStack.Offset = context.Esp;
|
||||
//stackFrame.AddrStack.Mode = AddrModeFlat;
|
||||
//m_currentStackTrace.clear();
|
||||
|
||||
//do {
|
||||
// StackFrame sf;
|
||||
// bSuccess = StackWalk64(IMAGE_FILE_MACHINE_I386, m_hDebuggeeProcess, m_hDebuggeeThread, &stackFrame,
|
||||
// &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL);
|
||||
// if (bSuccess) {
|
||||
// qDebug() << "StackWalk";
|
||||
// IMAGEHLP_MODULE64 moduleInfo;
|
||||
// moduleInfo.SizeOfStruct = sizeof(moduleInfo);
|
||||
// if (SymGetModuleInfo64(m_hDebuggeeProcess, stackFrame.AddrPC.Offset, &moduleInfo))
|
||||
// qDebug() << "SymGetModuleInfo64 success!";
|
||||
// else
|
||||
// qDebug() << "SymGetModuleInfo64 failed w/ error code" << GetLastError();
|
||||
// }
|
||||
|
||||
// if (stackFrame.AddrPC.Offset) {
|
||||
// DWORD64 dwDisplacement;
|
||||
// const size_t bufferSize = 200;
|
||||
// class MySymbol : public IMAGEHLP_SYMBOL64
|
||||
// {
|
||||
// public:
|
||||
// private:
|
||||
// char buffer[bufferSize];
|
||||
// };
|
||||
// MySymbol img;
|
||||
// ZeroMemory(&img, sizeof(img));
|
||||
// img.SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
||||
// img.MaxNameLength = bufferSize;
|
||||
|
||||
// BOOL bSuccess;
|
||||
// bSuccess = SymGetSymFromAddr64(m_hDebuggeeProcess,
|
||||
// stackFrame.AddrPC.Offset,
|
||||
// &dwDisplacement,
|
||||
// &img);
|
||||
// if (bSuccess) {
|
||||
// qDebug() << "SymGetSymFromAddr64:" << img.Name;
|
||||
// sf.symbol = QString::fromLocal8Bit(img.Name);
|
||||
// }
|
||||
// else
|
||||
// qDebug() << "SymGetSymFromAddr64 failed w/ error code" << GetLastError();
|
||||
// }
|
||||
|
||||
// if (stackFrame.AddrPC.Offset) {
|
||||
// DWORD dwDisplacement;
|
||||
// IMAGEHLP_LINE64 line;
|
||||
// ZeroMemory(&line, sizeof(line));
|
||||
// line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||
|
||||
// BOOL bSuccess;
|
||||
// bSuccess = SymGetLineFromAddr64(m_hDebuggeeProcess,
|
||||
// stackFrame.AddrPC.Offset,
|
||||
// &dwDisplacement,
|
||||
// &line);
|
||||
// if (bSuccess) {
|
||||
// //qDebug() << "SymGetLineFromAddr64:" << QString::fromUtf16((ushort*)line.FileName) << line.LineNumber;
|
||||
// sf.filename = QString::fromUtf16((ushort*)line.FileName);
|
||||
// sf.line = line.LineNumber;
|
||||
// } else
|
||||
// qDebug() << "SymGetLineFromAddr64 failed w/ error code" << GetLastError();
|
||||
|
||||
// m_currentStackTrace.append(sf);
|
||||
// }
|
||||
//} while (bSuccess);
|
||||
|
||||
//emit debuggeePaused();
|
||||
}
|
||||
|
||||
void Debugger::handleOutputDebugStringEvent(DEBUG_EVENT* e)
|
||||
{
|
||||
//qDebug() << "OUTPUT_DEBUG_STRING_EVENT";
|
||||
//BOOL bSuccess;
|
||||
//SIZE_T nNumberOfBytesRead;
|
||||
//void* buffer;
|
||||
//QString result;
|
||||
//if (e->u.DebugString.fUnicode) {
|
||||
// buffer = malloc(e->u.DebugString.nDebugStringLength * sizeof(WCHAR));
|
||||
//} else {
|
||||
// buffer = malloc(e->u.DebugString.nDebugStringLength * sizeof(char));
|
||||
//}
|
||||
|
||||
//bSuccess = ReadProcessMemory(m_hDebuggeeProcess, e->u.DebugString.lpDebugStringData,
|
||||
// buffer, e->u.DebugString.nDebugStringLength, &nNumberOfBytesRead);
|
||||
//if (bSuccess) {
|
||||
// if (e->u.DebugString.fUnicode)
|
||||
// result = QString::fromUtf16(reinterpret_cast<ushort*>(buffer), nNumberOfBytesRead);
|
||||
// else
|
||||
// result = QString::fromLocal8Bit(reinterpret_cast<char*>(buffer), nNumberOfBytesRead);
|
||||
// emit debugOutput(result);
|
||||
//}
|
||||
//free(buffer);
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "windbgeventcallback.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QVector>
|
||||
|
||||
#define DBGHELP_TRANSLATE_TCHAR
|
||||
#include <Dbghelp.h>
|
||||
|
||||
class WinDbgThread;
|
||||
|
||||
class Debugger : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Debugger(QObject* parent = 0);
|
||||
~Debugger();
|
||||
|
||||
void openProcess(const QString& filename);
|
||||
void closeProcess();
|
||||
void breakAtCurrentPosition();
|
||||
void continueProcess();
|
||||
|
||||
struct StackFrame
|
||||
{
|
||||
QString symbol;
|
||||
QString filename;
|
||||
uint line;
|
||||
};
|
||||
|
||||
typedef QVector<StackFrame> StackTrace;
|
||||
StackTrace stackTrace() { return m_currentStackTrace; }
|
||||
|
||||
signals:
|
||||
void debugOutput(const QString&);
|
||||
void debuggeePaused();
|
||||
|
||||
protected:
|
||||
void timerEvent(QTimerEvent*);
|
||||
|
||||
private:
|
||||
void handleDebugEvent();
|
||||
void handleCreateProcessEvent(DEBUG_EVENT* e);
|
||||
void handleExceptionEvent(DEBUG_EVENT* e);
|
||||
void handleOutputDebugStringEvent(DEBUG_EVENT* e);
|
||||
|
||||
private:
|
||||
HANDLE m_hDebuggeeProcess;
|
||||
HANDLE m_hDebuggeeThread;
|
||||
HANDLE m_hDebuggeeImage;
|
||||
StackTrace m_currentStackTrace;
|
||||
//DWORD64 m_dwModuleBaseAddress;
|
||||
|
||||
int m_watchTimer;
|
||||
IDebugClient5* m_pDebugClient;
|
||||
IDebugControl4* m_pDebugControl;
|
||||
IDebugSystemObjects4* m_pDebugSystemObjects;
|
||||
IDebugSymbols3* m_pDebugSymbols;
|
||||
IDebugRegisters2* m_pDebugRegisters;
|
||||
WinDbgEventCallback m_callbackEvent;
|
||||
|
||||
//struct ThreadInfo
|
||||
//{
|
||||
// ULONG64 handle, dataOffset, startOffset;
|
||||
//};
|
||||
|
||||
//QVector<ThreadInfo> m_threadlist;
|
||||
|
||||
friend class WinDbgEventCallback;
|
||||
};
|
||||
@@ -1,11 +0,0 @@
|
||||
#include "mainwindow.h"
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
MainWindow mw;
|
||||
if (argc >= 2) mw.setDebuggee(argv[1]);
|
||||
mw.show();
|
||||
return app.exec();
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
#include "mainwindow.h"
|
||||
#include <QFileDialog>
|
||||
#include <QTextStream>
|
||||
#include <QDebug>
|
||||
|
||||
MainWindow::MainWindow()
|
||||
: QMainWindow(0, 0)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
connect(&m_debugger, SIGNAL(debugOutput(const QString&)), SLOT(appendOutput(const QString&)));
|
||||
connect(&m_debugger, SIGNAL(debuggeePaused()), SLOT(onDebuggeePaused()));
|
||||
}
|
||||
|
||||
void MainWindow::setDebuggee(const QString& filename)
|
||||
{
|
||||
m_debugger.openProcess(filename);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionOpen_triggered()
|
||||
{
|
||||
QString exeName;
|
||||
exeName = QFileDialog::getOpenFileName(this, "Open Executable", ".", "*.exe");
|
||||
if (!exeName.isNull())
|
||||
m_debugger.openProcess(exeName);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionExit_triggered()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionBreak_triggered()
|
||||
{
|
||||
m_debugger.breakAtCurrentPosition();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionRun_triggered()
|
||||
{
|
||||
m_debugger.continueProcess();
|
||||
}
|
||||
|
||||
void MainWindow::on_lstStack_itemClicked(QListWidgetItem* item)
|
||||
{
|
||||
Debugger::StackFrame sf = m_stackTrace[ lstStack->row(item) ];
|
||||
QFile f(sf.filename);
|
||||
if (!f.exists())
|
||||
return;
|
||||
|
||||
f.open(QFile::ReadOnly);
|
||||
QTextStream ts(&f);
|
||||
int cursorPos = 0;
|
||||
int currentLine = 0;
|
||||
QString fullText;
|
||||
do {
|
||||
QString strLine = ts.readLine();
|
||||
currentLine++;
|
||||
if (currentLine < sf.line)
|
||||
cursorPos += strLine.length();
|
||||
fullText.append(strLine + "\n");
|
||||
} while (!ts.atEnd());
|
||||
codeWindow->setPlainText(fullText);
|
||||
|
||||
//QList<QTextEdit::ExtraSelection> extraSelections;
|
||||
//extraSelections.append(QTextEdit::ExtraSelection());
|
||||
|
||||
//QTextEdit::ExtraSelection& exsel = extraSelections.first();
|
||||
//exsel.cursor.setPosition(cursorPos, QTextCursor::MoveAnchor);
|
||||
//exsel.cursor.select(QTextCursor::LineUnderCursor);
|
||||
//exsel.format.setBackground(Qt::red);
|
||||
//exsel.format.setFontUnderline(true);
|
||||
//codeWindow->setExtraSelections(extraSelections);
|
||||
}
|
||||
|
||||
void MainWindow::appendOutput(const QString& str)
|
||||
{
|
||||
teOutput->setPlainText(teOutput->toPlainText() + str);
|
||||
}
|
||||
|
||||
void MainWindow::onDebuggeePaused()
|
||||
{
|
||||
lstStack->clear();
|
||||
m_stackTrace = m_debugger.stackTrace();
|
||||
foreach (Debugger::StackFrame sf, m_stackTrace) {
|
||||
QString str = sf.symbol;
|
||||
if (!sf.filename.isEmpty())
|
||||
str.append(" at " + sf.filename + ":" + QString::number(sf.line));
|
||||
lstStack->addItem(str);
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ui_mainwindow.h"
|
||||
#include "debugger.h"
|
||||
|
||||
class MainWindow : public QMainWindow, private Ui_MainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MainWindow();
|
||||
|
||||
void setDebuggee(const QString& filename);
|
||||
|
||||
private slots:
|
||||
void on_actionOpen_triggered();
|
||||
void on_actionExit_triggered();
|
||||
void on_actionBreak_triggered();
|
||||
void on_actionRun_triggered();
|
||||
void on_lstStack_itemClicked(QListWidgetItem*);
|
||||
void appendOutput(const QString&);
|
||||
void onDebuggeePaused();
|
||||
|
||||
private:
|
||||
Debugger m_debugger;
|
||||
Debugger::StackTrace m_stackTrace;
|
||||
};
|
||||
@@ -1,174 +0,0 @@
|
||||
<ui version="4.0" >
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>599</width>
|
||||
<height>606</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget" >
|
||||
<layout class="QVBoxLayout" name="verticalLayout" >
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="codeWindow" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="undoRedoEnabled" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="lineWrapMode" >
|
||||
<enum>QPlainTextEdit::NoWrap</enum>
|
||||
</property>
|
||||
<property name="readOnly" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags" >
|
||||
<set>Qt::NoTextInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget" >
|
||||
<property name="sizePolicy" >
|
||||
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="currentIndex" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab" >
|
||||
<attribute name="title" >
|
||||
<string>Threads</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" >
|
||||
<item>
|
||||
<widget class="QListWidget" name="lstThreads" />
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2" >
|
||||
<attribute name="title" >
|
||||
<string>Stack</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2" >
|
||||
<item>
|
||||
<widget class="QListWidget" name="lstStack" />
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_3" >
|
||||
<attribute name="title" >
|
||||
<string>Output</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3" >
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="teOutput" />
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>599</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_Debug" >
|
||||
<property name="title" >
|
||||
<string>&Debug</string>
|
||||
</property>
|
||||
<addaction name="actionRun" />
|
||||
<addaction name="actionBreak" />
|
||||
<addaction name="actionStepOver" />
|
||||
<addaction name="actionStopDebugging" />
|
||||
<addaction name="actionStepInto" />
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_File" >
|
||||
<property name="title" >
|
||||
<string>&File</string>
|
||||
</property>
|
||||
<addaction name="actionOpen" />
|
||||
<addaction name="actionClose" />
|
||||
<addaction name="separator" />
|
||||
<addaction name="actionExit" />
|
||||
</widget>
|
||||
<addaction name="menu_File" />
|
||||
<addaction name="menu_Debug" />
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar" />
|
||||
<action name="actionOpen" >
|
||||
<property name="text" >
|
||||
<string>&Open...</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Ctrl+O</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionClose" >
|
||||
<property name="text" >
|
||||
<string>&Close</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExit" >
|
||||
<property name="text" >
|
||||
<string>E&xit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRun" >
|
||||
<property name="text" >
|
||||
<string>&Run</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>F5</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionBreak" >
|
||||
<property name="text" >
|
||||
<string>&Break</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionStepOver" >
|
||||
<property name="text" >
|
||||
<string>Step over</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>F10</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionStepInto" >
|
||||
<property name="text" >
|
||||
<string>Step into</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>F11</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionStopDebugging" >
|
||||
<property name="text" >
|
||||
<string>Stop debugging</string>
|
||||
</property>
|
||||
<property name="shortcut" >
|
||||
<string>Shift+F5</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,61 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <windows.h>
|
||||
#include <dbgeng.h>
|
||||
|
||||
#include "outputcallback.h"
|
||||
|
||||
WinDbgOutputCallback g_outputCallbacks;
|
||||
|
||||
STDMETHODIMP
|
||||
WinDbgOutputCallback::QueryInterface(
|
||||
THIS_
|
||||
IN REFIID InterfaceId,
|
||||
OUT PVOID* Interface
|
||||
)
|
||||
{
|
||||
*Interface = NULL;
|
||||
|
||||
if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
|
||||
IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacks)))
|
||||
{
|
||||
*Interface = (IDebugOutputCallbacks *)this;
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG)
|
||||
WinDbgOutputCallback::AddRef(
|
||||
THIS
|
||||
)
|
||||
{
|
||||
// This class is designed to be static so
|
||||
// there's no true refcount.
|
||||
return 1;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG)
|
||||
WinDbgOutputCallback::Release(
|
||||
THIS
|
||||
)
|
||||
{
|
||||
// This class is designed to be static so
|
||||
// there's no true refcount.
|
||||
return 0;
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
WinDbgOutputCallback::Output(
|
||||
THIS_
|
||||
IN ULONG Mask,
|
||||
IN PCSTR Text
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(Mask);
|
||||
fputs(Text, stdout);
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
#ifndef __OUT_HPP__
|
||||
#define __OUT_HPP__
|
||||
|
||||
class WinDbgOutputCallback : public IDebugOutputCallbacks
|
||||
{
|
||||
public:
|
||||
// IUnknown.
|
||||
STDMETHOD(QueryInterface)(
|
||||
THIS_
|
||||
IN REFIID InterfaceId,
|
||||
OUT PVOID* Interface
|
||||
);
|
||||
STDMETHOD_(ULONG, AddRef)(
|
||||
THIS
|
||||
);
|
||||
STDMETHOD_(ULONG, Release)(
|
||||
THIS
|
||||
);
|
||||
|
||||
// IDebugOutputCallbacks.
|
||||
STDMETHOD(Output)(
|
||||
THIS_
|
||||
IN ULONG Mask,
|
||||
IN PCSTR Text
|
||||
);
|
||||
};
|
||||
|
||||
extern WinDbgOutputCallback g_outputCallbacks;
|
||||
|
||||
#endif // #ifndef __OUT_HPP__
|
||||
@@ -1,186 +0,0 @@
|
||||
#include "windbgeventcallback.h"
|
||||
#include "debugger.h"
|
||||
|
||||
STDMETHODIMP
|
||||
WinDbgEventCallback::QueryInterface(
|
||||
THIS_
|
||||
IN REFIID InterfaceId,
|
||||
OUT PVOID* Interface
|
||||
)
|
||||
{
|
||||
*Interface = NULL;
|
||||
|
||||
if (IsEqualIID(InterfaceId, __uuidof(IUnknown)) ||
|
||||
IsEqualIID(InterfaceId, __uuidof(IDebugOutputCallbacks)))
|
||||
{
|
||||
*Interface = (IDebugOutputCallbacks *)this;
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG)
|
||||
WinDbgEventCallback::AddRef(
|
||||
THIS
|
||||
)
|
||||
{
|
||||
// This class is designed to be static so
|
||||
// there's no true refcount.
|
||||
return 1;
|
||||
}
|
||||
|
||||
STDMETHODIMP_(ULONG)
|
||||
WinDbgEventCallback::Release(
|
||||
THIS
|
||||
)
|
||||
{
|
||||
// This class is designed to be static so
|
||||
// there's no true refcount.
|
||||
return 0;
|
||||
}
|
||||
|
||||
STDMETHODIMP WinDbgEventCallback::GetInterestMask(
|
||||
THIS_
|
||||
__out PULONG Mask
|
||||
)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP WinDbgEventCallback::Breakpoint(
|
||||
THIS_
|
||||
__in PDEBUG_BREAKPOINT Bp
|
||||
)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP WinDbgEventCallback::Exception(
|
||||
THIS_
|
||||
__in PEXCEPTION_RECORD64 Exception,
|
||||
__in ULONG FirstChance
|
||||
)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP WinDbgEventCallback::CreateThread(
|
||||
THIS_
|
||||
__in ULONG64 Handle,
|
||||
__in ULONG64 DataOffset,
|
||||
__in ULONG64 StartOffset
|
||||
)
|
||||
{
|
||||
//Debugger::ThreadInfo ti;
|
||||
//ti.handle = Handle;
|
||||
//ti.dataOffset = DataOffset;
|
||||
//ti.startOffset = StartOffset;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP WinDbgEventCallback::ExitThread(
|
||||
THIS_
|
||||
__in ULONG ExitCode
|
||||
)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP WinDbgEventCallback::CreateProcess(
|
||||
THIS_
|
||||
__in ULONG64 ImageFileHandle,
|
||||
__in ULONG64 Handle,
|
||||
__in ULONG64 BaseOffset,
|
||||
__in ULONG ModuleSize,
|
||||
__in_opt PCSTR ModuleName,
|
||||
__in_opt PCSTR ImageName,
|
||||
__in ULONG CheckSum,
|
||||
__in ULONG TimeDateStamp,
|
||||
__in ULONG64 InitialThreadHandle,
|
||||
__in ULONG64 ThreadDataOffset,
|
||||
__in ULONG64 StartOffset
|
||||
)
|
||||
{
|
||||
m_pDebugger->m_hDebuggeeProcess = (HANDLE)Handle;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP WinDbgEventCallback::ExitProcess(
|
||||
THIS_
|
||||
__in ULONG ExitCode
|
||||
)
|
||||
{
|
||||
m_pDebugger->m_hDebuggeeProcess = 0;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP WinDbgEventCallback::LoadModule(
|
||||
THIS_
|
||||
__in ULONG64 ImageFileHandle,
|
||||
__in ULONG64 BaseOffset,
|
||||
__in ULONG ModuleSize,
|
||||
__in_opt PCSTR ModuleName,
|
||||
__in_opt PCSTR ImageName,
|
||||
__in ULONG CheckSum,
|
||||
__in ULONG TimeDateStamp
|
||||
)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP WinDbgEventCallback::UnloadModule(
|
||||
THIS_
|
||||
__in_opt PCSTR ImageBaseName,
|
||||
__in ULONG64 BaseOffset
|
||||
)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP WinDbgEventCallback::SystemError(
|
||||
THIS_
|
||||
__in ULONG Error,
|
||||
__in ULONG Level
|
||||
)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP WinDbgEventCallback::SessionStatus(
|
||||
THIS_
|
||||
__in ULONG Status
|
||||
)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP WinDbgEventCallback::ChangeDebuggeeState(
|
||||
THIS_
|
||||
__in ULONG Flags,
|
||||
__in ULONG64 Argument
|
||||
)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP WinDbgEventCallback::ChangeEngineState(
|
||||
THIS_
|
||||
__in ULONG Flags,
|
||||
__in ULONG64 Argument
|
||||
)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP WinDbgEventCallback::ChangeSymbolState(
|
||||
THIS_
|
||||
__in ULONG Flags,
|
||||
__in ULONG64 Argument
|
||||
)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <dbgeng.h>
|
||||
|
||||
class Debugger;
|
||||
|
||||
class WinDbgEventCallback : public IDebugEventCallbacks
|
||||
{
|
||||
public:
|
||||
WinDbgEventCallback(Debugger* dbg)
|
||||
: m_pDebugger(dbg)
|
||||
{}
|
||||
|
||||
// IUnknown.
|
||||
STDMETHOD(QueryInterface)(
|
||||
THIS_
|
||||
IN REFIID InterfaceId,
|
||||
OUT PVOID* Interface
|
||||
);
|
||||
STDMETHOD_(ULONG, AddRef)(
|
||||
THIS
|
||||
);
|
||||
STDMETHOD_(ULONG, Release)(
|
||||
THIS
|
||||
);
|
||||
|
||||
// IDebugEventCallbacks.
|
||||
|
||||
STDMETHOD(GetInterestMask)(
|
||||
THIS_
|
||||
__out PULONG Mask
|
||||
);
|
||||
|
||||
STDMETHOD(Breakpoint)(
|
||||
THIS_
|
||||
__in PDEBUG_BREAKPOINT Bp
|
||||
);
|
||||
|
||||
STDMETHOD(Exception)(
|
||||
THIS_
|
||||
__in PEXCEPTION_RECORD64 Exception,
|
||||
__in ULONG FirstChance
|
||||
);
|
||||
|
||||
STDMETHOD(CreateThread)(
|
||||
THIS_
|
||||
__in ULONG64 Handle,
|
||||
__in ULONG64 DataOffset,
|
||||
__in ULONG64 StartOffset
|
||||
);
|
||||
STDMETHOD(ExitThread)(
|
||||
THIS_
|
||||
__in ULONG ExitCode
|
||||
);
|
||||
|
||||
STDMETHOD(CreateProcess)(
|
||||
THIS_
|
||||
__in ULONG64 ImageFileHandle,
|
||||
__in ULONG64 Handle,
|
||||
__in ULONG64 BaseOffset,
|
||||
__in ULONG ModuleSize,
|
||||
__in_opt PCSTR ModuleName,
|
||||
__in_opt PCSTR ImageName,
|
||||
__in ULONG CheckSum,
|
||||
__in ULONG TimeDateStamp,
|
||||
__in ULONG64 InitialThreadHandle,
|
||||
__in ULONG64 ThreadDataOffset,
|
||||
__in ULONG64 StartOffset
|
||||
);
|
||||
|
||||
STDMETHOD(ExitProcess)(
|
||||
THIS_
|
||||
__in ULONG ExitCode
|
||||
);
|
||||
|
||||
STDMETHOD(LoadModule)(
|
||||
THIS_
|
||||
__in ULONG64 ImageFileHandle,
|
||||
__in ULONG64 BaseOffset,
|
||||
__in ULONG ModuleSize,
|
||||
__in_opt PCSTR ModuleName,
|
||||
__in_opt PCSTR ImageName,
|
||||
__in ULONG CheckSum,
|
||||
__in ULONG TimeDateStamp
|
||||
);
|
||||
|
||||
STDMETHOD(UnloadModule)(
|
||||
THIS_
|
||||
__in_opt PCSTR ImageBaseName,
|
||||
__in ULONG64 BaseOffset
|
||||
);
|
||||
|
||||
STDMETHOD(SystemError)(
|
||||
THIS_
|
||||
__in ULONG Error,
|
||||
__in ULONG Level
|
||||
);
|
||||
|
||||
STDMETHOD(SessionStatus)(
|
||||
THIS_
|
||||
__in ULONG Status
|
||||
);
|
||||
|
||||
STDMETHOD(ChangeDebuggeeState)(
|
||||
THIS_
|
||||
__in ULONG Flags,
|
||||
__in ULONG64 Argument
|
||||
);
|
||||
|
||||
STDMETHOD(ChangeEngineState)(
|
||||
THIS_
|
||||
__in ULONG Flags,
|
||||
__in ULONG64 Argument
|
||||
);
|
||||
|
||||
STDMETHOD(ChangeSymbolState)(
|
||||
THIS_
|
||||
__in ULONG Flags,
|
||||
__in ULONG64 Argument
|
||||
);
|
||||
|
||||
private:
|
||||
Debugger* m_pDebugger;
|
||||
};
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
#include "windbgthread.h"
|
||||
#include <QDebug>
|
||||
|
||||
#define DBGHELP_TRANSLATE_TCHAR
|
||||
#include <Dbghelp.h>
|
||||
|
||||
WinDbgThread::WinDbgThread(QObject* parent)
|
||||
: QThread(parent),
|
||||
m_state(Idle)
|
||||
{
|
||||
}
|
||||
|
||||
WinDbgThread::~WinDbgThread()
|
||||
{
|
||||
stopProcess();
|
||||
}
|
||||
|
||||
void WinDbgThread::startProcess(const QString& filename)
|
||||
{
|
||||
stopProcess();
|
||||
m_bOwnsProcess = true;
|
||||
m_processFileName = filename;
|
||||
m_pi.dwProcessId = 0;
|
||||
QThread::start();
|
||||
}
|
||||
|
||||
void WinDbgThread::stopProcess()
|
||||
{
|
||||
if (!QThread::isRunning())
|
||||
return;
|
||||
|
||||
switch (m_state)
|
||||
{
|
||||
case ProcessRunning:
|
||||
if (m_bOwnsProcess) {
|
||||
m_bOwnsProcess = false; // don't terminate in the loop again
|
||||
TerminateProcess(m_pi.hProcess, 0);
|
||||
}
|
||||
// don't break here
|
||||
case ProcessPaused:
|
||||
m_bAbortEventPollingLoop = true;
|
||||
resume();
|
||||
break;
|
||||
}
|
||||
QThread::wait(5000);
|
||||
if (QThread::isRunning()) {
|
||||
qWarning("WinDbgThread still running... terminating!");
|
||||
QThread::terminate();
|
||||
}
|
||||
}
|
||||
|
||||
void WinDbgThread::attachToProcess(DWORD processId)
|
||||
{
|
||||
m_bOwnsProcess = false;
|
||||
m_processFileName = QString();
|
||||
m_pi.dwProcessId = processId;
|
||||
QThread::start();
|
||||
}
|
||||
|
||||
void WinDbgThread::run()
|
||||
{
|
||||
qDebug() << "WinDbgThread started";
|
||||
// start process or attach process
|
||||
if (m_bOwnsProcess) {
|
||||
// create new process
|
||||
internalStartProcess();
|
||||
} else {
|
||||
// attach to process
|
||||
qWarning("attach to process not yet implemented");
|
||||
return;
|
||||
}
|
||||
|
||||
m_hThisThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, GetCurrentThreadId());
|
||||
if (!m_hThisThread) {
|
||||
qWarning("WinDbgThread: can't open thread handle");
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_EVENT debugEvent;
|
||||
m_bAbortEventPollingLoop = false;
|
||||
while (WaitForDebugEvent(&debugEvent, INFINITE)) {
|
||||
setState(ProcessPaused);
|
||||
emit debugEventOccured(&debugEvent);
|
||||
suspend();
|
||||
if (m_bAbortEventPollingLoop)
|
||||
break;
|
||||
ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);
|
||||
setState(ProcessRunning);
|
||||
}
|
||||
|
||||
setState(Idle);
|
||||
if (m_bOwnsProcess) {
|
||||
TerminateProcess(m_pi.hProcess, 0);
|
||||
}
|
||||
CloseHandle(m_pi.hProcess);
|
||||
CloseHandle(m_pi.hThread);
|
||||
CloseHandle(m_hThisThread);
|
||||
|
||||
qDebug() << "WinDbgThread finished";
|
||||
}
|
||||
|
||||
void WinDbgThread::continueProcess()
|
||||
{
|
||||
if (m_state == ProcessPaused)
|
||||
resume();
|
||||
}
|
||||
|
||||
void WinDbgThread::pauseProcess()
|
||||
{
|
||||
if (m_state == ProcessRunning)
|
||||
DebugBreakProcess(m_pi.hProcess);
|
||||
}
|
||||
|
||||
void WinDbgThread::internalStartProcess()
|
||||
{
|
||||
BOOL bSuccess;
|
||||
|
||||
STARTUPINFO si;
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
si.wShowWindow = TRUE;
|
||||
|
||||
ZeroMemory(&m_pi, sizeof(m_pi));
|
||||
|
||||
DWORD dwCreationFlags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
|
||||
bSuccess = CreateProcess(m_processFileName.utf16(), NULL, NULL, NULL, FALSE,
|
||||
dwCreationFlags,
|
||||
NULL, NULL, &si, &m_pi
|
||||
);
|
||||
|
||||
if (bSuccess)
|
||||
setState(ProcessRunning);
|
||||
else
|
||||
setState(Idle);
|
||||
}
|
||||
|
||||
void WinDbgThread::setState(State s)
|
||||
{
|
||||
m_state = s;
|
||||
}
|
||||
|
||||
void WinDbgThread::suspend()
|
||||
{
|
||||
SuspendThread(m_hThisThread);
|
||||
}
|
||||
|
||||
void WinDbgThread::resume()
|
||||
{
|
||||
ResumeThread(m_hThisThread);
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QThread>
|
||||
#include <windows.h>
|
||||
|
||||
class WinDbgThread : protected QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
WinDbgThread(QObject* parent = 0);
|
||||
~WinDbgThread();
|
||||
|
||||
void startProcess(const QString& filename);
|
||||
void attachToProcess(DWORD processId);
|
||||
void continueProcess();
|
||||
void pauseProcess();
|
||||
void stopProcess();
|
||||
const QString& processFileName() { return m_processFileName; }
|
||||
|
||||
QObject* asQObject() { return this; }
|
||||
//using QThread::isRunning;
|
||||
|
||||
signals:
|
||||
void debugEventOccured(void*);
|
||||
|
||||
protected:
|
||||
void run();
|
||||
|
||||
private:
|
||||
void internalStartProcess();
|
||||
void suspend();
|
||||
void resume();
|
||||
|
||||
enum State {
|
||||
Idle,
|
||||
ProcessRunning,
|
||||
ProcessPaused
|
||||
};
|
||||
|
||||
void setState(State s);
|
||||
|
||||
private:
|
||||
State m_state;
|
||||
QString m_processFileName;
|
||||
HANDLE m_hThisThread;
|
||||
PROCESS_INFORMATION m_pi;
|
||||
bool m_bOwnsProcess;
|
||||
bool m_bAbortEventPollingLoop;
|
||||
};
|
||||
@@ -55,7 +55,9 @@
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <cxxabi.h>
|
||||
#ifdef __GNUC__
|
||||
# include <cxxabi.h>
|
||||
#endif
|
||||
|
||||
using namespace CPlusPlus;
|
||||
|
||||
@@ -103,9 +105,12 @@ protected:
|
||||
}
|
||||
|
||||
static QByteArray name(AST *ast) {
|
||||
#ifdef __GNUC__
|
||||
QByteArray name = abi::__cxa_demangle(typeid(*ast).name(), 0, 0, 0) + 11;
|
||||
name.truncate(name.length() - 3);
|
||||
|
||||
#else
|
||||
QByteArray name = typeid(*ast).name();
|
||||
#endif
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -199,7 +204,11 @@ public:
|
||||
|
||||
protected:
|
||||
QByteArray name(Symbol *s) {
|
||||
#ifdef __GNUC__
|
||||
QByteArray result = abi::__cxa_demangle(typeid(*s).name(), 0, 0, 0) + 11;
|
||||
#else
|
||||
QByteArray result = typeid(*s).name();
|
||||
#endif
|
||||
if (s->identifier()) {
|
||||
result.append("\\nid: ");
|
||||
result.append(s->identifier()->chars());
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
FAKEVIMHOME = ../../../src/plugins/fakevim
|
||||
UTILSDIR = ../../../src/libs
|
||||
|
||||
DEFINES += QTCREATOR_UTILS_STATIC_LIB
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
$$FAKEVIMHOME/fakevimhandler.cpp \
|
||||
|
||||
6
tests/manual/gdbdebugger/gdbdebugger.pro
Normal file
6
tests/manual/gdbdebugger/gdbdebugger.pro
Normal file
@@ -0,0 +1,6 @@
|
||||
TEMPLATE=subdirs
|
||||
|
||||
SUBDIRS= \
|
||||
gui \
|
||||
helper \
|
||||
simple
|
||||
26
tests/manual/manual.pro
Normal file
26
tests/manual/manual.pro
Normal file
@@ -0,0 +1,26 @@
|
||||
TEMPLATE=subdirs
|
||||
|
||||
SUBDIRS= \
|
||||
cplusplus \
|
||||
cplusplus-dump \
|
||||
fakevim \
|
||||
gdbdebugger \
|
||||
preprocessor \
|
||||
subdir_proparser \
|
||||
trklauncher
|
||||
|
||||
win32 {
|
||||
# Uses CDB debugger
|
||||
SUBDIRS += ccdb
|
||||
}
|
||||
|
||||
unix {
|
||||
# Uses popen
|
||||
SUBDIRS += \
|
||||
plain-cplusplus \
|
||||
# Profile library paths issues
|
||||
process \
|
||||
ssh
|
||||
}
|
||||
|
||||
subdir_proparser.file=proparser/testreader.pro
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <iosfwd>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cstring>
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
@@ -55,7 +56,7 @@ public:
|
||||
: _text(text), _size(size) {}
|
||||
|
||||
StringRef(const char *text)
|
||||
: _text(text), _size(strlen(text)) {}
|
||||
: _text(text), _size(std::strlen(text)) {}
|
||||
|
||||
inline const char *text() const { return _text; }
|
||||
inline unsigned size() const { return _size; }
|
||||
@@ -66,7 +67,7 @@ public:
|
||||
bool operator == (const StringRef &other) const
|
||||
{
|
||||
if (_size == other._size)
|
||||
return _text == other._text || ! strncmp(_text, other._text, _size);
|
||||
return _text == other._text || ! std::strncmp(_text, other._text, _size);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user