diff options
Diffstat (limited to 'src/corelib/plugin/qplugin.h')
-rw-r--r-- | src/corelib/plugin/qplugin.h | 262 |
1 files changed, 156 insertions, 106 deletions
diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h index d53182f1a9..909c8acdcc 100644 --- a/src/corelib/plugin/qplugin.h +++ b/src/corelib/plugin/qplugin.h @@ -1,61 +1,23 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2018 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** 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 https://www.qt.io/terms-conditions. For further -** information use the contact form at https://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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// Copyright (C) 2021 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QPLUGIN_H #define QPLUGIN_H +#if 0 +#pragma qt_class(QtPlugin) +#endif + #include <QtCore/qobject.h> #include <QtCore/qpointer.h> #include <QtCore/qjsonobject.h> -QT_BEGIN_NAMESPACE - +#include <QtCore/q20algorithm.h> -#ifndef Q_EXTERN_C -# ifdef __cplusplus -# define Q_EXTERN_C extern "C" -# else -# define Q_EXTERN_C extern -# endif -#endif +QT_BEGIN_NAMESPACE +// Used up to Qt 6.2 inline constexpr unsigned char qPluginArchRequirements() { return 0 @@ -72,53 +34,100 @@ inline constexpr unsigned char qPluginArchRequirements() } typedef QObject *(*QtPluginInstanceFunction)(); -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) -typedef const char *(*QtPluginMetaDataFunction)(); -#else struct QPluginMetaData { - const uchar *data; + static constexpr quint8 CurrentMetaDataVersion = 1; + static constexpr char MagicString[] = { + 'Q', 'T', 'M', 'E', 'T', 'A', 'D', 'A', 'T', 'A', ' ', '!' + }; + + template <size_t OSize, typename OO, size_t ISize, typename II> + static constexpr void copy(OO (&out)[OSize], II (&in)[ISize]) + { + static_assert(OSize <= ISize, "Output would not be fully initialized"); + q20::copy_n(in, OSize, out); + } + + static constexpr quint8 archRequirements() + { + quint8 v = 0; +#if defined(__AVX512F__) + v = 4; // x86-64-v4: AVX512F, AVX512BW, AVX512CD, AVX512DQ and AVX512VL +#elif defined(__AVX__) || defined(__BMI__) || defined(__BMI2__) || defined(__MOVBE__) + v = 3; // x86-64-v3: AVX, AVX2, BMI1, BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE +#elif defined(__SSE3__) + v = 2; // x86-64-v2: POPCNT, SSE3, SSSE3, SSE4.1 and SSE4.2. +#elif defined(__SSE__) || defined(__MMX___) + v = 1; // x86-64 baseline: SSE and SSE2 +#endif +#ifndef QT_NO_DEBUG + v |= 0x80; +#endif + return v; + } + + struct Header { + quint8 version = CurrentMetaDataVersion; + quint8 qt_major_version = QT_VERSION_MAJOR; + quint8 qt_minor_version = QT_VERSION_MINOR; + quint8 plugin_arch_requirements = archRequirements(); + }; + static_assert(alignof(Header) == 1, "Alignment of header incorrect with this compiler"); + + struct MagicHeader { + char magic[sizeof(QPluginMetaData::MagicString)] = {}; + constexpr MagicHeader() { copy(magic, QPluginMetaData::MagicString); } + Header header = {}; + }; + static_assert(alignof(MagicHeader) == 1, "Alignment of header incorrect with this compiler"); + + struct ElfNoteHeader { + static constexpr quint32 NoteType = 0x74510001; + static constexpr char NoteName[] = "qt-project!"; + + // ELF note header + quint32 n_namesz = sizeof(name); + quint32 n_descsz; + quint32 n_type = NoteType; + char name[sizeof(NoteName)] = {}; + + // payload + alignas(void *) // mandatory alignment as per ELF note requirements + Header header = {}; + constexpr ElfNoteHeader(quint32 payloadSize) : n_descsz(sizeof(header) + payloadSize) + { QPluginMetaData::copy(name, NoteName); } + }; + static_assert(alignof(ElfNoteHeader) == alignof(void*), "Alignment of header incorrect with this compiler"); + static_assert((sizeof(ElfNoteHeader::name) % 4) == 0, "ELF note name length not a multiple of 4"); + + const void *data; size_t size; }; typedef QPluginMetaData (*QtPluginMetaDataFunction)(); -#endif struct Q_CORE_EXPORT QStaticPlugin { -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) public: constexpr QStaticPlugin(QtPluginInstanceFunction i, QtPluginMetaDataFunction m) - : instance(i), rawMetaData(m().data), rawMetaDataSize(m().size) + : instance(i), rawMetaDataSize(m().size), rawMetaData(m().data) {} QtPluginInstanceFunction instance; + QJsonObject metaData() const; + private: - // ### Qt 6: revise, as this is not standard-layout - const void *rawMetaData; qsizetype rawMetaDataSize; -public: -#elif !defined(Q_QDOC) - // Note: This struct is initialized using an initializer list. - // As such, it cannot have any new constructors or variables. - QtPluginInstanceFunction instance; - QtPluginMetaDataFunction rawMetaData; -#else - // Since qdoc gets confused by the use of function - // pointers, we add these dummes for it to parse instead: - QObject *instance(); - const char *rawMetaData(); -#endif - QJsonObject metaData() const; + const void *rawMetaData; + friend class QFactoryLoader; }; Q_DECLARE_TYPEINFO(QStaticPlugin, Q_PRIMITIVE_TYPE); void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin); -#if (defined(Q_OF_ELF) || defined(Q_OS_WIN)) && (defined (Q_CC_GNU) || defined(Q_CC_CLANG)) +#if defined(Q_OF_ELF) || (defined(Q_OS_WIN) && (defined (Q_CC_GNU) || defined(Q_CC_CLANG))) # define QT_PLUGIN_METADATA_SECTION \ __attribute__ ((section (".qtmetadata"))) __attribute__((used)) -#elif defined(Q_OS_MAC) -// TODO: Implement section parsing on Mac +#elif defined(Q_OS_DARWIN) # define QT_PLUGIN_METADATA_SECTION \ __attribute__ ((section ("__TEXT,qtmetadata"))) __attribute__((used)) #elif defined(Q_CC_MSVC) @@ -130,6 +139,57 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin); # define QT_PLUGIN_METADATA_SECTION #endif +// Since Qt 6.3 +template <auto (&PluginMetaData)> class QPluginMetaDataV2 +{ + struct ElfNotePayload : QPluginMetaData::ElfNoteHeader { + static constexpr size_t HeaderOffset = offsetof(QPluginMetaData::ElfNoteHeader, header); + quint8 payload[sizeof(PluginMetaData)] = {}; + constexpr ElfNotePayload() : ElfNoteHeader(sizeof(PluginMetaData)) + { QPluginMetaData::copy(payload, PluginMetaData); } + }; + + struct RegularPayload : QPluginMetaData::MagicHeader { + static constexpr size_t HeaderOffset = offsetof(QPluginMetaData::MagicHeader, header); + quint8 payload[sizeof(PluginMetaData)] = {}; + constexpr RegularPayload() { QPluginMetaData::copy(payload, PluginMetaData); } + }; + + struct StaticPayload { + static constexpr size_t HeaderOffset = 0; + QPluginMetaData::Header header = {}; + quint8 payload[sizeof(PluginMetaData)] = {}; + constexpr StaticPayload() { QPluginMetaData::copy(payload, PluginMetaData); } + }; + +#if defined(QT_STATICPLUGIN) +# define QT_PLUGIN_METADATAV2_SECTION + using Payload = StaticPayload; +#elif defined(Q_OF_ELF) +# ifdef Q_CC_CLANG +# define QT_PLUGIN_METADATAV2_SECTION \ + __attribute__((section(".note.qt.metadata"), used, aligned(alignof(void *)), \ + no_sanitize("address"))) +# else +# define QT_PLUGIN_METADATAV2_SECTION \ + __attribute__((section(".note.qt.metadata"), used, aligned(alignof(void *)))) +# endif + using Payload = ElfNotePayload; +#else +# define QT_PLUGIN_METADATAV2_SECTION QT_PLUGIN_METADATA_SECTION + using Payload = RegularPayload; +#endif + + Payload payload = {}; + +public: + operator QPluginMetaData() const + { + Q_ASSERT(reinterpret_cast<const char *>(&payload) + Payload::HeaderOffset == + reinterpret_cast<const char *>(&payload.header)); + return { &payload.header, sizeof(payload) - Payload::HeaderOffset }; + } +}; #define Q_IMPORT_PLUGIN(PLUGIN) \ extern const QT_PREPEND_NAMESPACE(QStaticPlugin) qt_static_plugin_##PLUGIN(); \ @@ -160,48 +220,38 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin); } #if defined(QT_STATICPLUGIN) +# define QT_MOC_EXPORT_PLUGIN_COMMON(PLUGINCLASS, MANGLEDNAME) \ + static QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##MANGLEDNAME() \ + Q_PLUGIN_INSTANCE(PLUGINCLASS) \ + const QT_PREPEND_NAMESPACE(QStaticPlugin) qt_static_plugin_##MANGLEDNAME() \ + { return { qt_plugin_instance_##MANGLEDNAME, qt_plugin_query_metadata_##MANGLEDNAME}; } \ + /**/ -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) # define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \ - static QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGINCLASSNAME() \ - Q_PLUGIN_INSTANCE(PLUGINCLASS) \ static QPluginMetaData qt_plugin_query_metadata_##PLUGINCLASSNAME() \ - { return { qt_pluginMetaData, sizeof qt_pluginMetaData }; } \ - const QT_PREPEND_NAMESPACE(QStaticPlugin) qt_static_plugin_##PLUGINCLASSNAME() { \ - return { qt_plugin_instance_##PLUGINCLASSNAME, qt_plugin_query_metadata_##PLUGINCLASSNAME}; \ - } -#else -# define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \ - static QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGINCLASSNAME() \ - Q_PLUGIN_INSTANCE(PLUGINCLASS) \ - static const char *qt_plugin_query_metadata_##PLUGINCLASSNAME() { return reinterpret_cast<const char *>(qt_pluginMetaData); } \ - const QT_PREPEND_NAMESPACE(QStaticPlugin) qt_static_plugin_##PLUGINCLASSNAME() { \ - QT_PREPEND_NAMESPACE(QStaticPlugin) plugin = { qt_plugin_instance_##PLUGINCLASSNAME, qt_plugin_query_metadata_##PLUGINCLASSNAME}; \ - return plugin; \ - } -#endif + { return { qt_pluginMetaData_##PLUGINCLASSNAME, sizeof qt_pluginMetaData_##PLUGINCLASSNAME }; } \ + QT_MOC_EXPORT_PLUGIN_COMMON(PLUGINCLASS, PLUGINCLASSNAME) +# define QT_MOC_EXPORT_PLUGIN_V2(PLUGINCLASS, MANGLEDNAME, MD) \ + static QT_PREPEND_NAMESPACE(QPluginMetaData) qt_plugin_query_metadata_##MANGLEDNAME() \ + { static constexpr QPluginMetaDataV2<MD> md{}; return md; } \ + QT_MOC_EXPORT_PLUGIN_COMMON(PLUGINCLASS, MANGLEDNAME) #else -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +# define QT_MOC_EXPORT_PLUGIN_COMMON(PLUGINCLASS, MANGLEDNAME) \ + extern "C" Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance() \ + Q_PLUGIN_INSTANCE(PLUGINCLASS) \ + /**/ # define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \ - Q_EXTERN_C Q_DECL_EXPORT \ + extern "C" Q_DECL_EXPORT \ QPluginMetaData qt_plugin_query_metadata() \ - { return { qt_pluginMetaData, sizeof qt_pluginMetaData }; } \ - Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance() \ - Q_PLUGIN_INSTANCE(PLUGINCLASS) - -#else - -# define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \ - Q_EXTERN_C Q_DECL_EXPORT \ - const char *qt_plugin_query_metadata() \ - { return reinterpret_cast<const char *>(qt_pluginMetaData); } \ - Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance() \ - Q_PLUGIN_INSTANCE(PLUGINCLASS) - -#endif + { return { qt_pluginMetaData_##PLUGINCLASSNAME, sizeof qt_pluginMetaData_##PLUGINCLASSNAME }; } \ + QT_MOC_EXPORT_PLUGIN_COMMON(PLUGINCLASS, PLUGINCLASSNAME) +# define QT_MOC_EXPORT_PLUGIN_V2(PLUGINCLASS, MANGLEDNAME, MD) \ + extern "C" Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QPluginMetaData) qt_plugin_query_metadata_v2()\ + { static constexpr QT_PLUGIN_METADATAV2_SECTION QPluginMetaDataV2<MD> md{}; return md; } \ + QT_MOC_EXPORT_PLUGIN_COMMON(PLUGINCLASS, MANGLEDNAME) #endif #define Q_EXPORT_PLUGIN(PLUGIN) \ |