From 7a2d2a1c3b66308cf03a00757f8fd97f043ccde4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 2 Jun 2015 11:30:57 -0700 Subject: [PATCH] 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. The next commit will add a configure-time option to set QT_NO_VERSION_TAGGING to qconfig.h. 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 probably works on the BSDs too and 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 --- src/corelib/global/global.pri | 3 +- src/corelib/global/qglobal.h | 1 + src/corelib/global/qversiontagging.h | 80 ++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 src/corelib/global/qversiontagging.h diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index fdbebca..9f31fb9 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 c4e2f76..e7995ac 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -1103,6 +1103,7 @@ QT_END_NAMESPACE #include #include #include +#include #endif /* __cplusplus */ diff --git a/src/corelib/global/qversiontagging.h b/src/corelib/global/qversiontagging.h new file mode 100644 index 0000000..94246dd --- /dev/null +++ b/src/corelib/global/qversiontagging.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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 + +#if !defined(QVERSIONTAGGING_H) && !defined(QT_NO_VERSION_TAGGING) +#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) +// skip +#elif defined(Q_CC_GNU) +# if defined(Q_PROCESSOR_X86) && defined(Q_OS_LINUX) +asm ( +".section .qtversion, \"aG\", @progbits, qt_version_tag, comdat\n" +".align 8\n" +# ifdef __LP64__ +".quad " QT_STRINGIFY(QT_MANGLE_NAMESPACE(qt_version_tag)) "@GOTPCREL\n" +# elif defined(Q_PROCESSOR_X86_64) // x32 +".long " QT_STRINGIFY(QT_MANGLE_NAMESPACE(qt_version_tag)) "@GOTPCREL\n" +# else // x86 +".long " QT_STRINGIFY(QT_MANGLE_NAMESPACE(qt_version_tag)) "@GOT\n" +#endif +".long " QT_STRINGIFY(QT_VERSION) "\n" +".align 8\n" +".previous" +); +# endif +#endif + +QT_END_NAMESPACE + +#endif // QVERSIONTAGGING_H && !QT_NO_VERSION_TAGGING -- 2.3.5