From: Friedemann Kleint Date: Fri, 12 Jun 2015 12:52:32 +0000 (+0200) Subject: windeployqt: Detect -release -force-debug-info MSVC builds as release. X-Git-Tag: v5.5.90+alpha1~6^2~12^2~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6c8954b07807e31dbc8967ba6d92d4d022073087;p=platform%2Fupstream%2Fqttools.git 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 --- diff --git a/src/windeployqt/utils.cpp b/src/windeployqt/utils.cpp index 081c9c4..a331bac 100644 --- a/src/windeployqt/utils.cpp +++ b/src/windeployqt/utils.cpp @@ -35,6 +35,8 @@ #include "elfreader.h" #include +#include +#include #include #include #include @@ -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 +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(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(ntHeaders), + fileMemory, isMinGW, dependentLibrariesIn, isDebugIn, errorMessage); } else { - const IMAGE_NT_HEADERS64 *ntHeaders64 = reinterpret_cast(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(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)