From bd3366d8b54dfc5a3530ce3b8a00ff240dbe2e77 Mon Sep 17 00:00:00 2001 From: Thomas Otto Date: Thu, 24 Jul 2014 11:56:40 +0200 Subject: [PATCH] CoreGdbAdapter: improve finding the exe from a core file - added a function which tries to find the executable belonging to a core file if the extracted path does not exist - tries to find binaries with a relative path - tires to remove commandline arguments, since the core file does not store which part is the exe name (which can contain spaces), and which are arguments loading /QT/core which was created by "/QT/bin/exec w.." by calling "./bin/exec with spaces" arg1 arg2 now finds the binary ==== will be split into a separate commit, included to show the second use of the new function LoadCoreDialog: change when ExecFilename is set from core - only set the name if the exe exists - if it does not exist and the previous entry does not either then insert what was extracted from the corefile Change-Id: I4a9846761c91ed976f3ba38a7dc756fc30ed179c Reviewed-by: hjk --- src/plugins/debugger/gdb/coregdbadapter.cpp | 68 ++++++++++++++++----- src/plugins/debugger/gdb/coregdbadapter.h | 9 ++- src/plugins/debugger/loadcoredialog.cpp | 10 +-- 3 files changed, 65 insertions(+), 22 deletions(-) diff --git a/src/plugins/debugger/gdb/coregdbadapter.cpp b/src/plugins/debugger/gdb/coregdbadapter.cpp index 7515f54d24e..83cb42701c9 100644 --- a/src/plugins/debugger/gdb/coregdbadapter.cpp +++ b/src/plugins/debugger/gdb/coregdbadapter.cpp @@ -34,6 +34,7 @@ #include #include +#include #include #include @@ -89,11 +90,49 @@ void GdbCoreEngine::setupEngine() unpackCoreIfNeeded(); } -QString readExecutableNameFromCore(const QString &debuggerCommand, const QString &coreFile, bool *isCore) +static QString findExecutableFromName(const QString &fileNameFromCore, const QString &coreFile) { + if (QFileInfo(fileNameFromCore).isFile()) + return fileNameFromCore; + if (fileNameFromCore.isEmpty()) + return QString(); + + // turn the filename into an absolute path, using the location of the core as a hint + QString absPath; + QFileInfo fi(fileNameFromCore); + if (fi.isAbsolute()) { + absPath = fileNameFromCore; + } else { + QFileInfo coreInfo(coreFile); + QDir coreDir = coreInfo.dir(); + absPath = FileUtils::resolvePath(coreDir.absolutePath(), fileNameFromCore); + } + if (QFileInfo(absPath).isFile() || absPath.isEmpty()) + return absPath; + + // remove possible trailing arguments + QLatin1Char sep(' '); + QStringList pathFragments = absPath.split(sep); + while (pathFragments.size() > 0) { + QString joined_path = pathFragments.join(sep); + if (QFileInfo(joined_path).isFile()) { + return joined_path; + } + pathFragments.pop_back(); + } + + return QString(); +} + +GdbCoreEngine::CoreInfo +GdbCoreEngine::readExecutableNameFromCore(const QString &debuggerCommand, const QString &coreFile) +{ + CoreInfo cinfo; #if 0 - ElfReader reader(coreFileName()); - return QString::fromLocal8Bit(reader.readCoreName(isCore)); + ElfReader reader(coreFile); + cinfo.isCore = false; + cinfo.rawStringFromCore = QString::fromLocal8Bit(reader.readCoreName(&cinfo.isCore)); + cinfo.foundExecutableName = findExecutableFromName(cinfo.rawStringFromCore, coreFile); #else QStringList args; args.append(QLatin1String("-nx")); @@ -116,13 +155,15 @@ QString readExecutableNameFromCore(const QString &debuggerCommand, const QString pos1 += 23; int pos2 = ba.indexOf('\'', pos1); if (pos2 != -1) { - *isCore = true; - return QString::fromLocal8Bit(ba.mid(pos1, pos2 - pos1)); + cinfo.isCore = true; + cinfo.rawStringFromCore = QString::fromLocal8Bit(ba.mid(pos1, pos2 - pos1)); + cinfo.foundExecutableName = findExecutableFromName(cinfo.rawStringFromCore, coreFile); } } } - return QString(); + cinfo.isCore = false; #endif + return cinfo; } void GdbCoreEngine::continueSetupEngine() @@ -136,17 +177,12 @@ void GdbCoreEngine::continueSetupEngine() m_tempCoreFile.close(); } if (isCore && m_executable.isEmpty()) { - // Read executable from core. - isCore = false; - m_executable = readExecutableNameFromCore( - startParameters().debuggerCommand, - coreFileName(), &isCore); + GdbCoreEngine::CoreInfo cinfo = readExecutableNameFromCore( + startParameters().debuggerCommand, + coreFileName()); - if (isCore) { - // Strip off command line arguments. FIXME: make robust. - int idx = m_executable.indexOf(QLatin1Char(' ')); - if (idx >= 0) - m_executable.truncate(idx); + if (cinfo.isCore) { + m_executable = cinfo.foundExecutableName; if (m_executable.isEmpty()) { showMessageBox(QMessageBox::Warning, tr("Error Loading Symbols"), diff --git a/src/plugins/debugger/gdb/coregdbadapter.h b/src/plugins/debugger/gdb/coregdbadapter.h index 81a4ac9ce05..9356e9dd903 100644 --- a/src/plugins/debugger/gdb/coregdbadapter.h +++ b/src/plugins/debugger/gdb/coregdbadapter.h @@ -43,8 +43,6 @@ namespace Internal { // /////////////////////////////////////////////////////////////////////// -QString readExecutableNameFromCore(const QString &cmd, const QString &coreFile, bool *isCore); - class GdbCoreEngine : public GdbEngine { Q_OBJECT @@ -53,6 +51,13 @@ public: explicit GdbCoreEngine(const DebuggerStartParameters &startParameters); ~GdbCoreEngine(); + struct CoreInfo + { + QString rawStringFromCore; + QString foundExecutableName; // empty if no corresponding exec could be found + bool isCore; + }; + static CoreInfo readExecutableNameFromCore(const QString &debuggerCmd, const QString &coreFile); private: void setupEngine(); void setupInferior(); diff --git a/src/plugins/debugger/loadcoredialog.cpp b/src/plugins/debugger/loadcoredialog.cpp index 37ff6bc113e..05c3ac10991 100644 --- a/src/plugins/debugger/loadcoredialog.cpp +++ b/src/plugins/debugger/loadcoredialog.cpp @@ -367,10 +367,12 @@ void AttachCoreDialog::coreFileChanged(const QString &core) Kit *k = d->kitChooser->currentKit(); QTC_ASSERT(k, return); FileName cmd = DebuggerKitInformation::debuggerCommand(k); - bool isCore = false; - const QString exe = readExecutableNameFromCore(cmd.toString(), core, &isCore); - if (!exe.isEmpty()) - d->localExecFileName->setFileName(FileName::fromString(exe)); + GdbCoreEngine::CoreInfo cinfo = + GdbCoreEngine::readExecutableNameFromCore(cmd.toString(), core); + if (!cinfo.foundExecutableName.isEmpty()) + d->localExecFileName->setFileName(FileName::fromString(cinfo.foundExecutableName)); + else if (!d->localExecFileName->isValid() && !cinfo.rawStringFromCore.isEmpty()) + d->localExecFileName->setFileName(FileName::fromString(cinfo.rawStringFromCore)); } changed(); }