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

This commit is contained in:
hjk
2009-03-04 16:05:51 +01:00
13 changed files with 461 additions and 210 deletions

View File

@@ -137,7 +137,7 @@ protected:
} // end of anonymous namespace
QualifiedNameId *qualifiedNameIdForSymbol(Symbol *s, const LookupContext &context)
static QualifiedNameId *qualifiedNameIdForSymbol(Symbol *s, const LookupContext &context)
{
Name *symbolName = s->name();
if (! symbolName)
@@ -433,12 +433,21 @@ void CPPEditor::updateMethodBoxIndex()
if (file()->fileName() != symbol->fileName())
continue;
else if (symbol->isGenerated())
continue;
else if (symbol->isBlock())
continue;
if (symbol) {
int column = symbol->column();
if (column != 0)
--column;
if (symbol->isGenerated())
column = 0;
QTextCursor c(document()->findBlockByNumber(symbol->line() - 1));
c.setPosition(c.position() + column);
@@ -650,8 +659,6 @@ void CPPEditor::jumpToDefinition()
return; // done
}
}
qDebug() << "No results for expression:" << expression;
}
}
@@ -963,14 +970,14 @@ TextEditor::ITextEditor *CPPEditor::openCppEditorAt(const QString &fileName,
bool CPPEditor::openEditorAt(Symbol *s)
{
const QString fileName = QString::fromUtf8(s->fileName(), s->fileNameLength());
#ifdef QTCREATOR_WITH_ADVANCED_HIGHLIGHTER
unsigned line = s->line();
unsigned column = s->column();
if (column)
--column;
#else
unsigned column = 0;
#endif
return openCppEditorAt(fileName, s->line(), column);
if (s->isGenerated())
unsigned column = 0;
return openCppEditorAt(fileName, line, column);
}

View File

@@ -1,7 +1,8 @@
<ui version="4.0" >
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AttachExternalDialog</class>
<widget class="QDialog" name="AttachExternalDialog" >
<property name="geometry" >
<widget class="QDialog" name="AttachExternalDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
@@ -9,50 +10,76 @@
<height>866</height>
</rect>
</property>
<property name="windowTitle" >
<property name="windowTitle">
<string>Start Debugger</string>
</property>
<layout class="QVBoxLayout" >
<property name="spacing" >
<layout class="QVBoxLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="margin" >
<property name="margin">
<number>9</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" >
<item>
<widget class="QLabel" name="pidLabel" >
<property name="text" >
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="pidLabel">
<property name="text">
<string>Attach to Process ID:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="pidLineEdit" />
<item row="0" column="1">
<widget class="QLineEdit" name="pidLineEdit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="filterLabel">
<property name="text">
<string>Filter:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QWidget" name="filterWidget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="filterLineEdit"/>
</item>
<item>
<widget class="QToolButton" name="filterClearToolButton">
<property name="text">
<string>Clear</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTreeView" name="procView" >
<property name="editTriggers" >
<widget class="QTreeView" name="procView">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line" >
<property name="orientation" >
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="orientation" >
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons" >
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>

View File

@@ -35,6 +35,7 @@
#include "stackhandler.h"
#include <utils/qtcassert.h>
#include <utils/winutils.h>
#include <utils/consoleprocess.h>
#include <QtCore/QDebug>
@@ -49,6 +50,31 @@
static const char *dbgEngineDllC = "dbgeng";
static const char *debugCreateFuncC = "DebugCreate";
static QString debugEngineComError(HRESULT hr)
{
if (!FAILED(hr))
return QLatin1String("S_OK");
switch (hr) {
case E_FAIL:
break;
case E_INVALIDARG:
return QLatin1String("E_INVALIDARG");
case E_NOINTERFACE:
return QLatin1String("E_NOINTERFACE");
case E_OUTOFMEMORY:
return QLatin1String("E_OUTOFMEMORY");
case E_UNEXPECTED:
return QLatin1String("E_UNEXPECTED");
case E_NOTIMPL:
return QLatin1String("E_NOTIMPL");
}
if (hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED))
return QLatin1String("ERROR_ACCESS_DENIED");;
if (hr == HRESULT_FROM_NT(STATUS_CONTROL_C_EXIT))
return QLatin1String("STATUS_CONTROL_C_EXIT");
return Core::Utils::winErrorMessage(HRESULT_CODE(hr));
}
namespace Debugger {
namespace Internal {
@@ -177,14 +203,48 @@ void CdbDebugEngine::setToolTipExpression(const QPoint & /*pos*/, const QString
}
bool CdbDebugEngine::startDebugger()
{
m_d->m_debuggerManager->showStatusMessage("Starting Debugger", -1);
QString errorMessage;
bool rc = false;
switch (m_d->m_debuggerManager->startMode()) {
case AttachExternal:
rc = startAttachDebugger(m_d->m_debuggerManager->m_attachedPID, &errorMessage);
break;
case StartInternal:
case StartExternal:
rc = startDebuggerWithExecutable(&errorMessage);
break;
case AttachCore:
errorMessage = tr("CdbDebugEngine: Attach to core not supported!");
break;
}
if (rc) {
m_d->m_debuggerManager->showStatusMessage(tr("Debugger Running"), -1);
startWatchTimer();
} else {
qWarning("%s\n", qPrintable(errorMessage));
}
return rc;
}
bool CdbDebugEngine::startAttachDebugger(unsigned long pid, QString *errorMessage)
{
const HRESULT hr = m_d->m_pDebugClient->AttachProcess(NULL, pid,
DEBUG_ATTACH_NONINVASIVE |DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND);
if (debugCDB)
qDebug() << "Attaching to " << pid << " returns " << hr;
if (FAILED(hr)) {
*errorMessage = tr("AttachProcess failed for pid %1: %2").arg(pid).arg(debugEngineComError(hr));
return false;
}
return true;
}
bool CdbDebugEngine::startDebuggerWithExecutable(QString *errorMessage)
{
m_d->m_debuggerManager->showStatusMessage("Starting Debugger", -1);
//if (!q->m_workingDir.isEmpty())
// m_gdbProc.setWorkingDirectory(q->m_workingDir);
//if (!q->m_environment.isEmpty())
// m_gdbProc.setEnvironment(q->m_environment);
DEBUG_CREATE_PROCESS_OPTIONS dbgopts;
memset(&dbgopts, 0, sizeof(dbgopts));
dbgopts.CreateFlags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
@@ -199,32 +259,28 @@ bool CdbDebugEngine::startDebugger()
m_d->m_pDebugSymbols->SetSymbolOptions(SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | 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);
if (m_d->m_debuggerManager->startMode() == AttachExternal) {
qWarning("CdbDebugEngine: attach to process not yet implemented!");
return false;
} else {
QString cmd = Core::Utils::AbstractProcess::createWinCommandline(filename, m_d->m_debuggerManager->m_processArgs);
PCWSTR env = 0;
QByteArray envData;
if (!m_d->m_debuggerManager->m_environment.empty()) {
envData = Core::Utils::AbstractProcess::createWinEnvironment(Core::Utils::AbstractProcess::fixWinEnvironment(m_d->m_debuggerManager->m_environment));
env = reinterpret_cast<PCWSTR>(envData.data());
}
HRESULT hr = m_d->m_pDebugClient->CreateProcess2Wide(NULL,
const_cast<PWSTR>(cmd.utf16()),
&dbgopts,
sizeof(dbgopts),
m_d->m_debuggerManager->m_workingDir.utf16(),
env);
if (FAILED(hr)) {
//qWarning("CreateProcess2Wide failed");
m_d->m_debuggerManagerAccess->notifyInferiorExited();
return false;
}
// TODO console
const QString cmd = Core::Utils::AbstractProcess::createWinCommandline(filename, m_d->m_debuggerManager->m_processArgs);
if (debugCDB)
qDebug() << "Starting " << cmd;
PCWSTR env = 0;
QByteArray envData;
if (!m_d->m_debuggerManager->m_environment.empty()) {
envData = Core::Utils::AbstractProcess::createWinEnvironment(Core::Utils::AbstractProcess::fixWinEnvironment(m_d->m_debuggerManager->m_environment));
env = reinterpret_cast<PCWSTR>(envData.data());
}
m_d->m_debuggerManager->showStatusMessage(tr("Debugger Running"), -1);
startWatchTimer();
const HRESULT hr = m_d->m_pDebugClient->CreateProcess2Wide(NULL,
const_cast<PWSTR>(cmd.utf16()),
&dbgopts,
sizeof(dbgopts),
m_d->m_debuggerManager->m_workingDir.utf16(),
env);
if (FAILED(hr)) {
*errorMessage = tr("CreateProcess2Wide failed for '%1': %2").arg(cmd).arg(debugEngineComError(hr));
m_d->m_debuggerManagerAccess->notifyInferiorExited();
return false;
}
m_d->m_debuggerManagerAccess->notifyInferiorRunning();
return true;
}

View File

@@ -99,6 +99,8 @@ protected:
void timerEvent(QTimerEvent*);
private:
bool startAttachDebugger(unsigned long pid, QString *errorMessage);
bool startDebuggerWithExecutable(QString *errorMessage);
void startWatchTimer();
void killWatchTimer();

View File

@@ -34,6 +34,10 @@
#include "ui_attachremotedialog.h"
#include "ui_startexternaldialog.h"
#ifdef Q_OS_WIN
# include "dbgwinutils.h"
#endif
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFile>
@@ -41,17 +45,11 @@
#include <QtGui/QHeaderView>
#include <QtGui/QFileDialog>
#include <QtGui/QPushButton>
#ifdef Q_OS_WINDOWS
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <stdio.h>
#endif
#include <QtGui/QProxyModel>
#include <QtGui/QSortFilterProxyModel>
using namespace Debugger::Internal;
///////////////////////////////////////////////////////////////////////
//
// AttachCoreDialog
@@ -100,34 +98,21 @@ void AttachCoreDialog::setCoreFile(const QString &fileName)
m_ui->coreFileName->setPath(fileName);
}
///////////////////////////////////////////////////////////////////////
//
// AttachExternalDialog
// process model helpers
//
///////////////////////////////////////////////////////////////////////
AttachExternalDialog::AttachExternalDialog(QWidget *parent)
: QDialog(parent), m_ui(new Ui::AttachExternalDialog)
static QStandardItemModel *createProcessModel(QObject *parent)
{
m_ui->setupUi(this);
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
m_model = new QStandardItemModel(this);
m_ui->procView->setSortingEnabled(true);
connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
connect(m_ui->procView, SIGNAL(activated(QModelIndex)),
this, SLOT(procSelected(QModelIndex)));
rebuildProcessList();
}
AttachExternalDialog::~AttachExternalDialog()
{
delete m_ui;
QStandardItemModel *rc = new QStandardItemModel(parent);
QStringList columns;
columns << AttachExternalDialog::tr("Process ID")
<< AttachExternalDialog::tr("Name")
<< AttachExternalDialog::tr("State");
rc->setHorizontalHeaderLabels(columns);
return rc;
}
static bool isProcessName(const QString &procname)
@@ -138,87 +123,122 @@ static bool isProcessName(const QString &procname)
return true;
}
struct ProcData
bool operator<(const ProcData &p1, const ProcData &p2)
{
QString ppid;
QString name;
QString state;
};
static void insertItem(QStandardItem *root, const QString &pid,
const QMap<QString, ProcData> &procs, QMap<QString, QStandardItem *> &known)
{
//qDebug() << "HANDLING " << pid;
QStandardItem *parent = 0;
const ProcData &proc = procs[pid];
if (1 || pid == "0") { // FIXME: a real tree is not-so-nice to search
parent = root;
} else {
if (!known.contains(proc.ppid))
insertItem(root, proc.ppid, procs, known);
parent = known[proc.ppid];
}
QList<QStandardItem *> row;
row.append(new QStandardItem(pid));
row.append(new QStandardItem(proc.name));
//row.append(new QStandardItem(proc.ppid));
row.append(new QStandardItem(proc.state));
parent->appendRow(row);
known[pid] = row[0];
return p1.name < p2.name;
}
void AttachExternalDialog::rebuildProcessList()
// Determine UNIX processes by reading "/proc"
static QList<ProcData> unixProcessList()
{
QStringList procnames = QDir("/proc/").entryList();
if (procnames.isEmpty()) {
m_ui->procView->hide();
return;
}
typedef QMap<QString, ProcData> Procs;
Procs procs;
QList<ProcData> rc;
const QStringList procnames = QDir(QLatin1String("/proc/")).entryList();
if (procnames.isEmpty())
return rc;
foreach (const QString &procname, procnames) {
if (!isProcessName(procname))
continue;
QString filename = "/proc/" + procname + "/stat";
QString filename = QLatin1String("/proc/");
filename += procname;
filename += QLatin1String("/stat");
QFile file(filename);
file.open(QIODevice::ReadOnly);
QStringList data = QString::fromLocal8Bit(file.readAll()).split(' ');
//qDebug() << filename << data;
const QStringList data = QString::fromLocal8Bit(file.readAll()).split(' ');
ProcData proc;
proc.name = data.at(1);
if (proc.name.startsWith('(') && proc.name.endsWith(')'))
if (proc.name.startsWith(QLatin1Char('(')) && proc.name.endsWith(QLatin1Char(')')))
proc.name = proc.name.mid(1, proc.name.size() - 2);
proc.state = data.at(2);
proc.ppid = data.at(3);
procs[procname] = proc;
rc.push_back(proc);
}
return rc;
}
m_model->clear();
QMap<QString, QStandardItem *> known;
for (Procs::const_iterator it = procs.begin(); it != procs.end(); ++it)
insertItem(m_model->invisibleRootItem(), it.key(), procs, known);
m_model->setHeaderData(0, Qt::Horizontal, "Process ID", Qt::DisplayRole);
m_model->setHeaderData(1, Qt::Horizontal, "Name", Qt::DisplayRole);
//model->setHeaderData(2, Qt::Horizontal, "Parent", Qt::DisplayRole);
m_model->setHeaderData(2, Qt::Horizontal, "State", Qt::DisplayRole);
static void populateProcessModel(QStandardItemModel *model)
{
#ifdef Q_OS_WIN
QList<ProcData> processes = winProcessList();
#else
QList<ProcData> processes = unixProcessList();
#endif
qStableSort(processes);
m_ui->procView->setModel(m_model);
if (const int rowCount = model->rowCount())
model->removeRows(0, rowCount);
QStandardItem *root = model->invisibleRootItem();
foreach(const ProcData &proc, processes) {
QList<QStandardItem *> row;
row.append(new QStandardItem(proc.ppid));
row.append(new QStandardItem(proc.name));
if (!proc.image.isEmpty())
row.back()->setToolTip(proc.image);
row.append(new QStandardItem(proc.state));
root->appendRow(row);
}
}
///////////////////////////////////////////////////////////////////////
//
// AttachExternalDialog
//
///////////////////////////////////////////////////////////////////////
AttachExternalDialog::AttachExternalDialog(QWidget *parent) :
QDialog(parent),
m_ui(new Ui::AttachExternalDialog),
m_model(createProcessModel(this)),
m_proxyModel(new QSortFilterProxyModel(this))
{
m_ui->setupUi(this);
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
m_proxyModel->setSourceModel(m_model);
m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
m_proxyModel->setFilterKeyColumn(1);
m_ui->procView->setModel(m_proxyModel);
m_ui->procView->setSortingEnabled(true);
connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
QPushButton *refreshButton = new QPushButton(tr("Refresh"));
connect(refreshButton, SIGNAL(clicked()), this, SLOT(rebuildProcessList()));
m_ui->buttonBox->addButton(refreshButton, QDialogButtonBox::ActionRole);
connect(m_ui->procView, SIGNAL(activated(QModelIndex)),
this, SLOT(procSelected(QModelIndex)));
connect(m_ui->filterClearToolButton, SIGNAL(clicked()),
m_ui->filterLineEdit, SLOT(clear()));
connect(m_ui->filterLineEdit, SIGNAL(textChanged(QString)),
m_proxyModel, SLOT(setFilterFixedString(QString)));
rebuildProcessList();
}
AttachExternalDialog::~AttachExternalDialog()
{
delete m_ui;
}
void AttachExternalDialog::rebuildProcessList()
{
populateProcessModel(m_model);
m_ui->procView->expandAll();
m_ui->procView->resizeColumnToContents(0);
m_ui->procView->resizeColumnToContents(1);
m_ui->procView->sortByColumn(1, Qt::AscendingOrder);
}
void AttachExternalDialog::procSelected(const QModelIndex &index0)
void AttachExternalDialog::procSelected(const QModelIndex &proxyIndex)
{
const QModelIndex index0 = m_proxyModel->mapToSource(proxyIndex);
QModelIndex index = index0.sibling(index0.row(), 0);
QStandardItem *item = m_model->itemFromIndex(index);
if (!item)
return;
m_ui->pidLineEdit->setText(item->text());
accept();
if (const QStandardItem *item = m_model->itemFromIndex(index)) {
m_ui->pidLineEdit->setText(item->text());
m_ui->buttonBox->button(QDialogButtonBox::Ok)->animateClick();
}
}
int AttachExternalDialog::attachPID() const
@@ -226,22 +246,22 @@ int AttachExternalDialog::attachPID() const
return m_ui->pidLineEdit->text().toInt();
}
///////////////////////////////////////////////////////////////////////
//
// AttachRemoteDialog
//
///////////////////////////////////////////////////////////////////////
AttachRemoteDialog::AttachRemoteDialog(QWidget *parent, const QString &pid)
: QDialog(parent), m_ui(new Ui::AttachRemoteDialog)
AttachRemoteDialog::AttachRemoteDialog(QWidget *parent, const QString &pid) :
QDialog(parent),
m_ui(new Ui::AttachRemoteDialog),
m_model(createProcessModel(this))
{
m_ui->setupUi(this);
m_ui->buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
m_defaultPID = pid;
m_model = new QStandardItemModel(this);
m_ui->procView->setModel(m_model);
m_ui->procView->setSortingEnabled(true);
connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
@@ -261,42 +281,7 @@ AttachRemoteDialog::~AttachRemoteDialog()
void AttachRemoteDialog::rebuildProcessList()
{
QStringList procnames = QDir("/proc/").entryList();
if (procnames.isEmpty()) {
m_ui->procView->hide();
return;
}
typedef QMap<QString, ProcData> Procs;
Procs procs;
foreach (const QString &procname, procnames) {
if (!isProcessName(procname))
continue;
QString filename = "/proc/" + procname + "/stat";
QFile file(filename);
file.open(QIODevice::ReadOnly);
QStringList data = QString::fromLocal8Bit(file.readAll()).split(' ');
//qDebug() << filename << data;
ProcData proc;
proc.name = data.at(1);
if (proc.name.startsWith('(') && proc.name.endsWith(')'))
proc.name = proc.name.mid(1, proc.name.size() - 2);
proc.state = data.at(2);
proc.ppid = data.at(3);
procs[procname] = proc;
}
m_model->clear();
QMap<QString, QStandardItem *> known;
for (Procs::const_iterator it = procs.begin(); it != procs.end(); ++it)
insertItem(m_model->invisibleRootItem(), it.key(), procs, known);
m_model->setHeaderData(0, Qt::Horizontal, "Process ID", Qt::DisplayRole);
m_model->setHeaderData(1, Qt::Horizontal, "Name", Qt::DisplayRole);
//model->setHeaderData(2, Qt::Horizontal, "Parent", Qt::DisplayRole);
m_model->setHeaderData(2, Qt::Horizontal, "State", Qt::DisplayRole);
m_ui->procView->setModel(m_model);
populateProcessModel(m_model);
m_ui->procView->expandAll();
m_ui->procView->resizeColumnToContents(0);
m_ui->procView->resizeColumnToContents(1);
@@ -317,8 +302,6 @@ int AttachRemoteDialog::attachPID() const
return m_ui->pidLineEdit->text().toInt();
}
///////////////////////////////////////////////////////////////////////
//
// StartExternalDialog

View File

@@ -36,6 +36,7 @@ QT_BEGIN_NAMESPACE
class QModelIndex;
class QStandardItemModel;
class QSortFilterProxyModel;
namespace Ui {
class AttachCoreDialog;
@@ -50,6 +51,14 @@ QT_END_NAMESPACE
namespace Debugger {
namespace Internal {
struct ProcData
{
QString ppid;
QString name;
QString image;
QString state;
};
class AttachCoreDialog : public QDialog
{
Q_OBJECT
@@ -68,7 +77,6 @@ private:
Ui::AttachCoreDialog *m_ui;
};
class AttachExternalDialog : public QDialog
{
Q_OBJECT
@@ -85,6 +93,7 @@ private slots:
private:
Ui::AttachExternalDialog *m_ui;
QSortFilterProxyModel *m_proxyModel;
QStandardItemModel *m_model;
};

View File

@@ -137,7 +137,8 @@ extern IDebuggerEngine *createWinEngine(DebuggerManager *)
#endif
extern IDebuggerEngine *createScriptEngine(DebuggerManager *parent);
DebuggerManager::DebuggerManager()
DebuggerManager::DebuggerManager() :
m_attachCoreAction(0)
{
init();
}
@@ -245,7 +246,6 @@ void DebuggerManager::init()
m_registerHandler = new RegisterHandler;
registerView->setModel(m_registerHandler->model());
m_watchHandler = new WatchHandler;
// Locals
@@ -295,8 +295,11 @@ void DebuggerManager::init()
m_attachExternalAction = new QAction(this);
m_attachExternalAction->setText(tr("Attach to Running External Application..."));
#ifndef Q_OS_WIN
m_attachCoreAction = new QAction(this);
m_attachCoreAction->setText(tr("Attach to Core..."));
connect(m_attachCoreAction, SIGNAL(triggered()), this, SLOT(attachCore()));
#endif
m_continueAction = new QAction(this);
m_continueAction->setText(tr("Continue"));
@@ -366,8 +369,6 @@ void DebuggerManager::init()
this, SLOT(startExternalApplication()));
connect(m_attachExternalAction, SIGNAL(triggered()),
this, SLOT(attachExternalApplication()));
connect(m_attachCoreAction, SIGNAL(triggered()),
this, SLOT(attachCore()));
connect(m_stopAction, SIGNAL(triggered()),
this, SLOT(interruptDebuggingRequest()));
@@ -788,7 +789,7 @@ void DebuggerManager::attachCore()
emit debuggingFinished();
}
// Figure out the debugger type of an exexcutable
// Figure out the debugger type of an executable
static bool determineDebuggerType(const QString &executable,
DebuggerManager::DebuggerType *dt,
QString *errorMessage)
@@ -820,6 +821,20 @@ static bool determineDebuggerType(const QString &executable,
#endif
}
// Figure out the debugger type of a PID
static bool determineDebuggerType(int /* pid */,
DebuggerManager::DebuggerType *dt,
QString * /*errorMessage*/)
{
#ifdef Q_OS_WIN
// Preferably Windows debugger
*dt = winEngine ? DebuggerManager::WinDebugger : DebuggerManager::GdbDebugger;
#else
*dt = DebuggerManager::GdbDebugger;
#endif
return true;
}
bool DebuggerManager::startNewDebugger(DebuggerStartMode mode)
{
if (Debugger::Constants::Internal::debug)
@@ -828,7 +843,8 @@ bool DebuggerManager::startNewDebugger(DebuggerStartMode mode)
m_startMode = mode;
// FIXME: Clean up
if (startMode() == StartExternal) {
switch (startMode()) {
case StartExternal: {
StartExternalDialog dlg(mainWindow());
dlg.setExecutableFile(
configValue(QLatin1String("LastExternalExecutableFile")).toString());
@@ -844,7 +860,9 @@ bool DebuggerManager::startNewDebugger(DebuggerStartMode mode)
m_processArgs = dlg.executableArguments().split(' ');
m_workingDir = QString();
m_attachedPID = -1;
} else if (startMode() == AttachExternal) {
}
break;
case AttachExternal: {
AttachExternalDialog dlg(mainWindow());
if (dlg.exec() != QDialog::Accepted)
return false;
@@ -857,7 +875,9 @@ bool DebuggerManager::startNewDebugger(DebuggerStartMode mode)
tr("Cannot attach to PID 0"));
return false;
}
} else if (startMode() == StartInternal) {
}
break;
case StartInternal:
if (m_executable.isEmpty()) {
QString startDirectory = m_executable;
if (m_executable.isEmpty()) {
@@ -881,7 +901,8 @@ bool DebuggerManager::startNewDebugger(DebuggerStartMode mode)
//m_processArgs = sd.processArgs.join(QLatin1String(" "));
m_attachedPID = 0;
}
} else if (startMode() == AttachCore) {
break;
case AttachCore: {
AttachCoreDialog dlg(mainWindow());
dlg.setExecutableFile(
configValue(QLatin1String("LastExternalExecutableFile")).toString());
@@ -899,12 +920,17 @@ bool DebuggerManager::startNewDebugger(DebuggerStartMode mode)
m_workingDir = QString();
m_attachedPID = -1;
}
break;
}
emit debugModeRequested();
DebuggerType type;
QString errorMessage;
if (!determineDebuggerType(m_executable, &type, &errorMessage)) {
const bool hasDebugger = startMode() == AttachExternal ?
determineDebuggerType(m_attachedPID, &type, &errorMessage) :
determineDebuggerType(m_executable, &type, &errorMessage);
if (!hasDebugger) {
QMessageBox::warning(mainWindow(), tr("Warning"),
tr("Cannot debug '%1': %2").arg(m_executable, errorMessage));
return false;
@@ -1142,7 +1168,8 @@ void DebuggerManager::setStatus(int status)
m_startExternalAction->setEnabled(!started && !starting);
m_attachExternalAction->setEnabled(!started && !starting);
m_attachCoreAction->setEnabled(!started && !starting);
if (m_attachCoreAction)
m_attachCoreAction->setEnabled(!started && !starting);
m_watchAction->setEnabled(ready);
m_breakAction->setEnabled(true);

View File

@@ -443,15 +443,15 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *error_mes
Constants::STARTEXTERNAL, globalcontext);
mdebug->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
#ifndef Q_OS_WIN
cmd = am->registerAction(m_manager->m_attachExternalAction,
Constants::ATTACHEXTERNAL, globalcontext);
mdebug->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
cmd = am->registerAction(m_manager->m_attachCoreAction,
Constants::ATTACHCORE, globalcontext);
mdebug->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
#endif
if (m_manager->m_attachCoreAction) {
cmd = am->registerAction(m_manager->m_attachCoreAction,
Constants::ATTACHCORE, globalcontext);
mdebug->addAction(cmd, Core::Constants::G_DEFAULT_ONE);
}
cmd = am->registerAction(m_manager->m_continueAction,
ProjectExplorer::Constants::DEBUG, QList<int>() << m_gdbRunningContext);

View File

@@ -0,0 +1,79 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/
#include "winutils.h"
#include "debuggerdialogs.h"
#include <windows.h>
#include <tlhelp32.h>
#ifdef USE_PSAPI
# include <psapi.h>
#endif
namespace Debugger {
namespace Internal {
#ifdef USE_PSAPI
static inline QString imageName(DWORD processId)
{
QString rc;
HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION , FALSE, processId);
if (handle == INVALID_HANDLE_VALUE)
return rc;
WCHAR buffer[MAX_PATH];
if (GetProcessImageFileName(handle, buffer, MAX_PATH))
rc = QString::fromUtf16(buffer);
CloseHandle(handle);
return rc;
}
#endif
QList<ProcData> winProcessList()
{
QList<ProcData> rc;
PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot == INVALID_HANDLE_VALUE)
return rc;
for (bool hasNext = Process32First(snapshot, &pe); hasNext; hasNext = Process32Next(snapshot, &pe)) {
ProcData procData;
procData.ppid = QString::number(pe.th32ProcessID);
procData.name = QString::fromUtf16(pe.szExeFile);
#ifdef USE_PSAPI
procData.image = imageName(pe.th32ProcessID);
#endif
rc.push_back(procData);
}
CloseHandle(snapshot);
return rc;
}
}
}

View File

@@ -0,0 +1,44 @@
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/
#ifndef _DBG_WINDUTILS_H
#define _DBG_WINDUTILS_H
#include <QtCore/QList>
namespace Debugger {
namespace Internal {
struct ProcData; // debuggerdialogs, used by the process listing dialogs
QList<ProcData> winProcessList();
}
}
#endif

View File

@@ -1,3 +1,5 @@
INCLUDEPATH+=$$PWD
SOURCES += $$PWD/peutils.cpp
HEADERS += $$PWD/peutils.h
SOURCES += $$PWD/peutils.cpp \
$$PWD/dbgwinutils.cpp
HEADERS += $$PWD/peutils.h \
$$PWD/dbgwinutils.h

View File

@@ -164,7 +164,8 @@ Symbol::Symbol(TranslationUnit *translationUnit, unsigned sourceLocation, Name *
_visibility(Symbol::Public),
_scope(0),
_index(0),
_next(0)
_next(0),
_isGenerated(false)
{
setSourceLocation(sourceLocation);
setName(name);
@@ -200,14 +201,24 @@ unsigned Symbol::sourceLocation() const
unsigned Symbol::sourceOffset() const
{ return _sourceOffset; }
bool Symbol::isGenerated() const
{ return _isGenerated; }
void Symbol::setSourceLocation(unsigned sourceLocation)
{
_sourceLocation = sourceLocation;
if (_sourceLocation)
_sourceOffset = translationUnit()->tokenAt(sourceLocation).offset;
else
if (! _sourceLocation) {
_isGenerated = false;
_sourceOffset = 0;
} else {
TranslationUnit *unit = translationUnit();
const Token &tk = unit->tokenAt(sourceLocation);
_isGenerated = tk.generated;
_sourceOffset = tk.offset;
}
}
unsigned Symbol::line() const

View File

@@ -233,6 +233,8 @@ public:
Name *identity() const;
bool isGenerated() const;
void setScope(Scope *scope); // ### make me private
void setSourceLocation(unsigned sourceLocation); // ### make me private
@@ -256,6 +258,8 @@ private:
unsigned _index;
Symbol *_next;
bool _isGenerated: 1;
class IdentityForName;
class HashCode;