Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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 <qmutex.h>
16#include <qstringlist.h>
17
18#ifdef Q_OS_DARWIN
19# include <private/qcore_mac_p.h>
20#endif
21#include <private/qcoreapplication_p.h>
22#include <private/qloggingregistry_p.h>
23#include <private/qsystemerror_p.h>
24
25#include "qcoffpeparser_p.h"
26#include "qelfparser_p.h"
27#include "qfactoryloader_p.h"
28#include "qmachparser_p.h"
29
30#include <qtcore_tracepoints_p.h>
31
32#include <QtCore/q20map.h>
33
35
36using namespace Qt::StringLiterals;
37
38Q_TRACE_POINT(qtcore, QLibraryPrivate_load_entry, const QString &fileName);
39Q_TRACE_POINT(qtcore, QLibraryPrivate_load_exit, bool success);
40
41// On Unix systema and on Windows with MinGW, we can mix and match debug and
42// release plugins without problems. (unless compiled in debug-and-release mode
43// - why?)
44static constexpr bool PluginMustMatchQtDebug =
46#if defined(Q_CC_MINGW)
47 && QT_CONFIG(debug_and_release)
48#endif
49 ;
50
51#ifdef QT_NO_DEBUG
52static constexpr bool QtBuildIsDebug = false;
53#else
54static constexpr bool QtBuildIsDebug = true;
55#endif
56
57Q_LOGGING_CATEGORY_WITH_ENV_OVERRIDE(qt_lcDebugPlugins, "QT_DEBUG_PLUGINS", "qt.core.plugin.loader")
58static Q_LOGGING_CATEGORY_WITH_ENV_OVERRIDE(lcDebugLibrary, "QT_DEBUG_PLUGINS", "qt.core.library")
59
165static QLibraryScanResult qt_find_pattern(const char *s, qsizetype s_len, QString *errMsg)
166{
167 /*
168 We used to search from the end of the file so we'd skip the code and find
169 the read-only data that usually follows. Unfortunately, in debug builds,
170 the debug sections come after and are usually much bigger than everything
171 else, making this process slower than necessary with debug plugins.
172
173 More importantly, the pattern string may exist in the debug information due
174 to it being used in the plugin in the first place.
175 */
176#if defined(Q_OF_ELF)
177 return QElfParser::parse({s, s_len}, errMsg);
178#elif defined(Q_OF_MACH_O)
179 return QMachOParser::parse(s, s_len, errMsg);
180#elif defined(Q_OS_WIN)
181 return QCoffPeParser::parse({s, s_len}, errMsg);
182#else
183# warning "Qt does not know how to efficiently parse your platform's binary format; using slow fall-back."
184#endif
185 static constexpr auto matcher = [] {
186 // QPluginMetaData::MagicString is not NUL-terminated, but
187 // qMakeStaticByteArrayMatcher requires its argument to be, so
188 // duplicate here, but statically check we didn't mess up:
189 constexpr auto &pattern = "QTMETADATA !";
190 constexpr auto magic = std::string_view(QPluginMetaData::MagicString,
192 static_assert(pattern == magic);
194 }();
195 qsizetype i = matcher.indexIn({s, s_len});
196 if (i < 0) {
197 *errMsg = QLibrary::tr("'%1' is not a Qt plugin").arg(*errMsg);
198 return QLibraryScanResult{};
199 }
201 return { i, s_len - i };
202}
203
204/*
205 This opens the specified library, mmaps it into memory, and searches
206 for the QT_PLUGIN_VERIFICATION_DATA. The advantage of this approach is that
207 we can get the verification data without have to actually load the library.
208 This lets us detect mismatches more safely.
209
210 Returns \c false if version information is not present, or if the
211 information could not be read.
212 Returns true if version information is present and successfully read.
213*/
215{
216 QFile file(library);
218 if (lib)
220 qCWarning(qt_lcDebugPlugins, "%ls: cannot open: %ls", qUtf16Printable(library),
222 return {};
223 }
224
225 // Files can be bigger than the virtual memory size on 32-bit systems, so
226 // we limit to 512 MB there. For 64-bit, we allow up to 2^40 bytes.
227 constexpr qint64 MaxMemoryMapSize =
228 Q_INT64_C(1) << (sizeof(qsizetype) > 4 ? 40 : 29);
229
230 qsizetype fdlen = qMin(file.size(), MaxMemoryMapSize);
231 const char *filedata = reinterpret_cast<char *>(file.map(0, fdlen));
232
233#ifdef Q_OS_UNIX
234 if (filedata == nullptr) {
235 // If we can't mmap(), then the dynamic loader won't be able to either.
236 // This can't be used as a plugin.
237 qCWarning(qt_lcDebugPlugins, "%ls: failed to map to memory: %ls",
239 return {};
240 }
241#else
243 if (filedata == nullptr) {
244 // It's unknown at this point whether Windows supports LoadLibrary() on
245 // files that fail to CreateFileMapping / MapViewOfFile, so we err on
246 // the side of doing a regular read into memory (up to 64 MB).
247 data = file.read(64 * 1024 * 1024);
248 filedata = data.constData();
249 fdlen = data.size();
250 }
251#endif
252
253 QString errMsg = library;
254 QLibraryScanResult r = qt_find_pattern(filedata, fdlen, &errMsg);
255 if (r.length) {
256#if defined(Q_OF_MACH_O)
257 if (r.isEncrypted)
258 return r;
259#endif
260 if (!lib->metaData.parse(QByteArrayView(filedata + r.pos, r.length))) {
261 errMsg = lib->metaData.errorString();
262 qCDebug(qt_lcDebugPlugins, "Found invalid metadata in lib %ls: %ls",
264 } else {
265 qCDebug(qt_lcDebugPlugins, "Found metadata in lib %ls, metadata=\n%s\n",
266 qUtf16Printable(library),
268 return r;
269 }
270 } else {
271 qCDebug(qt_lcDebugPlugins, "Failed to find metadata in lib %ls: %ls",
273 }
274
275 lib->errorString = QLibrary::tr("Failed to extract plugin meta data from '%1': %2")
276 .arg(library, errMsg);
277 return {};
278}
279
280static void installCoverageTool(QLibraryPrivate *libPrivate)
281{
282#ifdef __COVERAGESCANNER__
283 /*
284 __COVERAGESCANNER__ is defined when Qt has been instrumented for code
285 coverage by TestCocoon. CoverageScanner is the name of the tool that
286 generates the code instrumentation.
287 This code is required here when code coverage analysis with TestCocoon
288 is enabled in order to allow the loading application to register the plugin
289 and then store its execution report. The execution report gathers information
290 about each part of the plugin's code that has been used when
291 the plugin was loaded by the launching application.
292 The execution report for the plugin will go to the same execution report
293 as the one defined for the application loading it.
294 */
295
296 int ret = __coveragescanner_register_library(libPrivate->fileName.toLocal8Bit());
297
298 if (ret >= 0) {
299 qDebug("coverage data for %ls registered",
300 qUtf16Printable(libPrivate->fileName));
301 } else {
302 qWarning("could not register %ls: error %d; coverage data may be incomplete",
303 qUtf16Printable(libPrivate->fileName),
304 ret);
305 }
306 }
307#else
308 Q_UNUSED(libPrivate);
309#endif
310}
311
313{
314public:
315 inline ~QLibraryStore();
316 static inline QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version, QLibrary::LoadHints loadHints);
317 static inline void releaseLibrary(QLibraryPrivate *lib);
318
319 static inline void cleanup();
320
321private:
322 static inline QLibraryStore *instance();
323
324 // all members and instance() are protected by qt_library_mutex
325 typedef std::map<QString, QLibraryPrivate *> LibraryMap;
326 LibraryMap libraryMap;
327};
328
329Q_CONSTINIT static QBasicMutex qt_library_mutex;
330Q_CONSTINIT static QLibraryStore *qt_library_data = nullptr;
331Q_CONSTINIT static bool qt_library_data_once;
332
337
339{
341 if (!data)
342 return;
343
344 // find any libraries that are still loaded but have a no one attached to them
345 for (auto &[_, lib] : data->libraryMap) {
346 if (lib->libraryRefCount.loadRelaxed() == 1) {
347 if (lib->libraryUnloadCount.loadRelaxed() > 0) {
348 Q_ASSERT(lib->pHnd.loadRelaxed());
349 lib->libraryUnloadCount.storeRelaxed(1);
350#if defined(Q_OS_DARWIN)
351 // We cannot fully unload libraries, as we don't know if there are
352 // lingering references (in system threads e.g.) to Objective-C classes
353 // defined in the library.
354 lib->unload(QLibraryPrivate::NoUnloadSys);
355#else
356 lib->unload();
357#endif
358 }
359 delete std::exchange(lib, nullptr);
360 }
361 }
362
363 // dump all objects that remain
364 if (lcDebugLibrary().isDebugEnabled()) {
365 for (auto &[_, lib] : data->libraryMap) {
366 if (lib)
367 qDebug(lcDebugLibrary)
368 << "On QtCore unload," << lib->fileName << "was leaked, with"
369 << lib->libraryRefCount.loadRelaxed() << "users";
370 }
371 }
372
373 delete data;
374}
375
376static void qlibraryCleanup()
377{
379}
380Q_DESTRUCTOR_FUNCTION(qlibraryCleanup)
381
382// must be called with a locked mutex
383QLibraryStore *QLibraryStore::instance()
384{
386 // only create once per process lifetime
389 }
390 return qt_library_data;
391}
392
394 QLibrary::LoadHints loadHints)
395{
396 auto lazyNewLib = [&] {
397 auto result = new QLibraryPrivate(fileName, version, loadHints);
398 result->libraryRefCount.ref();
399 return result;
400 };
401
402 if (fileName.isEmpty()) // request for empty d-pointer in QLibrary::setLoadHints();
403 return lazyNewLib(); // must return an independent (new) object
404
406 QLibraryStore *data = instance();
407
408 if (Q_UNLIKELY(!data)) {
409 locker.unlock();
410 return lazyNewLib();
411 }
412
413 QString mapName = version.isEmpty() ? fileName : fileName + u'\0' + version;
414
415 QLibraryPrivate *&lib = data->libraryMap[std::move(mapName)];
416 if (lib) {
417 // already loaded
418 lib->libraryRefCount.ref();
419 lib->mergeLoadHints(loadHints);
420 } else {
421 lib = lazyNewLib();
422 }
423
424 return lib;
425}
426
428{
430 QLibraryStore *data = instance();
431
432 if (lib->libraryRefCount.deref()) {
433 // still in use
434 return;
435 }
436
437 // no one else is using
438 Q_ASSERT(lib->libraryUnloadCount.loadRelaxed() == 0);
439
440 if (Q_LIKELY(data) && !lib->fileName.isEmpty()) {
441 using q20::erase_if;
442 const auto n = erase_if(data->libraryMap, [lib](const auto &e) {
443 return e.second == lib;
444 });
445 Q_ASSERT_X(n, "~QLibrary", "Did not find this library in the library map");
446 Q_UNUSED(n);
447 }
448 delete lib;
449}
450
451QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints)
452 : fileName(canonicalFileName), fullVersion(version), pluginState(MightBeAPlugin)
453{
454 loadHintsInt.storeRelaxed(loadHints.toInt());
455 if (canonicalFileName.isEmpty())
456 errorString = QLibrary::tr("The shared library was not found.");
457}
458
460 QLibrary::LoadHints loadHints)
461{
463}
464
465QLibraryPrivate::~QLibraryPrivate()
466{
467}
468
469void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh)
470{
471 // if the library is already loaded, we can't change the load hints
472 if (pHnd.loadRelaxed())
473 return;
474
475 loadHintsInt.fetchAndOrRelaxed(lh.toInt());
476}
477
478QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
479{
480 if (!pHnd.loadRelaxed())
481 return nullptr;
482 return resolve_sys(symbol);
483}
484
485void QLibraryPrivate::setLoadHints(QLibrary::LoadHints lh)
486{
487 // Set the load hints directly for a dummy if this object is not associated
488 // with a file. Such object is not shared between multiple instances.
489 if (fileName.isEmpty()) {
490 loadHintsInt.storeRelaxed(lh.toInt());
491 return;
492 }
493
494 // this locks a global mutex
496 mergeLoadHints(lh);
497}
498
500{
501 // first, check if the instance is cached and hasn't been deleted
502 QObject *obj = [&](){ QMutexLocker locker(&mutex); return inst.data(); }();
503 if (obj)
504 return obj;
505
506 // We need to call the plugin's factory function. Is that cached?
507 // skip increasing the reference count (why? -Thiago)
509 if (!factory)
511
512 if (!factory)
513 return nullptr;
514
515 obj = factory();
516
517 // cache again
518 QMutexLocker locker(&mutex);
519 if (inst)
520 obj = inst;
521 else
522 inst = obj;
523 return obj;
524}
525
527{
528 if (pHnd.loadRelaxed()) {
529 libraryUnloadCount.ref();
530 return true;
531 }
532 if (fileName.isEmpty())
533 return false;
534
535 Q_TRACE(QLibraryPrivate_load_entry, fileName);
536
537 bool ret = load_sys();
538 qCDebug(lcDebugLibrary)
539 << fileName
540 << (ret ? "loaded library" : qUtf8Printable(u"cannot load: " + errorString));
541 if (ret) {
542 //when loading a library we add a reference to it so that the QLibraryPrivate won't get deleted
543 //this allows to unload the library at a later time
544 libraryUnloadCount.ref();
545 libraryRefCount.ref();
547 }
548
549 Q_TRACE(QLibraryPrivate_load_exit, ret);
550
551 return ret;
552}
553
555{
556 if (!pHnd.loadRelaxed())
557 return false;
558 if (libraryUnloadCount.loadRelaxed() > 0 && !libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to
559 QMutexLocker locker(&mutex);
560 delete inst.data();
561 if (flag == NoUnloadSys || unload_sys()) {
562 qCDebug(lcDebugLibrary) << fileName << "unloaded library"
563 << (flag == NoUnloadSys ? "(faked)" : "");
564 // when the library is unloaded, we release the reference on it so that 'this'
565 // can get deleted
566 libraryRefCount.deref();
567 pHnd.storeRelaxed(nullptr);
569 return true;
570 }
571 }
572
573 return false;
574}
575
580
582{
583 if (auto ptr = instanceFactory.loadAcquire()) {
584 libraryUnloadCount.ref();
585 return ptr;
586 }
587 if (pluginState == IsNotAPlugin)
588 return nullptr;
589 if (load()) {
590 auto ptr = reinterpret_cast<QtPluginInstanceFunction>(resolve("qt_plugin_instance"));
591 instanceFactory.storeRelease(ptr); // two threads may store the same value
592 return ptr;
593 }
594 qCDebug(qt_lcDebugPlugins) << "QLibraryPrivate::loadPlugin failed on" << fileName << ":" << errorString;
595 pluginState = IsNotAPlugin;
596 return nullptr;
597}
598
615{
616#if defined(Q_OS_WIN)
617 return fileName.endsWith(".dll"_L1, Qt::CaseInsensitive);
618#else // Generic Unix
619# if defined(Q_OS_DARWIN)
620 // On Apple platforms, dylib look like libmylib.1.0.0.dylib
621 if (fileName.endsWith(".dylib"_L1))
622 return true;
623# endif
624 QString completeSuffix = QFileInfo(fileName).completeSuffix();
625 if (completeSuffix.isEmpty())
626 return false;
627
628 // if this throws an empty-array error, you need to fix the #ifdef's:
629 const QLatin1StringView candidates[] = {
630# if defined(Q_OS_HPUX)
631/*
632 See "HP-UX Linker and Libraries User's Guide", section "Link-time Differences between PA-RISC and IPF":
633 "In PA-RISC (PA-32 and PA-64) shared libraries are suffixed with .sl. In IPF (32-bit and 64-bit),
634 the shared libraries are suffixed with .so. For compatibility, the IPF linker also supports the .sl suffix."
635*/
636 "sl"_L1,
637# if defined __ia64
638 "so"_L1,
639# endif
640# elif defined(Q_OS_AIX)
641 "a"_L1,
642 "so"_L1,
643# elif defined(Q_OS_DARWIN)
644 "so"_L1,
645 "bundle"_L1,
646# elif defined(Q_OS_UNIX)
647 "so"_L1,
648# endif
649 }; // candidates
650
651 auto isValidSuffix = [&candidates](QStringView s) {
652 return std::find(std::begin(candidates), std::end(candidates), s) != std::end(candidates);
653 };
654
655 // Examples of valid library names:
656 // libfoo.so
657 // libfoo.so.0
658 // libfoo.so.0.3
659 // libfoo-0.3.so
660 // libfoo-0.3.so.0.3.0
661
662 auto suffixes = qTokenize(completeSuffix, u'.');
663 auto it = suffixes.begin();
664 const auto end = suffixes.end();
665
666 auto isNumeric = [](QStringView s) { bool ok; (void)s.toInt(&ok); return ok; };
667
668 while (it != end) {
669 if (isValidSuffix(*it++))
670 return q20::ranges::all_of(it, end, isNumeric);
671 }
672 return false; // no valid suffix found
673#endif
674}
675
677{
678 auto error = [=](QString &&explanation) {
679 *errMsg = QLibrary::tr("'%1' is not a Qt plugin (%2)").arg(priv->fileName, std::move(explanation));
680 return false;
681 };
682
683 QPluginMetaData metaData;
684 QFunctionPointer pfn = priv->resolve("qt_plugin_query_metadata_v2");
685 if (pfn) {
686 metaData = reinterpret_cast<QPluginMetaData (*)()>(pfn)();
687#if QT_VERSION <= QT_VERSION_CHECK(7, 0, 0)
688 } else if ((pfn = priv->resolve("qt_plugin_query_metadata"))) {
689 metaData = reinterpret_cast<QPluginMetaData (*)()>(pfn)();
690 if (metaData.size < sizeof(QPluginMetaData::MagicHeader))
691 return error(QLibrary::tr("metadata too small"));
692
693 // adjust the meta data to point to the header
694 auto data = reinterpret_cast<const char *>(metaData.data);
696 metaData.data = data;
697 metaData.size -= sizeof(QPluginMetaData::MagicString);
698#endif
699 } else {
700 return error(QLibrary::tr("entrypoint to query the plugin meta data not found"));
701 }
702
703 if (metaData.size < sizeof(QPluginMetaData::Header))
704 return error(QLibrary::tr("metadata too small"));
705
706 if (priv->metaData.parse(metaData))
707 return true;
708 *errMsg = priv->metaData.errorString();
709 return false;
710}
711
713{
714 if (pluginState == MightBeAPlugin)
716
717 return pluginState == IsAPlugin;
718}
719
721{
722 QMutexLocker locker(&mutex);
724 if (pluginState != MightBeAPlugin)
725 return;
726
727 bool success = false;
728
729#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
730 if (fileName.endsWith(".debug"_L1)) {
731 // refuse to load a file that ends in .debug
732 // these are the debug symbols from the libraries
733 // the problem is that they are valid shared library files
734 // and dlopen is known to crash while opening them
735
736 // pretend we didn't see the file
737 errorString = QLibrary::tr("The shared library was not found.");
738 pluginState = IsNotAPlugin;
739 return;
740 }
741#endif
742
743 if (!pHnd.loadRelaxed()) {
744 // scan for the plugin metadata without loading
746#if defined(Q_OF_MACH_O)
747 if (result.length && result.isEncrypted) {
748 // We found the .qtmetadata section, but since the library is encrypted
749 // we need to dlopen() it before we can parse the metadata for further
750 // validation.
751 qCDebug(qt_lcDebugPlugins, "Library is encrypted. Doing prospective load before parsing metadata");
752 locker.unlock();
753 load();
754 locker.relock();
755 success = qt_get_metadata(this, &errorString);
756 } else
757#endif
758 {
759 success = result.length != 0;
760 }
761 } else {
762 // library is already loaded (probably via QLibrary)
763 // simply get the target function and call it.
764 success = qt_get_metadata(this, &errorString);
765 }
766
767 if (!success) {
768 if (errorString.isEmpty()) {
769 if (fileName.isEmpty())
770 errorString = QLibrary::tr("The shared library was not found.");
771 else
772 errorString = QLibrary::tr("The file '%1' is not a valid Qt plugin.").arg(fileName);
773 }
774 pluginState = IsNotAPlugin;
775 return;
776 }
777
778 pluginState = IsNotAPlugin; // be pessimistic
779
782 if ((qt_version & 0x00ff00) > (QT_VERSION & 0x00ff00) || (qt_version & 0xff0000) != (QT_VERSION & 0xff0000)) {
783 qCDebug(qt_lcDebugPlugins, "In %s:\n"
784 " Plugin uses incompatible Qt library (%d.%d.%d) [%s]",
785 QFile::encodeName(fileName).constData(),
786 (qt_version&0xff0000) >> 16, (qt_version&0xff00) >> 8, qt_version&0xff,
787 debug ? "debug" : "release");
788 errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5]")
789 .arg(fileName,
790 QString::number((qt_version & 0xff0000) >> 16),
791 QString::number((qt_version & 0xff00) >> 8),
792 QString::number(qt_version & 0xff),
793 debug ? "debug"_L1 : "release"_L1);
795 //don't issue a qWarning since we will hopefully find a non-debug? --Sam
796 errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library."
797 " (Cannot mix debug and release libraries.)").arg(fileName);
798 } else {
799 pluginState = IsAPlugin;
800 }
801}
802
814{
815 if (!d)
816 return false;
817 if (d.tag() == Loaded)
818 return d->pHnd.loadRelaxed();
819 if (d->load()) {
820 d.setTag(Loaded);
821 return true;
822 }
823 return false;
824}
825
844{
845 if (d.tag() == Loaded) {
846 d.setTag(NotLoaded);
847 return d->unload();
848 }
849 return false;
850}
851
862{
863 return d.tag() == Loaded;
864}
865
866
871{
872}
873
874
885{
887}
888
899QLibrary::QLibrary(const QString &fileName, int verNum, QObject *parent) : QObject(parent)
900{
902}
903
914QLibrary::QLibrary(const QString &fileName, const QString &version, QObject *parent)
915 : QObject(parent)
916{
918}
919
929{
930 if (d)
931 d->release();
932}
933
959
961{
962 if (d) {
963 QMutexLocker locker(&d->mutex);
965 }
966 return QString();
967}
968
979{
980 setFileNameAndVersion(fileName, verNum >= 0 ? QString::number(verNum) : QString());
981}
982
993{
994 QLibrary::LoadHints lh;
995 if (d) {
996 lh = d->loadHints();
997 d->release();
998 }
1000 d = QTaggedPointer(dd, NotLoaded); // we haven't load()ed
1001}
1002
1023QFunctionPointer QLibrary::resolve(const char *symbol)
1024{
1025 if (!isLoaded() && !load())
1026 return nullptr;
1027 return d->resolve(symbol);
1028}
1029
1043QFunctionPointer QLibrary::resolve(const QString &fileName, const char *symbol)
1044{
1045 QLibrary library(fileName);
1046 return library.resolve(symbol);
1047}
1048
1063QFunctionPointer QLibrary::resolve(const QString &fileName, int verNum, const char *symbol)
1064{
1065 QLibrary library(fileName, verNum);
1066 return library.resolve(symbol);
1067}
1068
1084QFunctionPointer QLibrary::resolve(const QString &fileName, const QString &version, const char *symbol)
1085{
1086 QLibrary library(fileName, version);
1087 return library.resolve(symbol);
1088}
1089
1097{
1098 QString str;
1099 if (d) {
1100 QMutexLocker locker(&d->mutex);
1101 str = d->errorString;
1102 }
1103 return str.isEmpty() ? tr("Unknown error") : str;
1104}
1105
1145void QLibrary::setLoadHints(LoadHints hints)
1146{
1147 if (!d) {
1148 d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr
1149 d->errorString.clear();
1150 }
1151 d->setLoadHints(hints);
1152}
1153
1154QLibrary::LoadHints QLibrary::loadHints() const
1155{
1156 return d ? d->loadHints() : QLibrary::LoadHints();
1157}
1158
1159/* Internal, for debugging */
1161{
1162 static int debug_env = QT_PREPEND_NAMESPACE(qEnvironmentVariableIntValue)("QT_DEBUG_PLUGINS");
1163 return debug_env != 0;
1164}
1165
1167
1168#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:124
qint64 toInteger(qint64 defaultValue=0) const
Returns the integer value stored in this QCborValue, if it is of the integer type.
Definition qcborvalue.h:187
bool toBool(bool defaultValue=false) const
Returns the boolean value stored in this QCborValue, if it is of a boolean type.
Definition qcborvalue.h:189
uchar * map(qint64 offset, qint64 size, MemoryMapFlags flags=NoOptions)
Maps size bytes of the file into memory starting at offset.
QString completeSuffix() const
Returns the complete suffix (extension) of the file.
\inmodule QtCore
Definition qfile.h:93
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition qfile.cpp:904
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:1179
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:91
bool unload(UnloadFlag flag=UnloadSys)
Definition qlibrary.cpp:554
QString qualifiedFileName
Definition qlibrary_p.h:92
QtPluginInstanceFunction loadPlugin()
Definition qlibrary.cpp:581
QAtomicPointer< std::remove_pointer< Handle >::type > pHnd
Definition qlibrary_p.h:85
void setLoadHints(QLibrary::LoadHints lh)
Definition qlibrary.cpp:485
const QString fileName
Definition qlibrary_p.h:65
void updatePluginState()
Definition qlibrary.cpp:720
QAtomicPointer< std::remove_pointer< QtPluginInstanceFunction >::type > instanceFactory
Definition qlibrary_p.h:84
QPluginParsedMetaData metaData
Definition qlibrary_p.h:90
QFunctionPointer resolve(const char *)
Definition qlibrary.cpp:478
QPointer< QObject > inst
Definition qlibrary_p.h:89
QObject * pluginInstance()
Definition qlibrary.cpp:499
static QLibraryPrivate * findOrCreate(const QString &fileName, const QString &version=QString(), QLibrary::LoadHints loadHints={ })
Definition qlibrary.cpp:459
QLibrary::LoadHints loadHints() const
Definition qlibrary_p.h:74
static void cleanup()
Definition qlibrary.cpp:338
static void releaseLibrary(QLibraryPrivate *lib)
Definition qlibrary.cpp:427
static QLibraryPrivate * findOrCreate(const QString &fileName, const QString &version, QLibrary::LoadHints loadHints)
Definition qlibrary.cpp:393
\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:813
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:614
void setFileNameAndVersion(const QString &fileName, int verNum)
Sets the fileName property and major version number to fileName and versionNumber respectively.
Definition qlibrary.cpp:978
void setFileName(const QString &fileName)
Definition qlibrary.cpp:955
bool isLoaded() const
Returns true if load() succeeded; otherwise returns false.
Definition qlibrary.cpp:861
bool unload()
Unloads the library and returns true if the library could be unloaded; otherwise returns false.
Definition qlibrary.cpp:843
void setLoadHints(LoadHints hints)
QLibrary(QObject *parent=nullptr)
Constructs a library with the given parent.
Definition qlibrary.cpp:870
QFunctionPointer resolve(const char *symbol)
Returns the address of the exported symbol symbol.
~QLibrary()
Destroys the QLibrary object.
Definition qlibrary.cpp:928
QString errorString() const
\inmodule QtCore
Definition qmutex.h:313
void unlock() noexcept
Unlocks this mutex locker.
Definition qmutex.h:319
void relock() noexcept
Relocks an unlocked mutex locker.
Definition qmutex.h:320
\inmodule QtCore
Definition qmutex.h:281
\inmodule QtCore
Definition qobject.h:103
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 noexcept
Definition qpointer.h:73
iterator begin()
Definition qset.h:136
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
void clear()
Clears the contents of the string and makes it null.
Definition qstring.h:1252
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
Definition qstring.cpp:8870
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:5506
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:8084
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
constexpr std::vector< T, std::allocator< T > >::size_type erase_if(std::vector< T, std::allocator< T > > &c, Pred pred)
Definition q20vector.h:55
qsizetype erase_if(QByteArray &ba, Predicate pred)
Definition qbytearray.h:788
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:280
static Q_CONSTINIT bool qt_library_data_once
Definition qlibrary.cpp:331
bool qt_debug_component()
qsizetype QString * errMsg
Definition qlibrary.cpp:166
static constexpr bool QtBuildIsDebug
Definition qlibrary.cpp:54
static bool qt_get_metadata(QLibraryPrivate *priv, QString *errMsg)
Definition qlibrary.cpp:676
qsizetype i
Definition qlibrary.cpp:195
static Q_CONSTINIT QLibraryStore * qt_library_data
Definition qlibrary.cpp:330
static QLibraryScanResult findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
Definition qlibrary.cpp:214
static Q_CONSTINIT QBasicMutex qt_library_mutex
Definition qlibrary.cpp:329
qsizetype s_len
Definition qlibrary.cpp:165
static constexpr bool PluginMustMatchQtDebug
Definition qlibrary.cpp:44
static void qlibraryCleanup()
Definition qlibrary.cpp:376
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
#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]
GLdouble s
[6]
Definition qopenglext.h:235
GLuint64EXT * result
[6]
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:1535
#define qUtf16Printable(string)
Definition qstring.h:1543
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:165
unsigned int uint
Definition qtypes.h:34
long long qint64
Definition qtypes.h:60
#define Q_INT64_C(c)
Definition qtypes.h:57
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