diff options
author | Friedemann Kleint <Friedemann.Kleint@theqtcompany.com> | 2015-06-12 14:52:32 +0200 |
---|---|---|
committer | Jani Heikkinen <jani.heikkinen@theqtcompany.com> | 2015-06-14 06:17:35 +0000 |
commit | 6c8954b07807e31dbc8967ba6d92d4d022073087 (patch) | |
tree | 96e599ebb501571be3d8c56a401edea4f0e866e3 | |
parent | 3f69aa732d22603d88f98728b51b76888f062c94 (diff) | |
download | qttools-6c8954b07807e31dbc8967ba6d92d4d022073087.tar.gz qttools-6c8954b07807e31dbc8967ba6d92d4d022073087.tar.bz2 qttools-6c8954b07807e31dbc8967ba6d92d4d022073087.zip |
windeployqt: Detect -release -force-debug-info MSVC builds as release.
Factor out detection logic into a template for 32/64bit.
When a debug entry is detected, detect release if the
library positively uses the release runtime dll.
Task-number: QTBUG-46629
Change-Id: Ic34c2e3850e7f1945086da87867934c502026a2e
Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
-rw-r--r-- | src/windeployqt/utils.cpp | 91 |
1 files changed, 62 insertions, 29 deletions
diff --git a/src/windeployqt/utils.cpp b/src/windeployqt/utils.cpp index 081c9c47..a331bac9 100644 --- a/src/windeployqt/utils.cpp +++ b/src/windeployqt/utils.cpp @@ -35,6 +35,8 @@ #include "elfreader.h" #include <QtCore/QString> +#include <QtCore/QDebug> +#include <QtCore/QDir> #include <QtCore/QFile> #include <QtCore/QFileInfo> #include <QtCore/QTemporaryFile> @@ -723,6 +725,46 @@ inline QStringList readImportSections(const ImageNtHeader *ntHeaders, const void return result; } +// Check for MSCV runtime (MSVCP120D.dll/MSVCP120.dll). +enum MsvcDebugRuntimeResult { MsvcDebugRuntime, MsvcReleaseRuntime, NoMsvcRuntime }; + +static inline MsvcDebugRuntimeResult checkMsvcDebugRuntime(const QStringList &dependentLibraries) +{ + foreach (const QString &lib, dependentLibraries) { + if (lib.startsWith(QLatin1String("MSVCR"), Qt::CaseInsensitive) + || lib.startsWith(QLatin1String("MSVCP"), Qt::CaseInsensitive)) { + return lib.endsWith(QLatin1String("D.dll"), Qt::CaseInsensitive) + ? MsvcDebugRuntime : MsvcReleaseRuntime; + } + } + return NoMsvcRuntime; +} + +template <class ImageNtHeader> +inline void determineDebugAndDependentLibs(const ImageNtHeader *nth, const void *fileMemory, + bool isMinGW, + QStringList *dependentLibrariesIn, + bool *isDebugIn, QString *errorMessage) +{ + const bool hasDebugEntry = nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size; + QStringList dependentLibraries; + if (dependentLibrariesIn || (isDebugIn && hasDebugEntry && !isMinGW)) + dependentLibraries = readImportSections(nth, fileMemory, errorMessage); + + if (dependentLibrariesIn) + *dependentLibrariesIn = dependentLibraries; + if (isDebugIn) { + if (isMinGW) { + // Use logic that's used e.g. in objdump / pfd library + *isDebugIn = !(nth->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED); + } else { + // When an MSVC debug entry is present, check whether the debug runtime + // is actually used to detect -release / -force-debug-info builds. + *isDebugIn = hasDebugEntry && checkMsvcDebugRuntime(dependentLibraries) != MsvcReleaseRuntime; + } + } +} + // Read a PE executable and determine dependent libraries, word size // and debug flags. bool readPeExecutable(const QString &peExecutableFileName, QString *errorMessage, @@ -769,40 +811,31 @@ bool readPeExecutable(const QString &peExecutableFileName, QString *errorMessage const unsigned wordSize = ntHeaderWordSize(ntHeaders); if (wordSizeIn) *wordSizeIn = wordSize; - bool debug = false; if (wordSize == 32) { - const IMAGE_NT_HEADERS32 *ntHeaders32 = reinterpret_cast<const IMAGE_NT_HEADERS32 *>(ntHeaders); - - if (!isMinGW) { - debug = ntHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size; - } else { - // Use logic that's used e.g. in objdump / pfd library - debug = !(ntHeaders32->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED); - } - - if (dependentLibrariesIn) - *dependentLibrariesIn = readImportSections(ntHeaders32, fileMemory, errorMessage); - + determineDebugAndDependentLibs(reinterpret_cast<const IMAGE_NT_HEADERS32 *>(ntHeaders), + fileMemory, isMinGW, dependentLibrariesIn, isDebugIn, errorMessage); } else { - const IMAGE_NT_HEADERS64 *ntHeaders64 = reinterpret_cast<const IMAGE_NT_HEADERS64 *>(ntHeaders); - - if (!isMinGW) { - debug = ntHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size; - } else { - // Use logic that's used e.g. in objdump / pfd library - debug = !(ntHeaders64->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED); - } - - if (dependentLibrariesIn) - *dependentLibrariesIn = readImportSections(ntHeaders64, fileMemory, errorMessage); + determineDebugAndDependentLibs(reinterpret_cast<const IMAGE_NT_HEADERS64 *>(ntHeaders), + fileMemory, isMinGW, dependentLibrariesIn, isDebugIn, errorMessage); } - if (isDebugIn) - *isDebugIn = debug; result = true; - if (optVerboseLevel > 1) - std::wcout << __FUNCTION__ << ": " << peExecutableFileName - << ' ' << wordSize << " bit, debug: " << debug << '\n'; + if (optVerboseLevel > 1) { + std::wcout << __FUNCTION__ << ": " << QDir::toNativeSeparators(peExecutableFileName) + << ' ' << wordSize << " bit"; + if (isMinGW) + std::wcout << ", MinGW"; + if (dependentLibrariesIn) { + std::wcout << ", dependent libraries: "; + if (optVerboseLevel > 2) + std::wcout << dependentLibrariesIn->join(QLatin1Char(' ')); + else + std::wcout << dependentLibrariesIn->size(); + } + if (isDebugIn) + std::wcout << (*isDebugIn ? ", debug" : ", release"); + std::wcout << '\n'; + } } while (false); if (fileMemory) |