PageRenderTime 55ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/src/qt/qtbase/src/corelib/plugin/qlibrary.cpp

https://gitlab.com/x33n/phantomjs
C++ | 1115 lines | 571 code | 104 blank | 440 comment | 135 complexity | 8e8a966e86c51bd8190d7d04099c0187 MD5 | raw file
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
  4. ** Copyright (C) 2013 Intel Corporation
  5. ** Contact: http://www.qt-project.org/legal
  6. **
  7. ** This file is part of the QtCore module of the Qt Toolkit.
  8. **
  9. ** $QT_BEGIN_LICENSE:LGPL$
  10. ** Commercial License Usage
  11. ** Licensees holding valid commercial Qt licenses may use this file in
  12. ** accordance with the commercial license agreement provided with the
  13. ** Software or, alternatively, in accordance with the terms contained in
  14. ** a written agreement between you and Digia. For licensing terms and
  15. ** conditions see http://qt.digia.com/licensing. For further information
  16. ** use the contact form at http://qt.digia.com/contact-us.
  17. **
  18. ** GNU Lesser General Public License Usage
  19. ** Alternatively, this file may be used under the terms of the GNU Lesser
  20. ** General Public License version 2.1 as published by the Free Software
  21. ** Foundation and appearing in the file LICENSE.LGPL included in the
  22. ** packaging of this file. Please review the following information to
  23. ** ensure the GNU Lesser General Public License version 2.1 requirements
  24. ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
  25. **
  26. ** In addition, as a special exception, Digia gives you certain additional
  27. ** rights. These rights are described in the Digia Qt LGPL Exception
  28. ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
  29. **
  30. ** GNU General Public License Usage
  31. ** Alternatively, this file may be used under the terms of the GNU
  32. ** General Public License version 3.0 as published by the Free Software
  33. ** Foundation and appearing in the file LICENSE.GPL included in the
  34. ** packaging of this file. Please review the following information to
  35. ** ensure the GNU General Public License version 3.0 requirements will be
  36. ** met: http://www.gnu.org/copyleft/gpl.html.
  37. **
  38. **
  39. ** $QT_END_LICENSE$
  40. **
  41. ****************************************************************************/
  42. #include "qplatformdefs.h"
  43. #include "qlibrary.h"
  44. #ifndef QT_NO_LIBRARY
  45. #include "qlibrary_p.h"
  46. #include <qstringlist.h>
  47. #include <qfile.h>
  48. #include <qfileinfo.h>
  49. #include <qmutex.h>
  50. #include <qmap.h>
  51. #include <private/qcoreapplication_p.h>
  52. #ifdef Q_OS_MAC
  53. # include <private/qcore_mac_p.h>
  54. #endif
  55. #ifndef NO_ERRNO_H
  56. #include <errno.h>
  57. #endif // NO_ERROR_H
  58. #include <qdebug.h>
  59. #include <qvector.h>
  60. #include <qdir.h>
  61. #include <qendian.h>
  62. #include <qjsondocument.h>
  63. #include <qjsonvalue.h>
  64. #include "qelfparser_p.h"
  65. #include "qmachparser_p.h"
  66. QT_BEGIN_NAMESPACE
  67. #ifdef QT_NO_DEBUG
  68. # define QLIBRARY_AS_DEBUG false
  69. #else
  70. # define QLIBRARY_AS_DEBUG true
  71. #endif
  72. #if defined(Q_OS_UNIX)
  73. // We don't use separate debug and release libs on UNIX, so we want
  74. // to allow loading plugins, regardless of how they were built.
  75. # define QT_NO_DEBUG_PLUGIN_CHECK
  76. #endif
  77. /*!
  78. \class QLibrary
  79. \inmodule QtCore
  80. \reentrant
  81. \brief The QLibrary class loads shared libraries at runtime.
  82. \ingroup plugins
  83. An instance of a QLibrary object operates on a single shared
  84. object file (which we call a "library", but is also known as a
  85. "DLL"). A QLibrary provides access to the functionality in the
  86. library in a platform independent way. You can either pass a file
  87. name in the constructor, or set it explicitly with setFileName().
  88. When loading the library, QLibrary searches in all the
  89. system-specific library locations (e.g. \c LD_LIBRARY_PATH on
  90. Unix), unless the file name has an absolute path.
  91. If the file name is an absolute path then an attempt is made to
  92. load this path first. If the file cannot be found, QLibrary tries
  93. the name with different platform-specific file prefixes, like
  94. "lib" on Unix and Mac, and suffixes, like ".so" on Unix, ".dylib"
  95. on the Mac, or ".dll" on Windows.
  96. If the file path is not absolute then QLibrary modifies the search
  97. order to try the system-specific prefixes and suffixes first,
  98. followed by the file path specified.
  99. This makes it possible to specify shared libraries that are only
  100. identified by their basename (i.e. without their suffix), so the
  101. same code will work on different operating systems yet still
  102. minimise the number of attempts to find the library.
  103. The most important functions are load() to dynamically load the
  104. library file, isLoaded() to check whether loading was successful,
  105. and resolve() to resolve a symbol in the library. The resolve()
  106. function implicitly tries to load the library if it has not been
  107. loaded yet. Multiple instances of QLibrary can be used to access
  108. the same physical library. Once loaded, libraries remain in memory
  109. until the application terminates. You can attempt to unload a
  110. library using unload(), but if other instances of QLibrary are
  111. using the same library, the call will fail, and unloading will
  112. only happen when every instance has called unload().
  113. A typical use of QLibrary is to resolve an exported symbol in a
  114. library, and to call the C function that this symbol represents.
  115. This is called "explicit linking" in contrast to "implicit
  116. linking", which is done by the link step in the build process when
  117. linking an executable against a library.
  118. The following code snippet loads a library, resolves the symbol
  119. "mysymbol", and calls the function if everything succeeded. If
  120. something goes wrong, e.g. the library file does not exist or the
  121. symbol is not defined, the function pointer will be 0 and won't be
  122. called.
  123. \snippet code/src_corelib_plugin_qlibrary.cpp 0
  124. The symbol must be exported as a C function from the library for
  125. resolve() to work. This means that the function must be wrapped in
  126. an \c{extern "C"} block if the library is compiled with a C++
  127. compiler. On Windows, this also requires the use of a \c dllexport
  128. macro; see resolve() for the details of how this is done. For
  129. convenience, there is a static resolve() function which you can
  130. use if you just want to call a function in a library without
  131. explicitly loading the library first:
  132. \snippet code/src_corelib_plugin_qlibrary.cpp 1
  133. \sa QPluginLoader
  134. */
  135. /*!
  136. \enum QLibrary::LoadHint
  137. This enum describes the possible hints that can be used to change the way
  138. libraries are handled when they are loaded. These values indicate how
  139. symbols are resolved when libraries are loaded, and are specified using
  140. the setLoadHints() function.
  141. \value ResolveAllSymbolsHint
  142. Causes all symbols in a library to be resolved when it is loaded, not
  143. simply when resolve() is called.
  144. \value ExportExternalSymbolsHint
  145. Exports unresolved and external symbols in the library so that they can be
  146. resolved in other dynamically-loaded libraries loaded later.
  147. \value LoadArchiveMemberHint
  148. Allows the file name of the library to specify a particular object file
  149. within an archive file.
  150. If this hint is given, the filename of the library consists of
  151. a path, which is a reference to an archive file, followed by
  152. a reference to the archive member.
  153. \value PreventUnloadHint
  154. Prevents the library from being unloaded from the address space if close()
  155. is called. The library's static variables are not reinitialized if open()
  156. is called at a later time.
  157. \sa loadHints
  158. */
  159. static long qt_find_pattern(const char *s, ulong s_len,
  160. const char *pattern, ulong p_len)
  161. {
  162. /*
  163. we search from the end of the file because on the supported
  164. systems, the read-only data/text segments are placed at the end
  165. of the file. HOWEVER, when building with debugging enabled, all
  166. the debug symbols are placed AFTER the data/text segments.
  167. what does this mean? when building in release mode, the search
  168. is fast because the data we are looking for is at the end of the
  169. file... when building in debug mode, the search is slower
  170. because we have to skip over all the debugging symbols first
  171. */
  172. if (! s || ! pattern || p_len > s_len) return -1;
  173. ulong i, hs = 0, hp = 0, delta = s_len - p_len;
  174. for (i = 0; i < p_len; ++i) {
  175. hs += s[delta + i];
  176. hp += pattern[i];
  177. }
  178. i = delta;
  179. for (;;) {
  180. if (hs == hp && qstrncmp(s + i, pattern, p_len) == 0)
  181. return i;
  182. if (i == 0)
  183. break;
  184. --i;
  185. hs -= s[i + p_len];
  186. hs += s[i];
  187. }
  188. return -1;
  189. }
  190. /*
  191. This opens the specified library, mmaps it into memory, and searches
  192. for the QT_PLUGIN_VERIFICATION_DATA. The advantage of this approach is that
  193. we can get the verification data without have to actually load the library.
  194. This lets us detect mismatches more safely.
  195. Returns \c false if version information is not present, or if the
  196. information could not be read.
  197. Returns true if version information is present and successfully read.
  198. */
  199. static bool findPatternUnloaded(const QString &library, QLibraryPrivate *lib)
  200. {
  201. QFile file(library);
  202. if (!file.open(QIODevice::ReadOnly)) {
  203. if (lib)
  204. lib->errorString = file.errorString();
  205. if (qt_debug_component()) {
  206. qWarning("%s: %s", (const char*) QFile::encodeName(library),
  207. qPrintable(qt_error_string(errno)));
  208. }
  209. return false;
  210. }
  211. QByteArray data;
  212. const char *filedata = 0;
  213. ulong fdlen = file.size();
  214. filedata = (char *) file.map(0, fdlen);
  215. if (filedata == 0) {
  216. // try reading the data into memory instead
  217. data = file.readAll();
  218. filedata = data.constData();
  219. fdlen = data.size();
  220. }
  221. /*
  222. ELF and Mach-O binaries with GCC have .qplugin sections.
  223. */
  224. bool hasMetaData = false;
  225. long pos = 0;
  226. char pattern[] = "qTMETADATA ";
  227. pattern[0] = 'Q'; // Ensure the pattern "QTMETADATA" is not found in this library should QPluginLoader ever encounter it.
  228. const ulong plen = qstrlen(pattern);
  229. #if defined (Q_OF_ELF) && defined(Q_CC_GNU)
  230. int r = QElfParser().parse(filedata, fdlen, library, lib, &pos, &fdlen);
  231. if (r == QElfParser::Corrupt || r == QElfParser::NotElf) {
  232. if (lib && qt_debug_component()) {
  233. qWarning("QElfParser: %s",qPrintable(lib->errorString));
  234. }
  235. return false;
  236. } else if (r == QElfParser::QtMetaDataSection) {
  237. long rel = qt_find_pattern(filedata + pos, fdlen, pattern, plen);
  238. if (rel < 0)
  239. pos = -1;
  240. else
  241. pos += rel;
  242. hasMetaData = true;
  243. }
  244. #elif defined (Q_OF_MACH_O)
  245. {
  246. QString errorString;
  247. int r = QMachOParser::parse(filedata, fdlen, library, &errorString, &pos, &fdlen);
  248. if (r == QMachOParser::NotSuitable) {
  249. if (qt_debug_component())
  250. qWarning("QMachOParser: %s", qPrintable(errorString));
  251. if (lib)
  252. lib->errorString = errorString;
  253. return false;
  254. }
  255. // even if the metadata section was not found, the Mach-O parser will
  256. // at least return the boundaries of the right architecture
  257. long rel = qt_find_pattern(filedata + pos, fdlen, pattern, plen);
  258. if (rel < 0)
  259. pos = -1;
  260. else
  261. pos += rel;
  262. hasMetaData = true;
  263. }
  264. #else
  265. pos = qt_find_pattern(filedata, fdlen, pattern, plen);
  266. if (pos > 0)
  267. hasMetaData = true;
  268. #endif // defined(Q_OF_ELF) && defined(Q_CC_GNU)
  269. bool ret = false;
  270. if (pos >= 0) {
  271. if (hasMetaData) {
  272. const char *data = filedata + pos;
  273. QJsonDocument doc = QLibraryPrivate::fromRawMetaData(data);
  274. lib->metaData = doc.object();
  275. if (qt_debug_component())
  276. qWarning("Found metadata in lib %s, metadata=\n%s\n",
  277. library.toLocal8Bit().constData(), doc.toJson().constData());
  278. ret = !doc.isNull();
  279. }
  280. }
  281. if (!ret && lib)
  282. lib->errorString = QLibrary::tr("Plugin verification data mismatch in '%1'").arg(library);
  283. file.close();
  284. return ret;
  285. }
  286. static void installCoverageTool(QLibraryPrivate *libPrivate)
  287. {
  288. #ifdef __COVERAGESCANNER__
  289. /*
  290. __COVERAGESCANNER__ is defined when Qt has been instrumented for code
  291. coverage by TestCocoon. CoverageScanner is the name of the tool that
  292. generates the code instrumentation.
  293. This code is required here when code coverage analysis with TestCocoon
  294. is enabled in order to allow the loading application to register the plugin
  295. and then store its execution report. The execution report gathers information
  296. about each part of the plugin's code that has been used when
  297. the plugin was loaded by the launching application.
  298. The execution report for the plugin will go to the same execution report
  299. as the one defined for the application loading it.
  300. */
  301. int ret = __coveragescanner_register_library(libPrivate->fileName.toLocal8Bit());
  302. if (qt_debug_component()) {
  303. if (ret >= 0) {
  304. qDebug("%s: coverage data for %s registered",
  305. Q_FUNC_INFO,
  306. qPrintable(libPrivate->fileName));
  307. } else {
  308. qWarning("%s: could not register %s: error %d; coverage data may be incomplete",
  309. Q_FUNC_INFO,
  310. qPrintable(libPrivate->fileName),
  311. ret);
  312. }
  313. }
  314. #else
  315. Q_UNUSED(libPrivate);
  316. #endif
  317. }
  318. class QLibraryStore
  319. {
  320. public:
  321. inline ~QLibraryStore();
  322. static inline QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version);
  323. static inline void releaseLibrary(QLibraryPrivate *lib);
  324. static inline void cleanup();
  325. private:
  326. static inline QLibraryStore *instance();
  327. // all members and instance() are protected by qt_library_mutex
  328. typedef QMap<QString, QLibraryPrivate*> LibraryMap;
  329. LibraryMap libraryMap;
  330. };
  331. static QBasicMutex qt_library_mutex;
  332. static QLibraryStore *qt_library_data = 0;
  333. static bool qt_library_data_once;
  334. QLibraryStore::~QLibraryStore()
  335. {
  336. qt_library_data = 0;
  337. }
  338. inline void QLibraryStore::cleanup()
  339. {
  340. QLibraryStore *data = qt_library_data;
  341. if (!data)
  342. return;
  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.load() == 1) {
  348. if (lib->libraryUnloadCount.load() > 0) {
  349. Q_ASSERT(lib->pHnd);
  350. lib->libraryUnloadCount.store(1);
  351. #ifdef __GLIBC__
  352. // glibc has a bug in unloading from global destructors
  353. // see https://bugzilla.novell.com/show_bug.cgi?id=622977
  354. // and http://sourceware.org/bugzilla/show_bug.cgi?id=11941
  355. lib->unload(QLibraryPrivate::NoUnloadSys);
  356. #else
  357. lib->unload();
  358. #endif
  359. }
  360. delete lib;
  361. it.value() = 0;
  362. }
  363. }
  364. if (qt_debug_component()) {
  365. // dump all objects that remain
  366. foreach (QLibraryPrivate *lib, data->libraryMap) {
  367. if (lib)
  368. qDebug() << "On QtCore unload," << lib->fileName << "was leaked, with"
  369. << lib->libraryRefCount.load() << "users";
  370. }
  371. }
  372. delete data;
  373. }
  374. static void qlibraryCleanup()
  375. {
  376. QLibraryStore::cleanup();
  377. }
  378. Q_DESTRUCTOR_FUNCTION(qlibraryCleanup)
  379. // must be called with a locked mutex
  380. QLibraryStore *QLibraryStore::instance()
  381. {
  382. if (Q_UNLIKELY(!qt_library_data_once && !qt_library_data)) {
  383. // only create once per process lifetime
  384. qt_library_data = new QLibraryStore;
  385. qt_library_data_once = true;
  386. }
  387. return qt_library_data;
  388. }
  389. inline QLibraryPrivate *QLibraryStore::findOrCreate(const QString &fileName, const QString &version)
  390. {
  391. QMutexLocker locker(&qt_library_mutex);
  392. QLibraryStore *data = instance();
  393. // check if this library is already loaded
  394. QLibraryPrivate *lib = 0;
  395. if (Q_LIKELY(data))
  396. lib = data->libraryMap.value(fileName);
  397. if (!lib)
  398. lib = new QLibraryPrivate(fileName, version);
  399. // track this library
  400. if (Q_LIKELY(data))
  401. data->libraryMap.insert(fileName, lib);
  402. lib->libraryRefCount.ref();
  403. return lib;
  404. }
  405. inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib)
  406. {
  407. QMutexLocker locker(&qt_library_mutex);
  408. QLibraryStore *data = instance();
  409. if (lib->libraryRefCount.deref()) {
  410. // still in use
  411. return;
  412. }
  413. // no one else is using
  414. Q_ASSERT(lib->libraryUnloadCount.load() == 0);
  415. if (Q_LIKELY(data)) {
  416. QLibraryPrivate *that = data->libraryMap.take(lib->fileName);
  417. Q_ASSERT(lib == that);
  418. Q_UNUSED(that);
  419. }
  420. delete lib;
  421. }
  422. QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version)
  423. : pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0),
  424. loadHints(0),
  425. libraryRefCount(0), libraryUnloadCount(0), pluginState(MightBeAPlugin)
  426. { }
  427. QLibraryPrivate *QLibraryPrivate::findOrCreate(const QString &fileName, const QString &version)
  428. {
  429. return QLibraryStore::findOrCreate(fileName, version);
  430. }
  431. QLibraryPrivate::~QLibraryPrivate()
  432. {
  433. }
  434. QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
  435. {
  436. if (!pHnd)
  437. return 0;
  438. return resolve_sys(symbol);
  439. }
  440. bool QLibraryPrivate::load()
  441. {
  442. if (pHnd) {
  443. libraryUnloadCount.ref();
  444. return true;
  445. }
  446. if (fileName.isEmpty())
  447. return false;
  448. bool ret = load_sys();
  449. if (qt_debug_component())
  450. qDebug() << "loaded library" << fileName;
  451. if (ret) {
  452. //when loading a library we add a reference to it so that the QLibraryPrivate won't get deleted
  453. //this allows to unload the library at a later time
  454. libraryUnloadCount.ref();
  455. libraryRefCount.ref();
  456. installCoverageTool(this);
  457. }
  458. return ret;
  459. }
  460. bool QLibraryPrivate::unload(UnloadFlag flag)
  461. {
  462. if (!pHnd)
  463. return false;
  464. if (libraryUnloadCount.load() > 0 && !libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to
  465. delete inst.data();
  466. if (flag == NoUnloadSys || unload_sys()) {
  467. if (qt_debug_component())
  468. qWarning() << "QLibraryPrivate::unload succeeded on" << fileName
  469. << (flag == NoUnloadSys ? "(faked)" : "");
  470. //when the library is unloaded, we release the reference on it so that 'this'
  471. //can get deleted
  472. libraryRefCount.deref();
  473. pHnd = 0;
  474. instance = 0;
  475. }
  476. }
  477. return (pHnd == 0);
  478. }
  479. void QLibraryPrivate::release()
  480. {
  481. QLibraryStore::releaseLibrary(this);
  482. }
  483. bool QLibraryPrivate::loadPlugin()
  484. {
  485. if (instance) {
  486. libraryUnloadCount.ref();
  487. return true;
  488. }
  489. if (pluginState == IsNotAPlugin)
  490. return false;
  491. if (load()) {
  492. instance = (QtPluginInstanceFunction)resolve("qt_plugin_instance");
  493. return instance;
  494. }
  495. if (qt_debug_component())
  496. qWarning() << "QLibraryPrivate::loadPlugin failed on" << fileName << ":" << errorString;
  497. pluginState = IsNotAPlugin;
  498. return false;
  499. }
  500. /*!
  501. Returns \c true if \a fileName has a valid suffix for a loadable
  502. library; otherwise returns \c false.
  503. \table
  504. \header \li Platform \li Valid suffixes
  505. \row \li Windows \li \c .dll, \c .DLL
  506. \row \li Unix/Linux \li \c .so
  507. \row \li AIX \li \c .a
  508. \row \li HP-UX \li \c .sl, \c .so (HP-UXi)
  509. \row \li Mac OS X \li \c .dylib, \c .bundle, \c .so
  510. \endtable
  511. Trailing versioning numbers on Unix are ignored.
  512. */
  513. bool QLibrary::isLibrary(const QString &fileName)
  514. {
  515. #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
  516. return fileName.endsWith(QLatin1String(".dll"), Qt::CaseInsensitive);
  517. #else
  518. QString completeSuffix = QFileInfo(fileName).completeSuffix();
  519. if (completeSuffix.isEmpty())
  520. return false;
  521. QStringList suffixes = completeSuffix.split(QLatin1Char('.'));
  522. # if defined(Q_OS_DARWIN)
  523. // On Mac, libs look like libmylib.1.0.0.dylib
  524. const QString lastSuffix = suffixes.at(suffixes.count() - 1);
  525. const QString firstSuffix = suffixes.at(0);
  526. bool valid = (lastSuffix == QLatin1String("dylib")
  527. || firstSuffix == QLatin1String("so")
  528. || firstSuffix == QLatin1String("bundle"));
  529. return valid;
  530. # else // Generic Unix
  531. QStringList validSuffixList;
  532. # if defined(Q_OS_HPUX)
  533. /*
  534. See "HP-UX Linker and Libraries User's Guide", section "Link-time Differences between PA-RISC and IPF":
  535. "In PA-RISC (PA-32 and PA-64) shared libraries are suffixed with .sl. In IPF (32-bit and 64-bit),
  536. the shared libraries are suffixed with .so. For compatibility, the IPF linker also supports the .sl suffix."
  537. */
  538. validSuffixList << QLatin1String("sl");
  539. # if defined __ia64
  540. validSuffixList << QLatin1String("so");
  541. # endif
  542. # elif defined(Q_OS_AIX)
  543. validSuffixList << QLatin1String("a") << QLatin1String("so");
  544. # elif defined(Q_OS_UNIX)
  545. validSuffixList << QLatin1String("so");
  546. # endif
  547. // Examples of valid library names:
  548. // libfoo.so
  549. // libfoo.so.0
  550. // libfoo.so.0.3
  551. // libfoo-0.3.so
  552. // libfoo-0.3.so.0.3.0
  553. int suffix;
  554. int suffixPos = -1;
  555. for (suffix = 0; suffix < validSuffixList.count() && suffixPos == -1; ++suffix)
  556. suffixPos = suffixes.indexOf(validSuffixList.at(suffix));
  557. bool valid = suffixPos != -1;
  558. for (int i = suffixPos + 1; i < suffixes.count() && valid; ++i)
  559. if (i != suffixPos)
  560. suffixes.at(i).toInt(&valid);
  561. return valid;
  562. # endif
  563. #endif
  564. }
  565. typedef const char * (*QtPluginQueryVerificationDataFunction)();
  566. static bool qt_get_metadata(QtPluginQueryVerificationDataFunction pfn, QLibraryPrivate *priv)
  567. {
  568. const char *szData = 0;
  569. if (!pfn)
  570. return false;
  571. szData = pfn();
  572. if (!szData)
  573. return false;
  574. QJsonDocument doc = QLibraryPrivate::fromRawMetaData(szData);
  575. if (doc.isNull())
  576. return false;
  577. priv->metaData = doc.object();
  578. return true;
  579. }
  580. bool QLibraryPrivate::isPlugin()
  581. {
  582. if (pluginState == MightBeAPlugin)
  583. updatePluginState();
  584. return pluginState == IsAPlugin;
  585. }
  586. void QLibraryPrivate::updatePluginState()
  587. {
  588. errorString.clear();
  589. if (pluginState != MightBeAPlugin)
  590. return;
  591. bool success = false;
  592. #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
  593. if (fileName.endsWith(QLatin1String(".debug"))) {
  594. // refuse to load a file that ends in .debug
  595. // these are the debug symbols from the libraries
  596. // the problem is that they are valid shared library files
  597. // and dlopen is known to crash while opening them
  598. // pretend we didn't see the file
  599. errorString = QLibrary::tr("The shared library was not found.");
  600. pluginState = IsNotAPlugin;
  601. return;
  602. }
  603. #endif
  604. if (!pHnd) {
  605. // scan for the plugin metadata without loading
  606. success = findPatternUnloaded(fileName, this);
  607. } else {
  608. // library is already loaded (probably via QLibrary)
  609. // simply get the target function and call it.
  610. QtPluginQueryVerificationDataFunction getMetaData = NULL;
  611. getMetaData = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_metadata");
  612. success = qt_get_metadata(getMetaData, this);
  613. }
  614. if (!success) {
  615. if (errorString.isEmpty()){
  616. if (fileName.isEmpty())
  617. errorString = QLibrary::tr("The shared library was not found.");
  618. else
  619. errorString = QLibrary::tr("The file '%1' is not a valid Qt plugin.").arg(fileName);
  620. }
  621. pluginState = IsNotAPlugin;
  622. return;
  623. }
  624. pluginState = IsNotAPlugin; // be pessimistic
  625. uint qt_version = (uint)metaData.value(QLatin1String("version")).toDouble();
  626. bool debug = metaData.value(QLatin1String("debug")).toBool();
  627. if ((qt_version & 0x00ff00) > (QT_VERSION & 0x00ff00) || (qt_version & 0xff0000) != (QT_VERSION & 0xff0000)) {
  628. if (qt_debug_component()) {
  629. qWarning("In %s:\n"
  630. " Plugin uses incompatible Qt library (%d.%d.%d) [%s]",
  631. (const char*) QFile::encodeName(fileName),
  632. (qt_version&0xff0000) >> 16, (qt_version&0xff00) >> 8, qt_version&0xff,
  633. debug ? "debug" : "release");
  634. }
  635. errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5]")
  636. .arg(fileName)
  637. .arg((qt_version&0xff0000) >> 16)
  638. .arg((qt_version&0xff00) >> 8)
  639. .arg(qt_version&0xff)
  640. .arg(debug ? QLatin1String("debug") : QLatin1String("release"));
  641. #ifndef QT_NO_DEBUG_PLUGIN_CHECK
  642. } else if(debug != QLIBRARY_AS_DEBUG) {
  643. //don't issue a qWarning since we will hopefully find a non-debug? --Sam
  644. errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library."
  645. " (Cannot mix debug and release libraries.)").arg(fileName);
  646. #endif
  647. } else {
  648. pluginState = IsAPlugin;
  649. }
  650. }
  651. /*!
  652. Loads the library and returns \c true if the library was loaded
  653. successfully; otherwise returns \c false. Since resolve() always
  654. calls this function before resolving any symbols it is not
  655. necessary to call it explicitly. In some situations you might want
  656. the library loaded in advance, in which case you would use this
  657. function.
  658. \sa unload()
  659. */
  660. bool QLibrary::load()
  661. {
  662. if (!d)
  663. return false;
  664. if (did_load)
  665. return d->pHnd;
  666. did_load = true;
  667. return d->load();
  668. }
  669. /*!
  670. Unloads the library and returns \c true if the library could be
  671. unloaded; otherwise returns \c false.
  672. This happens automatically on application termination, so you
  673. shouldn't normally need to call this function.
  674. If other instances of QLibrary are using the same library, the
  675. call will fail, and unloading will only happen when every instance
  676. has called unload().
  677. Note that on Mac OS X 10.3 (Panther), dynamic libraries cannot be unloaded.
  678. \sa resolve(), load()
  679. */
  680. bool QLibrary::unload()
  681. {
  682. if (did_load) {
  683. did_load = false;
  684. return d->unload();
  685. }
  686. return false;
  687. }
  688. /*!
  689. Returns \c true if the library is loaded; otherwise returns \c false.
  690. \sa load()
  691. */
  692. bool QLibrary::isLoaded() const
  693. {
  694. return d && d->pHnd;
  695. }
  696. /*!
  697. Constructs a library with the given \a parent.
  698. */
  699. QLibrary::QLibrary(QObject *parent)
  700. :QObject(parent), d(0), did_load(false)
  701. {
  702. }
  703. /*!
  704. Constructs a library object with the given \a parent that will
  705. load the library specified by \a fileName.
  706. We recommend omitting the file's suffix in \a fileName, since
  707. QLibrary will automatically look for the file with the appropriate
  708. suffix in accordance with the platform, e.g. ".so" on Unix,
  709. ".dylib" on Mac OS X, and ".dll" on Windows. (See \l{fileName}.)
  710. */
  711. QLibrary::QLibrary(const QString& fileName, QObject *parent)
  712. :QObject(parent), d(0), did_load(false)
  713. {
  714. setFileName(fileName);
  715. }
  716. /*!
  717. Constructs a library object with the given \a parent that will
  718. load the library specified by \a fileName and major version number \a verNum.
  719. Currently, the version number is ignored on Windows.
  720. We recommend omitting the file's suffix in \a fileName, since
  721. QLibrary will automatically look for the file with the appropriate
  722. suffix in accordance with the platform, e.g. ".so" on Unix,
  723. ".dylib" on Mac OS X, and ".dll" on Windows. (See \l{fileName}.)
  724. */
  725. QLibrary::QLibrary(const QString& fileName, int verNum, QObject *parent)
  726. :QObject(parent), d(0), did_load(false)
  727. {
  728. setFileNameAndVersion(fileName, verNum);
  729. }
  730. /*!
  731. Constructs a library object with the given \a parent that will
  732. load the library specified by \a fileName and full version number \a version.
  733. Currently, the version number is ignored on Windows.
  734. We recommend omitting the file's suffix in \a fileName, since
  735. QLibrary will automatically look for the file with the appropriate
  736. suffix in accordance with the platform, e.g. ".so" on Unix,
  737. ".dylib" on Mac OS X, and ".dll" on Windows. (See \l{fileName}.)
  738. */
  739. QLibrary::QLibrary(const QString& fileName, const QString &version, QObject *parent)
  740. :QObject(parent), d(0), did_load(false)
  741. {
  742. setFileNameAndVersion(fileName, version);
  743. }
  744. /*!
  745. Destroys the QLibrary object.
  746. Unless unload() was called explicitly, the library stays in memory
  747. until the application terminates.
  748. \sa isLoaded(), unload()
  749. */
  750. QLibrary::~QLibrary()
  751. {
  752. if (d)
  753. d->release();
  754. }
  755. /*!
  756. \property QLibrary::fileName
  757. \brief the file name of the library
  758. We recommend omitting the file's suffix in the file name, since
  759. QLibrary will automatically look for the file with the appropriate
  760. suffix (see isLibrary()).
  761. When loading the library, QLibrary searches in all system-specific
  762. library locations (e.g. \c LD_LIBRARY_PATH on Unix), unless the
  763. file name has an absolute path. After loading the library
  764. successfully, fileName() returns the fully-qualified file name of
  765. the library, including the full path to the library if one was given
  766. in the constructor or passed to setFileName().
  767. For example, after successfully loading the "GL" library on Unix
  768. platforms, fileName() will return "libGL.so". If the file name was
  769. originally passed as "/usr/lib/libGL", fileName() will return
  770. "/usr/lib/libGL.so".
  771. */
  772. void QLibrary::setFileName(const QString &fileName)
  773. {
  774. QLibrary::LoadHints lh;
  775. if (d) {
  776. lh = d->loadHints;
  777. d->release();
  778. d = 0;
  779. did_load = false;
  780. }
  781. d = QLibraryPrivate::findOrCreate(fileName);
  782. d->loadHints = lh;
  783. }
  784. QString QLibrary::fileName() const
  785. {
  786. if (d)
  787. return d->qualifiedFileName.isEmpty() ? d->fileName : d->qualifiedFileName;
  788. return QString();
  789. }
  790. /*!
  791. \fn void QLibrary::setFileNameAndVersion(const QString &fileName, int versionNumber)
  792. Sets the fileName property and major version number to \a fileName
  793. and \a versionNumber respectively.
  794. The \a versionNumber is ignored on Windows.
  795. \sa setFileName()
  796. */
  797. void QLibrary::setFileNameAndVersion(const QString &fileName, int verNum)
  798. {
  799. QLibrary::LoadHints lh;
  800. if (d) {
  801. lh = d->loadHints;
  802. d->release();
  803. d = 0;
  804. did_load = false;
  805. }
  806. d = QLibraryPrivate::findOrCreate(fileName, verNum >= 0 ? QString::number(verNum) : QString());
  807. d->loadHints = lh;
  808. }
  809. /*!
  810. \since 4.4
  811. Sets the fileName property and full version number to \a fileName
  812. and \a version respectively.
  813. The \a version parameter is ignored on Windows.
  814. \sa setFileName()
  815. */
  816. void QLibrary::setFileNameAndVersion(const QString &fileName, const QString &version)
  817. {
  818. QLibrary::LoadHints lh;
  819. if (d) {
  820. lh = d->loadHints;
  821. d->release();
  822. d = 0;
  823. did_load = false;
  824. }
  825. d = QLibraryPrivate::findOrCreate(fileName, version);
  826. d->loadHints = lh;
  827. }
  828. /*!
  829. Returns the address of the exported symbol \a symbol. The library is
  830. loaded if necessary. The function returns 0 if the symbol could
  831. not be resolved or if the library could not be loaded.
  832. Example:
  833. \snippet code/src_corelib_plugin_qlibrary.cpp 2
  834. The symbol must be exported as a C function from the library. This
  835. means that the function must be wrapped in an \c{extern "C"} if
  836. the library is compiled with a C++ compiler. On Windows you must
  837. also explicitly export the function from the DLL using the
  838. \c{__declspec(dllexport)} compiler directive, for example:
  839. \snippet code/src_corelib_plugin_qlibrary.cpp 3
  840. with \c MY_EXPORT defined as
  841. \snippet code/src_corelib_plugin_qlibrary.cpp 4
  842. */
  843. QFunctionPointer QLibrary::resolve(const char *symbol)
  844. {
  845. if (!isLoaded() && !load())
  846. return 0;
  847. return d->resolve(symbol);
  848. }
  849. /*!
  850. \overload
  851. Loads the library \a fileName and returns the address of the
  852. exported symbol \a symbol. Note that \a fileName should not
  853. include the platform-specific file suffix; (see \l{fileName}). The
  854. library remains loaded until the application exits.
  855. The function returns 0 if the symbol could not be resolved or if
  856. the library could not be loaded.
  857. \sa resolve()
  858. */
  859. QFunctionPointer QLibrary::resolve(const QString &fileName, const char *symbol)
  860. {
  861. QLibrary library(fileName);
  862. return library.resolve(symbol);
  863. }
  864. /*!
  865. \overload
  866. Loads the library \a fileName with major version number \a verNum and
  867. returns the address of the exported symbol \a symbol.
  868. Note that \a fileName should not include the platform-specific file suffix;
  869. (see \l{fileName}). The library remains loaded until the application exits.
  870. \a verNum is ignored on Windows.
  871. The function returns 0 if the symbol could not be resolved or if
  872. the library could not be loaded.
  873. \sa resolve()
  874. */
  875. QFunctionPointer QLibrary::resolve(const QString &fileName, int verNum, const char *symbol)
  876. {
  877. QLibrary library(fileName, verNum);
  878. return library.resolve(symbol);
  879. }
  880. /*!
  881. \overload
  882. \since 4.4
  883. Loads the library \a fileName with full version number \a version and
  884. returns the address of the exported symbol \a symbol.
  885. Note that \a fileName should not include the platform-specific file suffix;
  886. (see \l{fileName}). The library remains loaded until the application exits.
  887. \a version is ignored on Windows.
  888. The function returns 0 if the symbol could not be resolved or if
  889. the library could not be loaded.
  890. \sa resolve()
  891. */
  892. QFunctionPointer QLibrary::resolve(const QString &fileName, const QString &version, const char *symbol)
  893. {
  894. QLibrary library(fileName, version);
  895. return library.resolve(symbol);
  896. }
  897. /*!
  898. \since 4.2
  899. Returns a text string with the description of the last error that occurred.
  900. Currently, errorString will only be set if load(), unload() or resolve() for some reason fails.
  901. */
  902. QString QLibrary::errorString() const
  903. {
  904. return (!d || d->errorString.isEmpty()) ? tr("Unknown error") : d->errorString;
  905. }
  906. /*!
  907. \property QLibrary::loadHints
  908. \brief Give the load() function some hints on how it should behave.
  909. You can give some hints on how the symbols are resolved. Usually,
  910. the symbols are not resolved at load time, but resolved lazily,
  911. (that is, when resolve() is called). If you set the loadHint to
  912. ResolveAllSymbolsHint, then all symbols will be resolved at load time
  913. if the platform supports it.
  914. Setting ExportExternalSymbolsHint will make the external symbols in the
  915. library available for resolution in subsequent loaded libraries.
  916. If LoadArchiveMemberHint is set, the file name
  917. is composed of two components: A path which is a reference to an
  918. archive file followed by the second component which is the reference to
  919. the archive member. For instance, the fileName \c libGL.a(shr_64.o) will refer
  920. to the library \c shr_64.o in the archive file named \c libGL.a. This
  921. is only supported on the AIX platform.
  922. Setting PreventUnloadHint will only apply on Unix platforms.
  923. The interpretation of the load hints is platform dependent, and if
  924. you use it you are probably making some assumptions on which platform
  925. you are compiling for, so use them only if you understand the consequences
  926. of them.
  927. By default, none of these flags are set, so libraries will be loaded with
  928. lazy symbol resolution, and will not export external symbols for resolution
  929. in other dynamically-loaded libraries.
  930. */
  931. void QLibrary::setLoadHints(LoadHints hints)
  932. {
  933. if (!d) {
  934. d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr
  935. d->errorString.clear();
  936. }
  937. d->loadHints = hints;
  938. }
  939. QLibrary::LoadHints QLibrary::loadHints() const
  940. {
  941. return d ? d->loadHints : (QLibrary::LoadHints)0;
  942. }
  943. /* Internal, for debugging */
  944. bool qt_debug_component()
  945. {
  946. static int debug_env = -1;
  947. if (debug_env == -1)
  948. debug_env = QT_PREPEND_NAMESPACE(qgetenv)("QT_DEBUG_PLUGINS").toInt();
  949. return debug_env != 0;
  950. }
  951. QT_END_NAMESPACE
  952. #endif // QT_NO_LIBRARY