From bdb8ab0690eb927575de6f3e34d2b49a148e046f 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. 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 --- src/corelib/global/global.pri | 3 +- src/corelib/global/qglobal.h | 1 + src/corelib/global/qversiontagging.h | 86 ++++++++++++++++++++++++++++++++++++ 3 files changed, 89 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 2165a6c22e86948655c0074d50f8669c8a192d40..e231a8f1fddf8fd705f665089c235bd11a55f0b4 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 15d9b6536a9f1ee85371fea6dc9115438eec32d1..1a5afbe753ad08d088c9174c58fcce54ce327e0e 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -1104,6 +1104,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 0000000000000000000000000000000000000000..94246dd08b139fe3b9040a95824dcb3116a5b790 --- /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.6.0