Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qlibrary.cpp
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// Copyright (C) 2021 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4#include "qlibrary.h"
5#include "qlibrary_p.h"
6
7#include <q20algorithm.h>
8#include <qbytearraymatcher.h>
9#include <qdebug.h>
10#include <qendian.h>
11#include <qfile.h>
12#include <qfileinfo.h>
13#include <qjsondocument.h>
14#include <qmap.h>
15#include <qmutex.h>
17#include <qstringlist.h>
18
19#ifdef Q_OS_DARWIN
20# include <private/qcore_mac_p.h>
21#endif
22#include <private/qcoreapplication_p.h>
23#include <private/qloggingregistry_p.h>
24#include <private/qsystemerror_p.h>
25
26#include "qcoffpeparser_p.h"
27#include "qelfparser_p.h"
28#include "qfactoryloader_p.h"
29#include "qmachparser_p.h"
30
31#include <qtcore_tracepoints_p.h>
32
34
35using namespace Qt::StringLiterals;
36
37Q_TRACE_POINT(qtcore, QLibraryPrivate_load_entry, const QString &fileName);
38Q_TRACE_POINT(qtcore, QLibraryPrivate_load_exit, bool success);
39
40// On Unix systema and on Windows with MinGW, we can mix and match debug and
41// release plugins without problems. (unless compiled in debug-and-release mode
42// - why?)
43static constexpr bool PluginMustMatchQtDebug =
45#if defined(Q_CC_MINGW)
46 && QT_CONFIG(debug_and_release)
47#endif
48 ;
49
50#ifdef QT_NO_DEBUG
51static constexpr bool QtBuildIsDebug = false;
52#else
53static constexpr bool QtBuildIsDebug = true;
54#endif
55
56Q_LOGGING_CATEGORY_WITH_ENV_OVERRIDE(qt_lcDebugPlugins, "QT_DEBUG_PLUGINS", "qt.core.plugin.loader")
57static Q_LOGGING_CATEGORY_WITH_ENV_OVERRIDE(lcDebugLibrary, "QT_DEBUG_PLUGINS", "qt.core.library")
58
164static QLibraryScanResult qt_find_pattern(const char *s, qsizetype s_len, QString *errMsg)
165{
166 /*
167 We used to search from the end of the file so we'd skip the code and find
168 the read-only data that usually follows. Unfortunately, in debug builds,
169 the debug sections come after and are usually much bigger than everything
170 else, making this process slower than necessary with debug plugins.
171
172 More importantly, the pattern string may exist in the debug information due
173 to it being used in the plugin in the first place.
174 */
175#if defined(Q_OF_ELF)
176 return QElfParser::parse({s, s_len}, errMsg);
177#elif defined(Q_OF_MACH_O)
178 return QMachOParser::parse(s, s_len, errMsg);
179#elif defined(Q_OS_WIN)
180 return QCoffPeParser::parse({s, s_len}, errMsg);
181#else
182# warning "Qt does not know how to efficiently parse your platform's binary format; using slow fall-back."
183#endif
184 static constexpr auto matcher = [] {
185 // QPluginMetaData::MagicString is not NUL-terminated, but
186 // qMakeStaticByteArrayMatcher requires its argument to be, so
187 // duplicate here, but statically check we didn't mess up:
188 constexpr auto &pattern = "QTMETADATA !";
189 constexpr auto magic = std::string_view(QPluginMetaData::MagicString,
191 static_assert(pattern == magic);
193 }();
194 qsizetype i = matcher.indexIn({s, s_len});
195 if (i < 0) {
196 *errMsg = QLibrary::tr("'%1' is not a Qt plugin").arg(*errMsg);
197 return QLibraryScanResult{};
198 }
200 return { i, s_len - i };
201}
202
203/*
204 This opens the specified library, mmaps it into memory, and searches
205 for the QT_PLUGIN_VERIFICATION_DATA. The advantage of this approach is that
206 we can get the verification data without have to actually load the library.
207 This lets us detect mismatches more safely.
208
209 Returns \c false if version information is not present, or if the
210 information could not be read.
211 Returns true if version information is present and successfully read.
212*/
214{
215 QFile file(library);
217 if (lib)
219 qCWarning(qt_lcDebugPlugins, "%ls: cannot open: %ls", qUtf16Printable(library),
221 return {};
222 }
223
224 // Files can be bigger than the virtual memory size on 32-bit systems, so
225 // we limit to 512 MB there. For 64-bit, we allow up to 2^40 bytes.
226 constexpr qint64 MaxMemoryMapSize =
227 Q_INT64_C(1) << (sizeof(qsizetype) > 4 ? 40 : 29);
228
229 qsizetype fdlen = qMin(file.size(), MaxMemoryMapSize);
230 const char *filedata = reinterpret_cast<char *>(file.map(0, fdlen));
231
232#ifdef Q_OS_UNIX
233 if (filedata == nullptr) {
234 // If we can't mmap(), then the dynamic loader won't be able to either.
235 // This can't be used as a plugin.
236 qCWarning(qt_lcDebugPlugins, "%ls: failed to map to memory: %ls",
238 return {};
239 }
240#else
242 if (filedata == nullptr) {
243 // It's unknown at this point whether Windows supports LoadLibrary() on
244 // files that fail to CreateFileMapping / MapViewOfFile, so we err on
245 // the side of doing a regular read into memory (up to 64 MB).
246 data = file.read(64 * 1024 * 1024);
247 filedata = data.constData();
248 fdlen = data.size();
249 }
250#endif
251
252 QString errMsg = library;
253 QLibraryScanResult r = qt_find_pattern(filedata, fdlen, &errMsg);
254 if (r.length) {
255#if defined(Q_OF_MACH_O)
256 if (r.isEncrypted)
257 return r;
258#endif
259 if (!lib->metaData.parse(QByteArrayView(filedata + r.pos, r.length))) {
260 errMsg = lib->metaData.errorString();
261 qCDebug(qt_lcDebugPlugins, "Found invalid metadata in lib %ls: %ls",
263 } else {
264 qCDebug(qt_lcDebugPlugins, "Found metadata in lib %ls, metadata=\n%s\n",
265 qUtf16Printable(library),
267 return r;
268 }
269 } else {
270 qCDebug(qt_lcDebugPlugins, "Failed to find metadata in lib %ls: %ls",
272 }
273
274 lib->errorString = QLibrary::tr("Failed to extract plugin meta data from '%1': %2")
275 .arg(library, errMsg);
276 return {};
277}
278
279static void installCoverageTool(QLibraryPrivate *libPrivate)
280{
281#ifdef __COVERAGESCANNER__
282 /*
283 __COVERAGESCANNER__ is defined when Qt has been instrumented for code
284 coverage by TestCocoon. CoverageScanner is the name of the tool that
285 generates the code instrumentation.
286 This code is required here when code coverage analysis with TestCocoon
287 is enabled in order to allow the loading application to register the plugin
288 and then store its execution report. The execution report gathers information
289 about each part of the plugin's code that has been used when
290 the plugin was loaded by the launching application.
291 The execution report for the plugin will go to the same execution report
292 as the one defined for the application loading it.
293 */
294
295 int ret = __coveragescanner_register_library(libPrivate->fileName.toLocal8Bit());
296
297 if (ret >= 0) {
298 qDebug("coverage data for %ls registered",
299 qUtf16Printable(libPrivate->fileName));
300 } else {
301 qWarning("could not register %ls: error %d; coverage data may be incomplete",
302 qUtf16Printable(libPrivate->fileName),
303 ret);
304 }
305 }
306#else
307 Q_UNUSED(libPrivate);
308#endif
309}
310
312{
313public:
314 inline ~QLibraryStore();
315 static inline QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version, QLibrary::LoadHints loadHints);
316 static inline void releaseLibrary(QLibraryPrivate *lib);
317
318 static inline void cleanup();
319
320private:
321 static inline QLibraryStore *instance();
322
323 // all members and instance() are protected by qt_library_mutex
325 LibraryMap libraryMap;
326};
327
328Q_CONSTINIT static QBasicMutex qt_library_mutex;
329Q_CONSTINIT static QLibraryStore *qt_library_data = nullptr;
330Q_CONSTINIT static bool qt_library_data_once;
331
333{
334 qt_library_data = nullptr;
335}
336
338{
340 if (!data)
341 return;
342
343 // find any libraries that are still loaded but have a no one attached to them
344 LibraryMap::Iterator it = data->libraryMap.begin();
345 for (; it != data->libraryMap.end(); ++it) {
346 QLibraryPrivate *lib = it.value();
347 if (lib->libraryRefCount.loadRelaxed() == 1) {
348 if (lib->libraryUnloadCount.loadRelaxed() > 0) {
349 Q_ASSERT(lib->pHnd.loadRelaxed());
350 lib->libraryUnloadCount.storeRelaxed(1);
351#if defined(Q_OS_DARWIN)
352 // We cannot fully unload libraries, as we don't know if there are
353 // lingering references (in system threads e.g.) to Objective-C classes
354 // defined in the library.
356#else
357 lib->unload();
358#endif
359 }
360 delete lib;
361 it.value() = nullptr;
362 }
363 }
364
365 // dump all objects that remain
366 if (lcDebugLibrary().isDebugEnabled()) {
367 for (QLibraryPrivate *lib : std::as_const(data->libraryMap)) {
368 if (lib)
369 qDebug(lcDebugLibrary)
370 << "On QtCore unload," << lib->fileName << "was leaked, with"
371 << lib->libraryRefCount.loadRelaxed() << "users";
372 }
373 }
374
375 delete data;
376}
377
378static void qlibraryCleanup()
379{
381}
382Q_DESTRUCTOR_FUNCTION(qlibraryCleanup)
383
384// must be called with a locked mutex
385QLibraryStore *QLibraryStore::instance()
386{
388 // only create once per process lifetime
391 }
392 return qt_library_data;
393}
394
396 QLibrary::LoadHints loadHints)
397{
399 QLibraryStore *data = instance();
400
401 QString mapName = version.isEmpty() ? fileName : fileName + u'\0' + version;
402
403 // check if this library is already loaded
404 QLibraryPrivate *lib = nullptr;
405 if (Q_LIKELY(data)) {
406 lib = data->libraryMap.value(mapName);
407 if (lib)
408 lib->mergeLoadHints(loadHints);
409 }
410 if (!lib)
411 lib = new QLibraryPrivate(fileName, version, loadHints);
412
413 // track this library
414 if (Q_LIKELY(data) && !fileName.isEmpty())
415 data->libraryMap.insert(mapName, lib);
416
417 lib->libraryRefCount.ref();
418 return lib;
419}
420
422{
424 QLibraryStore *data = instance();
425
426 if (lib->libraryRefCount.deref()) {
427 // still in use
428 return;
429 }
430
431 // no one else is using
432 Q_ASSERT(lib->libraryUnloadCount.loadRelaxed() == 0);
433
434 if (Q_LIKELY(data) && !lib->fileName.isEmpty()) {
435 qsizetype n = erase_if(data->libraryMap, [lib](LibraryMap::iterator it) {
436 return it.value() == lib;
437 });
438 Q_ASSERT_X(n, "~QLibrary", "Did not find this library in the library map");
439 Q_UNUSED(n);
440 }
441 delete lib;
442}
443
444QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints)
445 : fileName(canonicalFileName), fullVersion(version), pluginState(MightBeAPlugin)
446{
447 loadHintsInt.storeRelaxed(loadHints.toInt());
448 if (canonicalFileName.isEmpty())
449 errorString = QLibrary::tr("The shared library was not found.");
450}
451
453 QLibrary::LoadHints loadHints)
454{
456}
457
458QLibraryPrivate::~QLibraryPrivate()
459{
460}
461
462void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh)
463{
464 // if the library is already loaded, we can't change the load hints
465 if (pHnd.loadRelaxed())
466 return;
467
468 loadHintsInt.fetchAndOrRelaxed(lh.toInt());
469}
470
471QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
472{
473 if (!pHnd.loadRelaxed())
474 return nullptr;
475 return resolve_sys(symbol);
476}
477
478void QLibraryPrivate::setLoadHints(QLibrary::LoadHints lh)
479{
480 // Set the load hints directly for a dummy if this object is not associated
481 // with a file. Such object is not shared between multiple instances.
482 if (fileName.isEmpty()) {
483 loadHintsInt.storeRelaxed(lh.toInt());
484 return;
485 }
486
487 // this locks a global mutex
489 mergeLoadHints(lh);
490}
491
493{
494 // first, check if the instance is cached and hasn't been deleted
495 QObject *obj = [&](){ QMutexLocker locker(&mutex); return inst.data(); }();
496 if (obj)
497 return obj;
498
499 // We need to call the plugin's factory function. Is that cached?
500 // skip increasing the reference count (why? -Thiago)
502 if (!factory)
504
505 if (!factory)
506 return nullptr;
507
508 obj = factory();
509
510 // cache again
511 QMutexLocker locker(&mutex);
512 if (inst)
513 obj = inst;
514 else
515 inst = obj;
516 return obj;
517}
518
520{
521 if (pHnd.loadRelaxed()) {
522 libraryUnloadCount.ref();
523 return true;
524 }
525 if (fileName.isEmpty())
526 return false;
527
528 Q_TRACE(QLibraryPrivate_load_entry, fileName);
529
530 bool ret = load_sys();
531 qCDebug(lcDebugLibrary)
532 << fileName
533 << (ret ? "loaded library" : qUtf8Printable(u"cannot load: " + errorString));
534 if (ret) {
535 //when loading a library we add a reference to it so that the QLibraryPrivate won't get deleted
536 //this allows to unload the library at a later time
537 libraryUnloadCount.ref();
538 libraryRefCount.ref();
540 }
541
542 Q_TRACE(QLibraryPrivate_load_exit, ret);
543
544 return ret;
545}
546
548{
549 if (!pHnd.loadRelaxed())
550 return false;
551 if (libraryUnloadCount.loadRelaxed() > 0 && !libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to
552 QMutexLocker locker(&mutex);
553 delete inst.data();
554 if (flag == NoUnloadSys || unload_sys()) {
555 qCDebug(lcDebugLibrary) << fileName << "unloaded library"
556 << (flag == NoUnloadSys ? "(faked)" : "");
557 // when the library is unloaded, we release the reference on it so that 'this'
558 // can get deleted
559 libraryRefCount.deref();
560 pHnd.storeRelaxed(nullptr);
562 return true;
563 }
564 }
565
566 return false;
567}
568
570{
572}
573
575{
576 if (auto ptr = instanceFactory.loadAcquire()) {
577 libraryUnloadCount.ref();
578 return ptr;
579 }
580 if (pluginState == IsNotAPlugin)
581 return nullptr;
582 if (load()) {
583 auto ptr = reinterpret_cast<QtPluginInstanceFunction>(resolve("qt_plugin_instance"));
584 instanceFactory.storeRelease(ptr); // two threads may store the same value
585 return ptr;
586 }
587 qCDebug(qt_lcDebugPlugins) << "QLibraryPrivate::loadPlugin failed on" << fileName << ":" << errorString;
588 pluginState = IsNotAPlugin;
589 return nullptr;
590}
591
608{
609#if defined(Q_OS_WIN)
610 return fileName.endsWith(".dll"_L1, Qt::CaseInsensitive);
611#else // Generic Unix
612# if defined(Q_OS_DARWIN)
613 // On Apple platforms, dylib look like libmylib.1.0.0.dylib
614 if (fileName.endsWith(".dylib"_L1))
615 return true;
616# endif
617 QString completeSuffix = QFileInfo(fileName).completeSuffix();
618 if (completeSuffix.isEmpty())
619 return false;
620
621 // if this throws an empty-array error, you need to fix the #ifdef's:
622 const QLatin1StringView candidates[] = {
623# if defined(Q_OS_HPUX)
624/*
625 See "HP-UX Linker and Libraries User's Guide", section "Link-time Differences between PA-RISC and IPF":
626 "In PA-RISC (PA-32 and PA-64) shared libraries are suffixed with .sl. In IPF (32-bit and 64-bit),
627 the shared libraries are suffixed with .so. For compatibility, the IPF linker also supports the .sl suffix."
628*/
629 "sl"_L1,
630# if defined __ia64
631 "so"_L1,
632# endif
633# elif defined(Q_OS_AIX)
634 "a"_L1,
635 "so"_L1,
636# elif defined(Q_OS_DARWIN)
637 "so"_L1,
638 "bundle"_L1,
639# elif defined(Q_OS_UNIX)
640 "so"_L1,
641# endif
642 }; // candidates
643
644 auto isValidSuffix = [&candidates](QStringView s) {
645 return std::find(std::begin(candidates), std::end(candidates), s) != std::end(candidates);
646 };
647
648 // Examples of valid library names:
649 // libfoo.so
650 // libfoo.so.0
651 // libfoo.so.0.3
652 // libfoo-0.3.so
653 // libfoo-0.3.so.0.3.0
654
655 auto suffixes = qTokenize(completeSuffix, u'.');
656 auto it = suffixes.begin();
657 const auto end = suffixes.end();
658
659 auto isNumeric = [](QStringView s) { bool ok; (void)s.toInt(&ok); return ok; };
660
661 while (it != end) {
662 if (isValidSuffix(*it++))
663 return q20::ranges::all_of(it, end, isNumeric);
664 }
665 return false; // no valid suffix found
666#endif
667}
668
670{
671 auto error = [=](QString &&explanation) {
672 *errMsg = QLibrary::tr("'%1' is not a Qt plugin (%2)").arg(priv->fileName, std::move(explanation));
673 return false;
674 };
675
676 QPluginMetaData metaData;
677 QFunctionPointer pfn = priv->resolve("qt_plugin_query_metadata_v2");
678 if (pfn) {
679 metaData = reinterpret_cast<QPluginMetaData (*)()>(pfn)();
680#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
681 } else if ((pfn = priv->resolve("qt_plugin_query_metadata"))) {
682 metaData = reinterpret_cast<QPluginMetaData (*)()>(pfn)();
683 if (metaData.size < sizeof(QPluginMetaData::MagicHeader))
684 return error(QLibrary::tr("metadata too small"));
685
686 // adjust the meta data to point to the header
687 auto data = reinterpret_cast<const char *>(metaData.data);
689 metaData.data = data;
690 metaData.size -= sizeof(QPluginMetaData::MagicString);
691#endif
692 } else {
693 return error(QLibrary::tr("entrypoint to query the plugin meta data not found"));
694 }
695
696 if (metaData.size < sizeof(QPluginMetaData::Header))
697 return error(QLibrary::tr("metadata too small"));
698
699 if (priv->metaData.parse(metaData))
700 return true;
701 *errMsg = priv->metaData.errorString();
702 return false;
703}
704
706{
707 if (pluginState == MightBeAPlugin)
709
710 return pluginState == IsAPlugin;
711}
712
714{
715 QMutexLocker locker(&mutex);
717 if (pluginState != MightBeAPlugin)
718 return;
719
720 bool success = false;
721
722#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
723 if (fileName.endsWith(".debug"_L1)) {
724 // refuse to load a file that ends in .debug
725 // these are the debug symbols from the libraries
726 // the problem is that they are valid shared library files
727 // and dlopen is known to crash while opening them
728
729 // pretend we didn't see the file
730 errorString = QLibrary::tr("The shared library was not found.");
731 pluginState = IsNotAPlugin;
732 return;
733 }
734#endif
735
736 if (!pHnd.loadRelaxed()) {
737 // scan for the plugin metadata without loading
739#if defined(Q_OF_MACH_O)
740 if (result.length && result.isEncrypted) {
741 // We found the .qtmetadata section, but since the library is encrypted
742 // we need to dlopen() it before we can parse the metadata for further
743 // validation.
744 qCDebug(qt_lcDebugPlugins, "Library is encrypted. Doing prospective load before parsing metadata");
745 locker.unlock();
746 load();
747 locker.relock();
748 success = qt_get_metadata(this, &errorString);
749 } else
750#endif
751 {
752 success = result.length != 0;
753 }
754 } else {
755 // library is already loaded (probably via QLibrary)
756 // simply get the target function and call it.
757 success = qt_get_metadata(this, &errorString);
758 }
759
760 if (!success) {
761 if (errorString.isEmpty()) {
762 if (fileName.isEmpty())
763 errorString = QLibrary::tr("The shared library was not found.");
764 else
765 errorString = QLibrary::tr("The file '%1' is not a valid Qt plugin.").arg(fileName);
766 }
767 pluginState = IsNotAPlugin;
768 return;
769 }
770
771 pluginState = IsNotAPlugin; // be pessimistic
772
775 if ((qt_version & 0x00ff00) > (QT_VERSION & 0x00ff00) || (qt_version & 0xff0000) != (QT_VERSION & 0xff0000)) {
776 qCDebug(qt_lcDebugPlugins, "In %s:\n"
777 " Plugin uses incompatible Qt library (%d.%d.%d) [%s]",
778 QFile::encodeName(fileName).constData(),
779 (qt_version&0xff0000) >> 16, (qt_version&0xff00) >> 8, qt_version&0xff,
780 debug ? "debug" : "release");
781 errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5]")
782 .arg(fileName,
783 QString::number((qt_version & 0xff0000) >> 16),
784 QString::number((qt_version & 0xff00) >> 8),
785 QString::number(qt_version & 0xff),
786 debug ? "debug"_L1 : "release"_L1);
788 //don't issue a qWarning since we will hopefully find a non-debug? --Sam
789 errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library."
790 " (Cannot mix debug and release libraries.)").arg(fileName);
791 } else {
792 pluginState = IsAPlugin;
793 }
794}
795
807{
808 if (!d)
809 return false;
810 if (d.tag() == Loaded)
811 return d->pHnd.loadRelaxed();
812 if (d->load()) {
813 d.setTag(Loaded);
814 return true;
815 }
816 return false;
817}
818
835{
836 if (d.tag() == Loaded) {
837 d.setTag(NotLoaded);
838 return d->unload();
839 }
840 return false;
841}
842
853{
854 return d.tag() == Loaded;
855}
856
857
862{
863}
864
865
876{
878}
879
891{
893}
894
906 : QObject(parent)
907{
909}
910
920{
921 if (d)
922 d->release();
923}
924
947{
949}
950
952{
953 if (d) {
954 QMutexLocker locker(&d->mutex);
956 }
957 return QString();
958}
959
970{
971 setFileNameAndVersion(fileName, verNum >= 0 ? QString::number(verNum) : QString());
972}
973
984{
985 QLibrary::LoadHints lh;
986 if (d) {
987 lh = d->loadHints();
988 d->release();
989 }
991 d = QTaggedPointer(dd, NotLoaded); // we haven't load()ed
992}
993
1014QFunctionPointer QLibrary::resolve(const char *symbol)
1015{
1016 if (!isLoaded() && !load())
1017 return nullptr;
1018 return d->resolve(symbol);
1019}
1020
1034QFunctionPointer QLibrary::resolve(const QString &fileName, const char *symbol)
1035{
1036 QLibrary library(fileName);
1037 return library.resolve(symbol);
1038}
1039
1054QFunctionPointer QLibrary::resolve(const QString &fileName, int verNum, const char *symbol)
1055{
1056 QLibrary library(fileName, verNum);
1057 return library.resolve(symbol);
1058}
1059
1075QFunctionPointer QLibrary::resolve(const QString &fileName, const QString &version, const char *symbol)
1076{
1077 QLibrary library(fileName, version);
1078 return library.resolve(symbol);
1079}
1080
1088{
1089 QString str;
1090 if (d) {
1091 QMutexLocker locker(&d->mutex);
1092 str = d->errorString;
1093 }
1094 return str.isEmpty() ? tr("Unknown error") : str;
1095}
1096
1136void QLibrary::setLoadHints(LoadHints hints)
1137{
1138 if (!d) {
1139 d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr
1140 d->errorString.clear();
1141 }
1142 d->setLoadHints(hints);
1143}
1144
1145QLibrary::LoadHints QLibrary::loadHints() const
1146{
1147 return d ? d->loadHints() : QLibrary::LoadHints();
1148}
1149
1150/* Internal, for debugging */
1152{
1153 static int debug_env = QT_PREPEND_NAMESPACE(qEnvironmentVariableIntValue)("QT_DEBUG_PLUGINS");
1154 return debug_env != 0;
1155}
1156
1158
1159#include "moc_qlibrary.cpp"
T fetchAndOrRelaxed(T valueToAdd) noexcept
bool ref() noexcept
bool deref() noexcept
void storeRelaxed(T newValue) noexcept
T loadRelaxed() const noexcept
Type loadAcquire() const noexcept
Type loadRelaxed() const noexcept
void storeRelaxed(Type newValue) noexcept
void storeRelease(Type newValue) noexcept
\inmodule QtCore
Definition qbytearray.h:57
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:122
qint64 toInteger(qint64 defaultValue=0) const
Returns the integer value stored in this QCborValue, if it is of the integer type.
Definition qcborvalue.h:190
bool toBool(bool defaultValue=false) const
Returns the boolean value stored in this QCborValue, if it is of a boolean type.
Definition qcborvalue.h:192
uchar * map(qint64 offset, qint64 size, MemoryMapFlags flags=NoOptions)
Maps size bytes of the file into memory starting at offset.
\inmodule QtCore \reentrant
Definition qfileinfo.h:22
QString completeSuffix() const
Returns the complete suffix (extension) of the file.
\inmodule QtCore
Definition qfile.h:93
bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:881
static QByteArray encodeName(const QString &fileName)
Converts fileName to an 8-bit encoding that you can use in native APIs.
Definition qfile.h:158
qint64 size() const override
\reimp
Definition qfile.cpp:1156
QString errorString() const
Returns a human-readable description of the last device error that occurred.
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
\inmodule QtCore\reentrant
QByteArray toJson(JsonFormat format=Indented) const
QString errorString
Definition qlibrary_p.h:83
bool unload(UnloadFlag flag=UnloadSys)
Definition qlibrary.cpp:547
QString qualifiedFileName
Definition qlibrary_p.h:84
QtPluginInstanceFunction loadPlugin()
Definition qlibrary.cpp:574
QAtomicPointer< std::remove_pointer< Handle >::type > pHnd
Definition qlibrary_p.h:77
void setLoadHints(QLibrary::LoadHints lh)
Definition qlibrary.cpp:478
const QString fileName
Definition qlibrary_p.h:57
void updatePluginState()
Definition qlibrary.cpp:713
QAtomicPointer< std::remove_pointer< QtPluginInstanceFunction >::type > instanceFactory
Definition qlibrary_p.h:76
QPluginParsedMetaData metaData
Definition qlibrary_p.h:82
QFunctionPointer resolve(const char *)
Definition qlibrary.cpp:471
QPointer< QObject > inst
Definition qlibrary_p.h:81
QObject * pluginInstance()
Definition qlibrary.cpp:492
static QLibraryPrivate * findOrCreate(const QString &fileName, const QString &version=QString(), QLibrary::LoadHints loadHints={ })
Definition qlibrary.cpp:452
QLibrary::LoadHints loadHints() const
Definition qlibrary_p.h:66
static void cleanup()
Definition qlibrary.cpp:337
static void releaseLibrary(QLibraryPrivate *lib)
Definition qlibrary.cpp:421
static QLibraryPrivate * findOrCreate(const QString &fileName, const QString &version, QLibrary::LoadHints loadHints)
Definition qlibrary.cpp:395
\inmodule QtCore \reentrant
Definition qlibrary.h:17
bool load()
Loads the library and returns true if the library was loaded successfully; otherwise returns false.
Definition qlibrary.cpp:806
LoadHints loadHints
Give the load() function some hints on how it should behave.
Definition qlibrary.h:20
QString fileName
the file name of the library
Definition qlibrary.h:19
static bool isLibrary(const QString &fileName)
Returns true if fileName has a valid suffix for a loadable library; otherwise returns false.
Definition qlibrary.cpp:607
void setFileNameAndVersion(const QString &fileName, int verNum)
Sets the fileName property and major version number to fileName and versionNumber respectively.
Definition qlibrary.cpp:969
void setFileName(const QString &fileName)
Definition qlibrary.cpp:946
bool isLoaded() const
Returns true if load() succeeded; otherwise returns false.
Definition qlibrary.cpp:852
bool unload()
Unloads the library and returns true if the library could be unloaded; otherwise returns false.
Definition qlibrary.cpp:834
void setLoadHints(LoadHints hints)
QLibrary(QObject *parent=nullptr)
Constructs a library with the given parent.
Definition qlibrary.cpp:861
QFunctionPointer resolve(const char *symbol)
Returns the address of the exported symbol symbol.
~QLibrary()
Destroys the QLibrary object.
Definition qlibrary.cpp:919
QString errorString() const
Definition qmap.h:186
\inmodule QtCore
Definition qmutex.h:317
void unlock() noexcept
Unlocks this mutex locker.
Definition qmutex.h:323
void relock() noexcept
Relocks an unlocked mutex locker.
Definition qmutex.h:324
\inmodule QtCore
Definition qmutex.h:285
\inmodule QtCore
Definition qobject.h:90
static constexpr OSType currentType()
Returns the current OS type without constructing a QOperatingSystemVersion instance.
QCborValue value(QtPluginMetaDataKeys k) const
bool parse(QByteArrayView input)
QJsonObject toJson() const
QString errorString() const
T * data() const
Definition qpointer.h:56
iterator begin()
Definition qset.h:136
iterator end()
Definition qset.h:140
\inmodule QtCore
Definition qstringview.h:76
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1107
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
Definition qstring.cpp:8606
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition qstring.cpp:5350
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
QByteArray toLocal8Bit() const &
Definition qstring.h:567
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:7822
void setTag(Tag tag)
Tag tag() const noexcept
QString str
[2]
QSet< QString >::iterator it
Combined button and popup list for selecting options.
@ CaseInsensitive
constexpr struct q20::ranges::@5 all_of
qsizetype erase_if(QByteArray &ba, Predicate pred)
Definition qbytearray.h:701
constexpr QStaticByteArrayMatcher< N > qMakeStaticByteArrayMatcher(const char(&pattern)[N]) noexcept
#define Q_UNLIKELY(x)
#define Q_LIKELY(x)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError * error
static void installCoverageTool(QLibraryPrivate *libPrivate)
Definition qlibrary.cpp:279
static Q_CONSTINIT bool qt_library_data_once
Definition qlibrary.cpp:330
bool qt_debug_component()
qsizetype QString * errMsg
Definition qlibrary.cpp:165
static constexpr bool QtBuildIsDebug
Definition qlibrary.cpp:53
static bool qt_get_metadata(QLibraryPrivate *priv, QString *errMsg)
Definition qlibrary.cpp:669
qsizetype i
Definition qlibrary.cpp:194
static Q_CONSTINIT QLibraryStore * qt_library_data
Definition qlibrary.cpp:329
static QLibraryScanResult findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
Definition qlibrary.cpp:213
static Q_CONSTINIT QBasicMutex qt_library_mutex
Definition qlibrary.cpp:328
qsizetype s_len
Definition qlibrary.cpp:164
static constexpr bool PluginMustMatchQtDebug
Definition qlibrary.cpp:43
static void qlibraryCleanup()
Definition qlibrary.cpp:378
#define qDebug
[1]
Definition qlogging.h:160
#define qWarning
Definition qlogging.h:162
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_LOGGING_CATEGORY_WITH_ENV_OVERRIDE(name, env, categoryName)
return ret
static ControlElement< T > * ptr(QWidget *widget)
static const QMetaObjectPrivate * priv(const uint *data)
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
GLboolean r
[2]
GLuint GLuint end
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat n
GLhandleARB obj
[2]
GLuint64EXT * result
[6]
GLdouble s
[6]
Definition qopenglext.h:235
GLubyte * pattern
QObject *(* QtPluginInstanceFunction)()
Definition qplugin.h:36
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
#define qUtf8Printable(string)
Definition qstring.h:1395
#define qUtf16Printable(string)
Definition qstring.h:1403
constexpr auto qTokenize(Haystack &&h, Needle &&n, Flags...flags) noexcept(QtPrivate::Tok::is_nothrow_constructible_from< Haystack, Needle >::value) -> decltype(QtPrivate::Tok::TokenizerResult< Haystack, Needle >{std::forward< Haystack >(h), std::forward< Needle >(n), flags...})
#define QT_CONFIG(feature)
#define tr(X)
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
#define Q_UNUSED(x)
#define Q_TRACE(x,...)
Definition qtrace_p.h:144
#define Q_TRACE_POINT(provider, tracepoint,...)
Definition qtrace_p.h:232
static const uchar magic[MagicLength]
#define QT_VERSION
ptrdiff_t qsizetype
Definition qtypes.h:70
unsigned int uint
Definition qtypes.h:29
long long qint64
Definition qtypes.h:55
#define Q_INT64_C(c)
Definition qtypes.h:52
QT_END_NAMESPACE typedef QT_PREPEND_NAMESPACE(quintptr) WId
QFile file
[0]
static const auto matcher
[0]
QReadWriteLock lock
[0]
QItemEditorFactory * factory
const void * data
Definition qplugin.h:103
static constexpr char MagicString[]
Definition qplugin.h:40
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent