forked from qt-creator/qt-creator
Debugger: Improve engine detection.
Try to detect engine by looking at toolchain, executable, attach mode. Find out path to executable in attach to running dialog. Reviewed-by: hjk
This commit is contained in:
@@ -68,9 +68,13 @@ class ProcessListFilterModel : public QSortFilterProxyModel
|
||||
public:
|
||||
explicit ProcessListFilterModel(QObject *parent);
|
||||
QString processIdAt(const QModelIndex &index) const;
|
||||
QString executableForPid(const QString& pid) const;
|
||||
|
||||
void populate(QList<ProcData> processes, const QString &excludePid = QString());
|
||||
|
||||
private:
|
||||
enum { processImageRole = Qt::UserRole };
|
||||
|
||||
bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
|
||||
|
||||
QStandardItemModel *m_model;
|
||||
@@ -111,6 +115,17 @@ QString ProcessListFilterModel::processIdAt(const QModelIndex &index) const
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString ProcessListFilterModel::executableForPid(const QString &pid) const
|
||||
{
|
||||
const int rowCount = m_model->rowCount();
|
||||
for (int r = 0; r < rowCount; r++) {
|
||||
const QStandardItem *item = m_model->item(r, 0);
|
||||
if (item->text() == pid)
|
||||
return item->data(processImageRole).toString();
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
void ProcessListFilterModel::populate(QList<ProcData> processes, const QString &excludePid)
|
||||
{
|
||||
qStableSort(processes);
|
||||
@@ -122,10 +137,12 @@ void ProcessListFilterModel::populate(QList<ProcData> processes, const QString &
|
||||
foreach(const ProcData &proc, processes) {
|
||||
QList<QStandardItem *> row;
|
||||
row.append(new QStandardItem(proc.ppid));
|
||||
row.front()->setData(QVariant(proc.image), processImageRole);
|
||||
row.append(new QStandardItem(proc.name));
|
||||
if (!proc.image.isEmpty())
|
||||
row.back()->setToolTip(proc.image);
|
||||
row.append(new QStandardItem(proc.state));
|
||||
|
||||
if (proc.ppid == excludePid)
|
||||
foreach(QStandardItem *i, row)
|
||||
i->setEnabled(false);
|
||||
@@ -372,9 +389,20 @@ void AttachExternalDialog::procClicked(const QModelIndex &proxyIndex)
|
||||
m_ui->pidLineEdit->setText(processId);
|
||||
}
|
||||
|
||||
QString AttachExternalDialog::attachPIDText() const
|
||||
{
|
||||
return m_ui->pidLineEdit->text().trimmed();
|
||||
}
|
||||
|
||||
qint64 AttachExternalDialog::attachPID() const
|
||||
{
|
||||
return m_ui->pidLineEdit->text().toLongLong();
|
||||
return attachPIDText().toLongLong();
|
||||
}
|
||||
|
||||
QString AttachExternalDialog::executable() const
|
||||
{
|
||||
// Search pid in model in case the user typed in the PID.
|
||||
return m_model->executableForPid(attachPIDText());
|
||||
}
|
||||
|
||||
void AttachExternalDialog::pidChanged(const QString &pid)
|
||||
|
||||
@@ -89,6 +89,7 @@ public:
|
||||
~AttachExternalDialog();
|
||||
|
||||
qint64 attachPID() const;
|
||||
QString executable() const;
|
||||
|
||||
private slots:
|
||||
void rebuildProcessList();
|
||||
@@ -99,8 +100,9 @@ private slots:
|
||||
|
||||
private:
|
||||
inline QPushButton *okButton() const;
|
||||
const QString m_selfPid;
|
||||
inline QString attachPIDText() const;
|
||||
|
||||
const QString m_selfPid;
|
||||
Ui::AttachExternalDialog *m_ui;
|
||||
ProcessListFilterModel *m_model;
|
||||
};
|
||||
|
||||
@@ -964,10 +964,9 @@ static IDebuggerEngine *debuggerEngineForToolChain(int toolChainType)
|
||||
|
||||
// Figure out the debugger type of an executable. Analyze executable
|
||||
// unless the toolchain provides a hint.
|
||||
static IDebuggerEngine *determineDebuggerEngine(const QString &executable,
|
||||
int toolChainType,
|
||||
QString *errorMessage,
|
||||
QString *settingsIdHint)
|
||||
static IDebuggerEngine *debuggerEngineForExecutable(const QString &executable,
|
||||
QString *errorMessage,
|
||||
QString *settingsIdHint)
|
||||
{
|
||||
if (executable.endsWith(_(".js"))) {
|
||||
if (!scriptEngine) {
|
||||
@@ -977,19 +976,6 @@ static IDebuggerEngine *determineDebuggerEngine(const QString &executable,
|
||||
return scriptEngine;
|
||||
}
|
||||
|
||||
/*
|
||||
if (executable.endsWith(_(".sym"))) {
|
||||
if (!gdbEngine) {
|
||||
*errorMessage = msgEngineNotAvailable("Gdb Engine");
|
||||
return 0;
|
||||
}
|
||||
return gdbEngine;
|
||||
}
|
||||
*/
|
||||
|
||||
if (IDebuggerEngine *tce = debuggerEngineForToolChain(toolChainType))
|
||||
return tce;
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
Q_UNUSED(settingsIdHint)
|
||||
if (!gdbEngine) {
|
||||
@@ -1004,8 +990,11 @@ static IDebuggerEngine *determineDebuggerEngine(const QString &executable,
|
||||
return gdbEngine;
|
||||
// If a file has PDB files, it has been compiled by VS.
|
||||
QStringList pdbFiles;
|
||||
if (!getPDBFiles(executable, &pdbFiles, errorMessage))
|
||||
if (!getPDBFiles(executable, &pdbFiles, errorMessage)) {
|
||||
qWarning("Cannot determine type of executable %s: %s",
|
||||
qPrintable(executable), qPrintable(*errorMessage));
|
||||
return 0;
|
||||
}
|
||||
if (pdbFiles.empty())
|
||||
return gdbEngine;
|
||||
|
||||
@@ -1018,12 +1007,8 @@ static IDebuggerEngine *determineDebuggerEngine(const QString &executable,
|
||||
}
|
||||
|
||||
// Figure out the debugger type of a PID
|
||||
static IDebuggerEngine *determineDebuggerEngine(int /* pid */,
|
||||
int toolChainType,
|
||||
QString *errorMessage)
|
||||
static IDebuggerEngine *debuggerEngineForAttach(QString *errorMessage)
|
||||
{
|
||||
if (IDebuggerEngine *tce = debuggerEngineForToolChain(toolChainType))
|
||||
return tce;
|
||||
#ifdef Q_OS_WIN
|
||||
// Preferably Windows debugger
|
||||
if (winEngine)
|
||||
@@ -1059,17 +1044,18 @@ void DebuggerManager::startNewDebugger(const DebuggerStartParametersPtr &sp)
|
||||
|
||||
QString errorMessage;
|
||||
QString settingsIdHint;
|
||||
switch (d->m_startParameters->startMode) {
|
||||
case AttachExternal:
|
||||
case AttachCrashedExternal:
|
||||
d->m_engine = determineDebuggerEngine(d->m_startParameters->attachPID,
|
||||
d->m_startParameters->toolChainType, &errorMessage);
|
||||
break;
|
||||
default:
|
||||
d->m_engine = determineDebuggerEngine(d->m_startParameters->executable,
|
||||
d->m_startParameters->toolChainType, &errorMessage, &settingsIdHint);
|
||||
break;
|
||||
}
|
||||
|
||||
// Figure out engine: toolchain, executable or attach
|
||||
const DebuggerStartMode startMode = d->m_startParameters->startMode;
|
||||
d->m_engine = debuggerEngineForToolChain(d->m_startParameters->toolChainType);
|
||||
|
||||
if (d->m_engine == 0 && startMode != StartRemote
|
||||
&& !d->m_startParameters->executable.isEmpty())
|
||||
d->m_engine = debuggerEngineForExecutable(d->m_startParameters->executable, &errorMessage, &settingsIdHint);
|
||||
|
||||
if (d->m_engine == 0
|
||||
&& (startMode == AttachExternal || startMode == AttachCrashedExternal))
|
||||
d->m_engine = debuggerEngineForAttach(&errorMessage);
|
||||
|
||||
if (!d->m_engine) {
|
||||
emit debuggingFinished();
|
||||
|
||||
@@ -999,7 +999,7 @@ void DebuggerPlugin::attachCmdLine()
|
||||
m_manager->showStatusMessage(tr("Attaching to PID %1.").arg(m_attachRemoteParameters.attachPid));
|
||||
const QString crashParameter =
|
||||
m_attachRemoteParameters.winCrashEvent ? QString::number(m_attachRemoteParameters.winCrashEvent) : QString();
|
||||
attachExternalApplication(m_attachRemoteParameters.attachPid, crashParameter);
|
||||
attachExternalApplication(m_attachRemoteParameters.attachPid, QString(), crashParameter);
|
||||
return;
|
||||
}
|
||||
if (!m_attachRemoteParameters.attachCore.isEmpty()) {
|
||||
@@ -1282,10 +1282,12 @@ void DebuggerPlugin::attachExternalApplication()
|
||||
{
|
||||
AttachExternalDialog dlg(m_uiSwitcher->mainWindow());
|
||||
if (dlg.exec() == QDialog::Accepted)
|
||||
attachExternalApplication(dlg.attachPID());
|
||||
attachExternalApplication(dlg.attachPID(), dlg.executable(), QString());
|
||||
}
|
||||
|
||||
void DebuggerPlugin::attachExternalApplication(qint64 pid, const QString &crashParameter)
|
||||
void DebuggerPlugin::attachExternalApplication(qint64 pid,
|
||||
const QString &binary,
|
||||
const QString &crashParameter)
|
||||
{
|
||||
if (pid == 0) {
|
||||
QMessageBox::warning(m_uiSwitcher->mainWindow(), tr("Warning"),
|
||||
@@ -1294,6 +1296,7 @@ void DebuggerPlugin::attachExternalApplication(qint64 pid, const QString &crashP
|
||||
}
|
||||
const DebuggerStartParametersPtr sp(new DebuggerStartParameters);
|
||||
sp->attachPID = pid;
|
||||
sp->executable = binary;
|
||||
sp->crashParameter = crashParameter;
|
||||
sp->startMode = crashParameter.isEmpty() ? AttachExternal : AttachCrashedExternal;
|
||||
if (RunControl *runControl = m_debuggerRunControlFactory->create(sp))
|
||||
|
||||
@@ -125,7 +125,9 @@ private slots:
|
||||
private:
|
||||
void readSettings();
|
||||
void writeSettings() const;
|
||||
void attachExternalApplication(qint64 pid, const QString &crashParameter = QString());
|
||||
void attachExternalApplication(qint64 pid,
|
||||
const QString &binary,
|
||||
const QString &crashParameter);
|
||||
void attachCore(const QString &core, const QString &exeFileName);
|
||||
|
||||
friend class Debugger::DebuggerManager;
|
||||
|
||||
@@ -29,16 +29,44 @@
|
||||
|
||||
#include "winutils.h"
|
||||
#include "debuggerdialogs.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <windows.h>
|
||||
#include <tlhelp32.h>
|
||||
#ifdef USE_PSAPI
|
||||
# include <psapi.h>
|
||||
#include <psapi.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
# include <QtCore/QLibrary>
|
||||
#endif
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
#ifdef USE_PSAPI
|
||||
#ifdef __GNUC__
|
||||
// Resolve QueryFullProcessImageNameW out of kernel32.dll due
|
||||
// to incomplete MinGW import libs.
|
||||
static inline BOOL minGW_QueryFullProcessImageName(HANDLE h,
|
||||
DWORD flags,
|
||||
LPWSTR buffer,
|
||||
DWORD *size)
|
||||
{
|
||||
// Resolve required symbols from the kernel32.dll
|
||||
typedef BOOL (WINAPI *QueryFullProcessImageNameWProtoType)
|
||||
(HANDLE, DWORD, LPWSTR, PDWORD);
|
||||
static QueryFullProcessImageNameWProtoType queryFullProcessImageNameW = 0;
|
||||
if (!queryFullProcessImageNameW) {
|
||||
QLibrary kernel32Lib(QLatin1String("kernel32.dll"), 0);
|
||||
if (kernel32Lib.isLoaded() || kernel32Lib.load())
|
||||
queryFullProcessImageNameW = (QueryFullProcessImageNameWProtoType)kernel32Lib.resolve("QueryFullProcessImageNameW");
|
||||
}
|
||||
if (!queryFullProcessImageNameW)
|
||||
return FALSE;
|
||||
// Read out process
|
||||
return (*queryFullProcessImageNameW)(h, flags, buffer, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline QString imageName(DWORD processId)
|
||||
{
|
||||
QString rc;
|
||||
@@ -46,12 +74,17 @@ static inline QString imageName(DWORD processId)
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return rc;
|
||||
WCHAR buffer[MAX_PATH];
|
||||
if (GetProcessImageFileName(handle, buffer, MAX_PATH))
|
||||
DWORD bufSize = MAX_PATH;
|
||||
#ifdef __GNUC__
|
||||
if (minGW_QueryFullProcessImageName(handle, 0, buffer, &bufSize))
|
||||
rc = QString::fromUtf16(reinterpret_cast<const ushort*>(buffer));
|
||||
#else
|
||||
if (QueryFullProcessImageNameW(handle, 0, buffer, &bufSize))
|
||||
rc = QString::fromUtf16(buffer);
|
||||
#endif
|
||||
CloseHandle(handle);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
QList<ProcData> winProcessList()
|
||||
{
|
||||
@@ -67,9 +100,7 @@ QList<ProcData> winProcessList()
|
||||
ProcData procData;
|
||||
procData.ppid = QString::number(pe.th32ProcessID);
|
||||
procData.name = QString::fromUtf16(reinterpret_cast<ushort*>(pe.szExeFile));
|
||||
#ifdef USE_PSAPI
|
||||
procData.image = imageName(pe.th32ProcessID);
|
||||
#endif
|
||||
rc.push_back(procData);
|
||||
}
|
||||
CloseHandle(snapshot);
|
||||
|
||||
Reference in New Issue
Block a user