Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qversiontagging.h
Go to the documentation of this file.
1// Copyright (C) 2022 Intel Corporation.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#if !defined(QVERSIONTAGGING_H)
6#define QVERSIONTAGGING_H
7
8#if 0
9#pragma qt_no_master_include
10#endif
11
12#include <QtCore/qcompilerdetection.h>
13#include <QtCore/qtconfigmacros.h>
14#include <QtCore/qtversionchecks.h>
15#include <QtCore/qtypes.h>
16
18
19QT_BEGIN_NAMESPACE
20
21/*
22 * Explanation
23 *
24 * This file causes all libraries, plugins, and applications that #include this
25 * file to automatically pull in a symbol found in QtCore that encodes the
26 * current Qt version number at the time of compilation. The relocation is
27 * designed so that it's impossible for the dynamic linker to perform lazy
28 * binding. Instead, it must resolve at load time or fail. That way, attempting
29 * to load such a library or plugin while an older QtCore is loaded will fail.
30 * Similarly, if an older QtCore is found when launching an application, the
31 * application will fail to launch.
32 *
33 * It's also possible to inspect which version is required by decoding the
34 * .qtversion section. The second pointer-sized variable is the required
35 * version, for example, for Qt 6.4.1:
36 *
37 * Hex dump of section [18] '.qtversion', 16 bytes at offset 0x1ee48:
38 * 0x00000000 b0ffffff ffffffff 01040600 00000000 ................
39 * ^^^^^^^^ ^^^^^^^^
40 *
41 * There will only be one copy of the section in the output library or application.
42 *
43 * This functionality can be disabled by defining QT_NO_VERSION_TAGGING. It's
44 * disabled if Qt was built statically.
45 *
46 * Windows notes:
47 *
48 * On Windows, the address of a __declspec(dllimport) variable is not a
49 * constant expression, unlike Unix systems. So we instead use the address of
50 * the import variable, which is created by prefixing the external name with
51 * "__imp_". Using that variable causes an import of the corresponding symbol
52 * from QtCore DLL.
53 *
54 * With MinGW (GCC and Clang), we use a C++17 inline variable, so the compiler
55 * and linker automatically merge the variables. The "used" __attribute__
56 * tells the compiler to always emit that variable, whether it's used or not.
57 *
58 * MSVC has no equivalent to that attribute, so instead we create an extern
59 * const variable and tell the linker to merge them all via
60 * __declspec(selectany).
61 *
62 * Unix notes:
63 *
64 * On Unix, we use the same C++17 inline variable solution as MinGW, but we
65 * don't need the "__imp_" trick.
66 *
67 * Additionally, on ELF systems like Linux and FreeBSD, the symbol in question
68 * is simply "qt_version_tag" in both QtCore and in this ELF module, but it
69 * has an ELF version attached to it (see qversiontagging.cpp and
70 * QtFlagHandlingHelpers.cmake). That way, the error message from the dynamic
71 * linker will say it can't find version "Qt_6.x".
72 */
73
74namespace QtPrivate {
76{
77 const void *symbol;
79 constexpr QVersionTag(const void *sym, int currentVersion = QT_VERSION)
81 {}
82};
83}
84
85#if !defined(QT_NO_VERSION_TAGGING) && (defined(QT_BUILD_CORE_LIB) || defined(QT_BOOTSTRAPPED) || defined(QT_STATIC))
86// don't make tags in QtCore, bootstrapped systems or if the user asked not to
87# define QT_NO_VERSION_TAGGING
88#endif
89
90#if defined(Q_OS_WIN)
91# ifdef Q_PROCESSOR_X86_32
92// 32-bit x86 convention does prepend a _
93# define QT_MANGLE_IMPORT_PREFIX _imp__
94# else
95// Calling convention on other architectures does not prepend a _
96# define QT_MANGLE_IMPORT_PREFIX __imp_
97# endif
98# if defined(Q_CC_MSVC_ONLY)
99# pragma section(".qtversion",read,shared)
100# define QT_VERSION_TAG_SECTION __declspec(allocate(".qtversion"))
101# define QT_VERSION_TAG_ATTRIBUTE __declspec(selectany) extern const
102# else
103# define QT_VERSION_TAG_ATTRIBUTE __attribute__((used)) constexpr inline
104# endif
105# define QT_VERSION_TAG2(sym, imp)
106 extern "C" const char * const imp;
107 QT_VERSION_TAG_ATTRIBUTE QT_VERSION_TAG_SECTION QtPrivate::QVersionTag sym ## _used(&imp)
108# define QT_VERSION_TAG(sym, imp) QT_VERSION_TAG2(sym, imp)
109#elif defined(Q_CC_GNU) && __has_attribute(used)
110# ifdef Q_OS_DARWIN
111# define QT_VERSION_TAG_SECTION __attribute__((section("__DATA,.qtversion")))
112# endif
113# define QT_VERSION_TAG_ATTRIBUTE __attribute__((visibility("hidden"), used))
114# define QT_VERSION_TAG2(sym, imp)
115 extern "C" Q_DECL_IMPORT const char sym;
116 QT_VERSION_TAG_ATTRIBUTE QT_VERSION_TAG_SECTION constexpr inline QtPrivate::QVersionTag sym ## _use(&sym)
117# define QT_VERSION_TAG(sym, imp) QT_VERSION_TAG2(sym, imp)
118#endif
119
120#ifdef Q_OF_ELF
121# define QT_VERSION_TAG_SYMBOL(prefix, sym, m, n) sym
122#else
123# define QT_VERSION_TAG_SYMBOL2(prefix, sym, m, n) prefix ## sym ## _ ## m ## _ ## n
124# define QT_VERSION_TAG_SYMBOL(prefix, sym, m, n) QT_VERSION_TAG_SYMBOL2(prefix, sym, m, n)
125#endif
126
127#if defined(QT_VERSION_TAG) && !defined(QT_NO_VERSION_TAGGING)
128# ifndef QT_VERSION_TAG_SECTION
129# define QT_VERSION_TAG_SECTION __attribute__((section(".qtversion")))
130# endif
131# 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)
132# define QT_MANGLED_VERSION_TAG QT_VERSION_TAG_SYMBOL(, QT_MANGLE_NAMESPACE(qt_version_tag), QT_VERSION_MAJOR, QT_VERSION_MINOR)
133
134QT_VERSION_TAG(QT_MANGLED_VERSION_TAG, QT_MANGLED_VERSION_TAG_IMPORT);
135
136# undef QT_MANGLED_VERSION_TAG
137# undef QT_MANGLED_VERSION_TAG_IMPORT
138# undef QT_VERSION_TAG_SECTION
139#endif
140
141QT_END_NAMESPACE
142
143#endif // QVERSIONTAGGING_H
#define __has_attribute(x)
#define make_versioned_symbol(sym, m, n, separator)
#define SSYM
#define make_versioned_symbol2(sym, m, n, separator)
#define SYM
QT_REQUIRE_CONFIG(version_tagging)
#define QT_VERSION_TAG_SYMBOL2(prefix, sym, m, n)
constexpr QVersionTag(const void *sym, int currentVersion=QT_VERSION)