summaryrefslogtreecommitdiffstats
path: root/src/corelib/global
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2015-06-02 11:30:57 -0700
committerThiago Macieira <thiago.macieira@intel.com>2015-10-20 16:21:03 +0000
commitbf929938293abd398c2c6f3e88c4774e56f75efa (patch)
tree39276ef7f3d68d2410d8d1c8dbb67eddb2781aaf /src/corelib/global
parent629ceec208ad5fe9f5d201fc42fce611e55c567d (diff)
Add an automatic use of the ELF-versioned QtCore symbol
See the comment in the header for an explanation of what it does. This trick is enabled for every single .o that is compiled, unless QT_NO_VERSION_TAGGING is defined. The assembly expands to a COMDAT section, which is mergeable by the linker, so only one copy of the output is present in the ELF module. This is enabled only for Linux and x86 / x86-64 / x32 due to the requirement of writing assembly and relocations, so it needs to be tested on each platform, which I have not done. It might work on Solaris/x86, but again it requires testing. Support for other architectures requires different assembly output and relocations and can be added as needed, but they are not as important since this trick is has most value on desktop systems. Change-Id: I049a653beeb5454c9539ffff13e3ff5782a8cb86 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> Reviewed-by: Rex Dieter <rdieter@gmail.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/global')
-rw-r--r--src/corelib/global/global.pri3
-rw-r--r--src/corelib/global/qglobal.h1
-rw-r--r--src/corelib/global/qversiontagging.h86
3 files changed, 89 insertions, 1 deletions
diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri
index 8ecde5a769..aa4945f90e 100644
--- a/src/corelib/global/global.pri
+++ b/src/corelib/global/global.pri
@@ -17,7 +17,8 @@ HEADERS += \
global/qisenum.h \
global/qtypetraits.h \
global/qflags.h \
- global/qhooks_p.h
+ global/qhooks_p.h \
+ global/qversiontagging.h
SOURCES += \
global/archdetect.cpp \
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 81ab3bcb9e..d86e410194 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -1126,6 +1126,7 @@ QT_END_NAMESPACE
#include <QtCore/qatomic.h>
#include <QtCore/qglobalstatic.h>
#include <QtCore/qnumeric.h>
+#include <QtCore/qversiontagging.h>
#endif /* __cplusplus */
diff --git a/src/corelib/global/qversiontagging.h b/src/corelib/global/qversiontagging.h
new file mode 100644
index 0000000000..22e6e82a58
--- /dev/null
+++ b/src/corelib/global/qversiontagging.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Intel Corporation.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// qglobal.h includes this header, so keep it outside of our include guards
+#include <QtCore/qglobal.h>
+
+#if !defined(QVERSIONTAGGING_H)
+#define QVERSIONTAGGING_H
+
+QT_BEGIN_NAMESPACE
+
+/*
+ * Ugly hack warning and explanation:
+ *
+ * This file causes all ELF modules, be they libraries or applications, to use the
+ * qt_version_tag symbol that is present in QtCore. Such symbol is versioned,
+ * so the linker will automatically pull the current Qt version and add it to
+ * the ELF header of the library/application. The assembly produces one section
+ * called ".qtversion" containing two pointer-sized values. The first is a
+ * relocation to the qt_version_tag symbol (which is what causes the ELF
+ * version to get used). The second value is the current Qt version at the time
+ * of compilation.
+ *
+ * There will only be one copy of the section in the output library or application.
+ */
+
+#if defined(QT_BUILD_CORE_LIB) || defined(QT_BOOTSTRAPPED) || defined(QT_NO_VERSION_TAGGING)
+// don't make tags in QtCore, bootstrapped systems or if the user asked not to
+#elif defined(Q_CC_GNU)
+# if defined(Q_PROCESSOR_X86) && (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD_KERNEL))
+# ifdef __LP64__
+# define QT_VERSION_TAG_RELOC(sym) ".quad " QT_STRINGIFY(QT_MANGLE_NAMESPACE(sym)) "@GOTPCREL\n"
+# elif defined(Q_PROCESSOR_X86_64) // x32
+# define QT_VERSION_TAG_RELOC(sym) ".long " QT_STRINGIFY(QT_MANGLE_NAMESPACE(sym)) "@GOTPCREL\n"
+# else // x86
+# define QT_VERSION_TAG_RELOC(sym) ".long " QT_STRINGIFY(QT_MANGLE_NAMESPACE(sym)) "@GOT\n"
+# endif
+# define QT_VERSION_TAG(sym) \
+ asm ( \
+ ".section .qtversion, \"aG\", @progbits, qt_version_tag, comdat\n" \
+ ".align 8\n" \
+ QT_VERSION_TAG_RELOC(sym) \
+ ".long " QT_STRINGIFY(QT_VERSION) "\n" \
+ ".align 8\n" \
+ ".previous" \
+ )
+# endif
+#endif
+
+#if defined(QT_VERSION_TAG)
+QT_VERSION_TAG(qt_version_tag);
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QVERSIONTAGGING_H