Commit 0146926f authored by Friedemann Kleint's avatar Friedemann Kleint

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
parent 3e750afc
......@@ -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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment