Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-05 09:19:26

0001 // Copyright (C) 2022 Intel Corporation.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 // Qt-Security score:significant reason:default
0004 
0005 #if !defined(QVERSIONTAGGING_H)
0006 #define QVERSIONTAGGING_H
0007 
0008 #if 0
0009 #pragma qt_no_master_include
0010 #endif
0011 
0012 #include <QtCore/qcompilerdetection.h>
0013 #include <QtCore/qtconfigmacros.h>
0014 #include <QtCore/qtversionchecks.h>
0015 #include <QtCore/qtypes.h>
0016 
0017 QT_REQUIRE_CONFIG(version_tagging);
0018 
0019 QT_BEGIN_NAMESPACE
0020 
0021 /*
0022  * Explanation
0023  *
0024  * This file causes all libraries, plugins, and applications that #include this
0025  * file to automatically pull in a symbol found in QtCore that encodes the
0026  * current Qt version number at the time of compilation. The relocation is
0027  * designed so that it's impossible for the dynamic linker to perform lazy
0028  * binding. Instead, it must resolve at load time or fail. That way, attempting
0029  * to load such a library or plugin while an older QtCore is loaded will fail.
0030  * Similarly, if an older QtCore is found when launching an application, the
0031  * application will fail to launch.
0032  *
0033  * It's also possible to inspect which version is required by decoding the
0034  * .qtversion section. The second pointer-sized variable is the required
0035  * version, for example, for Qt 6.4.1:
0036  *
0037  *      Hex dump of section [18] '.qtversion', 16 bytes at offset 0x1ee48:
0038  *        0x00000000 b0ffffff ffffffff 01040600 00000000 ................
0039  *                                     ^^^^^^^^ ^^^^^^^^
0040  *
0041  * There will only be one copy of the section in the output library or application.
0042  *
0043  * This functionality can be disabled by defining QT_NO_VERSION_TAGGING. It's
0044  * disabled if Qt was built statically.
0045  *
0046  * Windows notes:
0047  *
0048  *  On Windows, the address of a __declspec(dllimport) variable is not a
0049  *  constant expression, unlike Unix systems. So we instead use the address of
0050  *  the import variable, which is created by prefixing the external name with
0051  *  "__imp_". Using that variable causes an import of the corresponding symbol
0052  *  from QtCore DLL.
0053  *
0054  *  With MinGW (GCC and Clang), we use a C++17 inline variable, so the compiler
0055  *  and linker automatically merge the variables. The "used" __attribute__
0056  *  tells the compiler to always emit that variable, whether it's used or not.
0057  *
0058  *  MSVC has no equivalent to that attribute, so instead we create an extern
0059  *  const variable and tell the linker to merge them all via
0060  *  __declspec(selectany).
0061  *
0062  * Unix notes:
0063  *
0064  *  On Unix, we use the same C++17 inline variable solution as MinGW, but we
0065  *  don't need the "__imp_" trick.
0066  *
0067  *  Additionally, on ELF systems like Linux and FreeBSD, the symbol in question
0068  *  is simply "qt_version_tag" in both QtCore and in this ELF module, but it
0069  *  has an ELF version attached to it (see qversiontagging.cpp and
0070  *  QtFlagHandlingHelpers.cmake). That way, the error message from the dynamic
0071  *  linker will say it can't find version "Qt_6.x".
0072  */
0073 
0074 namespace QtPrivate {
0075 struct QVersionTag
0076 {
0077     const void *symbol;
0078     quintptr version;
0079     constexpr QVersionTag(const void *sym, int currentVersion = QT_VERSION)
0080         : symbol(sym), version(currentVersion)
0081     {}
0082 };
0083 }
0084 
0085 #if !defined(QT_NO_VERSION_TAGGING) && (defined(QT_BUILD_CORE_LIB) || defined(QT_BOOTSTRAPPED) || defined(QT_STATIC))
0086 // don't make tags in QtCore, bootstrapped systems or if the user asked not to
0087 #  define QT_NO_VERSION_TAGGING
0088 #endif
0089 
0090 #if defined(Q_OS_WIN)
0091 #  ifdef Q_PROCESSOR_X86_32
0092 //   32-bit x86 convention does prepend a _
0093 #    define QT_MANGLE_IMPORT_PREFIX     _imp__
0094 #  else
0095 //   Calling convention on other architectures does not prepend a _
0096 #    define QT_MANGLE_IMPORT_PREFIX     __imp_
0097 #  endif
0098 #  if defined(Q_CC_MSVC_ONLY)
0099 #    pragma section(".qtversion",read,shared)
0100 #    define QT_VERSION_TAG_SECTION      __declspec(allocate(".qtversion"))
0101 #    define QT_VERSION_TAG_ATTRIBUTE    __declspec(selectany) extern const
0102 #  else
0103 #    define QT_VERSION_TAG_ATTRIBUTE    __attribute__((used)) constexpr inline
0104 #  endif
0105 #  define QT_VERSION_TAG2(sym, imp)     \
0106     extern "C" const char * const imp;  \
0107     QT_VERSION_TAG_ATTRIBUTE QT_VERSION_TAG_SECTION QtPrivate::QVersionTag sym ## _used(&imp)
0108 #  define QT_VERSION_TAG(sym, imp)       QT_VERSION_TAG2(sym, imp)
0109 #elif defined(Q_CC_GNU) && __has_attribute(used)
0110 #  ifdef Q_OS_DARWIN
0111 #    define QT_VERSION_TAG_SECTION      __attribute__((section("__DATA,.qtversion")))
0112 #  endif
0113 #  define QT_VERSION_TAG_ATTRIBUTE    __attribute__((visibility("hidden"), used))
0114 #  define QT_VERSION_TAG2(sym, imp)     \
0115     extern "C" Q_DECL_IMPORT const char sym; \
0116     QT_VERSION_TAG_ATTRIBUTE QT_VERSION_TAG_SECTION constexpr inline QtPrivate::QVersionTag sym ## _use(&sym)
0117 #  define QT_VERSION_TAG(sym, imp)       QT_VERSION_TAG2(sym, imp)
0118 #endif
0119 
0120 #ifdef Q_OF_ELF
0121 #  define QT_VERSION_TAG_SYMBOL(prefix, sym, m, n)      sym
0122 #else
0123 #  define QT_VERSION_TAG_SYMBOL2(prefix, sym, m, n)     prefix ## sym ## _ ## m ## _ ## n
0124 #  define QT_VERSION_TAG_SYMBOL(prefix, sym, m, n)      QT_VERSION_TAG_SYMBOL2(prefix, sym, m, n)
0125 #endif
0126 
0127 #if defined(QT_VERSION_TAG) && !defined(QT_NO_VERSION_TAGGING)
0128 #  ifndef QT_VERSION_TAG_SECTION
0129 #    define QT_VERSION_TAG_SECTION          __attribute__((section(".qtversion")))
0130 #  endif
0131 #  define QT_MANGLED_VERSION_TAG_IMPORT     QT_VERSION_TAG_SYMBOL(QT_MANGLE_IMPORT_PREFIX, QT_MANGLE_NAMESPACE(qt_version_tag), QT_VERSION_MAJOR, QT_VERSION_MINOR)
0132 #  define QT_MANGLED_VERSION_TAG            QT_VERSION_TAG_SYMBOL(, QT_MANGLE_NAMESPACE(qt_version_tag), QT_VERSION_MAJOR, QT_VERSION_MINOR)
0133 
0134 QT_VERSION_TAG(QT_MANGLED_VERSION_TAG, QT_MANGLED_VERSION_TAG_IMPORT);
0135 
0136 #  undef QT_MANGLED_VERSION_TAG
0137 #  undef QT_MANGLED_VERSION_TAG_IMPORT
0138 #  undef QT_VERSION_TAG_SECTION
0139 #endif
0140 
0141 QT_END_NAMESPACE
0142 
0143 #endif // QVERSIONTAGGING_H