Revision control

++ // 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
++ // Qt-Security score:significant reason:default
++
++ #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>
++
++ #include <QtCore/q20algorithm.h>
++
++ QT_BEGIN_NAMESPACE
++
++ // Used up to Qt 6.2
++ inline constexpr unsigned char qPluginArchRequirements()
++ {
++ return 0
++ #ifndef QT_NO_DEBUG
++ | 1
++ #endif
++ #ifdef __AVX2__
++ | 2
++ # ifdef __AVX512F__
++ | 4
++ # endif
++ #endif
++ ;
++ }
++
++ typedef QObject *(*QtPluginInstanceFunction)();
++ struct QPluginMetaData
++ {
++ 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)();
++
++
++ struct Q_CORE_EXPORT QStaticPlugin
++ {
++ public:
++ constexpr QStaticPlugin(QtPluginInstanceFunction i, QtPluginMetaDataFunction m)
++ : instance(i), rawMetaDataSize(m().size), rawMetaData(m().data)
++ {}
++ QtPluginInstanceFunction instance;
++ QJsonObject metaData() const;
++
++ private:
++ qsizetype rawMetaDataSize;
++ 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)))
++ # define QT_PLUGIN_METADATA_SECTION \
++ __attribute__ ((section (".qtmetadata"))) __attribute__((used))
++ #elif defined(Q_OS_DARWIN)
++ # define QT_PLUGIN_METADATA_SECTION \
++ __attribute__ ((section ("__TEXT,qtmetadata"))) __attribute__((used))
++ #elif defined(Q_CC_MSVC)
++ // TODO: Implement section parsing for MSVC
++ #pragma section(".qtmetadata",read,shared)
++ # define QT_PLUGIN_METADATA_SECTION \
++ __declspec(allocate(".qtmetadata"))
++ #else
++ # 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_MANGLE_NAMESPACE(qt_static_plugin_##PLUGIN)(); \
++ namespace { \
++ struct Static##PLUGIN##PluginInstance { \
++ Static##PLUGIN##PluginInstance() { \
++ qRegisterStaticPluginFunction(QT_MANGLE_NAMESPACE(qt_static_plugin_##PLUGIN)()); \
++ } \
++ }; \
++ } /* namespace */ \
++ /* QTBUG-139615: static, to work around bug in clazy-non-pod-global-static */ \
++ static Static##PLUGIN##PluginInstance static##PLUGIN##Instance; \
++
++ #if defined(QT_PLUGIN_RESOURCE_INIT_FUNCTION)
++ # define QT_PLUGIN_RESOURCE_INIT \
++ extern void QT_PLUGIN_RESOURCE_INIT_FUNCTION(); \
++ QT_PLUGIN_RESOURCE_INIT_FUNCTION();
++ #else
++ # define QT_PLUGIN_RESOURCE_INIT
++ #endif
++
++ #define Q_PLUGIN_INSTANCE(IMPLEMENTATION) \
++ { \
++ static QT_PREPEND_NAMESPACE(QPointer)<QT_PREPEND_NAMESPACE(QObject)> _instance; \
++ if (!_instance) { \
++ QT_PLUGIN_RESOURCE_INIT \
++ _instance = new IMPLEMENTATION; \
++ } \
++ return _instance; \
++ }
++
++ #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_MANGLE_NAMESPACE(qt_static_plugin_##MANGLEDNAME)() \
++ { return { qt_plugin_instance_##MANGLEDNAME, qt_plugin_query_metadata_##MANGLEDNAME}; } \
++ /**/
++
++ # define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \
++ static QPluginMetaData qt_plugin_query_metadata_##PLUGINCLASSNAME() \
++ { 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
++ # 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) \
++ extern "C" Q_DECL_EXPORT \
++ QPluginMetaData qt_plugin_query_metadata() \
++ { 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) \
++ Q_EXPORT_PLUGIN2(PLUGIN, PLUGIN)
++ # define Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) \
++ static_assert(false, "Old plugin system used")
++
++ # define Q_EXPORT_STATIC_PLUGIN2(PLUGIN, PLUGINCLASS) \
++ static_assert(false, "Old plugin system used")
++
++
++ QT_END_NAMESPACE
++
++ #endif // Q_PLUGIN_H