Qt 4.8
qlibrary.cpp
Go to the documentation of this file.
1 
2 /****************************************************************************
3 **
4 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
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 
45 #ifndef QT_NO_LIBRARY
46 
47 #include "qlibrary_p.h"
48 #include <qstringlist.h>
49 #include <qfile.h>
50 #include <qfileinfo.h>
51 #include <qmutex.h>
52 #include <qmap.h>
53 #include <qsettings.h>
54 #include <qdatetime.h>
55 #include <private/qcoreapplication_p.h>
56 #ifdef Q_OS_MAC
57 # include <private/qcore_mac_p.h>
58 #endif
59 #ifndef NO_ERRNO_H
60 #include <errno.h>
61 #endif // NO_ERROR_H
62 #include <qdebug.h>
63 #include <qvector.h>
64 #include <qdir.h>
65 #include "qelfparser_p.h"
66 
68 
69 #ifdef QT_NO_DEBUG
70 # define QLIBRARY_AS_DEBUG false
71 #else
72 # define QLIBRARY_AS_DEBUG true
73 #endif
74 
75 #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
76 // We don't use separate debug and release libs on UNIX, so we want
77 // to allow loading plugins, regardless of how they were built.
78 # define QT_NO_DEBUG_PLUGIN_CHECK
79 #endif
80 
81 Q_GLOBAL_STATIC(QMutex, qt_library_mutex)
82 
83 
181 #ifndef QT_NO_PLUGIN_CHECK
183 {
184  qt_token_info(const char *f, const ulong fc)
185  : fields(f), field_count(fc), results(fc), lengths(fc)
186  {
187  results.fill(0);
188  lengths.fill(0);
189  }
190 
191  const char *fields;
193 
196 };
197 
198 /*
199  return values:
200  1 parse ok
201  0 eos
202  -1 parse error
203 */
204 static int qt_tokenize(const char *s, ulong s_len, ulong *advance,
205  qt_token_info &token_info)
206 {
207  if (!s)
208  return -1;
209 
210  ulong pos = 0, field = 0, fieldlen = 0;
211  char current;
212  int ret = -1;
213  *advance = 0;
214  for (;;) {
215  current = s[pos];
216 
217  // next char
218  ++pos;
219  ++fieldlen;
220  ++*advance;
221 
222  if (! current || pos == s_len + 1) {
223  // save result
224  token_info.results[(int)field] = s;
225  token_info.lengths[(int)field] = fieldlen - 1;
226 
227  // end of string
228  ret = 0;
229  break;
230  }
231 
232  if (current == token_info.fields[field]) {
233  // save result
234  token_info.results[(int)field] = s;
235  token_info.lengths[(int)field] = fieldlen - 1;
236 
237  // end of field
238  fieldlen = 0;
239  ++field;
240  if (field == token_info.field_count - 1) {
241  // parse ok
242  ret = 1;
243  }
244  if (field == token_info.field_count) {
245  // done parsing
246  break;
247  }
248 
249  // reset string and its length
250  s = s + pos;
251  s_len -= pos;
252  pos = 0;
253  }
254  }
255 
256  return ret;
257 }
258 
259 /*
260  returns true if the string s was correctly parsed, false otherwise.
261 */
262 static bool qt_parse_pattern(const char *s, uint *version, bool *debug, QByteArray *key)
263 {
264  bool ret = true;
265 
266  qt_token_info pinfo("=\n", 2);
267  int parse;
268  ulong at = 0, advance, parselen = qstrlen(s);
269  do {
270  parse = qt_tokenize(s + at, parselen, &advance, pinfo);
271  if (parse == -1) {
272  ret = false;
273  break;
274  }
275 
276  at += advance;
277  parselen -= advance;
278 
279  if (qstrncmp("version", pinfo.results[0], pinfo.lengths[0]) == 0) {
280  // parse version string
281  qt_token_info pinfo2("..-", 3);
282  if (qt_tokenize(pinfo.results[1], pinfo.lengths[1],
283  &advance, pinfo2) != -1) {
284  QByteArray m(pinfo2.results[0], pinfo2.lengths[0]);
285  QByteArray n(pinfo2.results[1], pinfo2.lengths[1]);
286  QByteArray p(pinfo2.results[2], pinfo2.lengths[2]);
287  *version = (m.toUInt() << 16) | (n.toUInt() << 8) | p.toUInt();
288  } else {
289  ret = false;
290  break;
291  }
292  } else if (qstrncmp("debug", pinfo.results[0], pinfo.lengths[0]) == 0) {
293  *debug = qstrncmp("true", pinfo.results[1], pinfo.lengths[1]) == 0;
294  } else if (qstrncmp("buildkey", pinfo.results[0],
295  pinfo.lengths[0]) == 0){
296  // save buildkey
297  *key = QByteArray(pinfo.results[1], pinfo.lengths[1]);
298  }
299  } while (parse == 1 && parselen > 0);
300 
301  return ret;
302 }
303 #endif // QT_NO_PLUGIN_CHECK
304 
305 #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_SYMBIAN) && !defined(QT_NO_PLUGIN_CHECK)
306 
307 static long qt_find_pattern(const char *s, ulong s_len,
308  const char *pattern, ulong p_len)
309 {
310  /*
311  we search from the end of the file because on the supported
312  systems, the read-only data/text segments are placed at the end
313  of the file. HOWEVER, when building with debugging enabled, all
314  the debug symbols are placed AFTER the data/text segments.
315 
316  what does this mean? when building in release mode, the search
317  is fast because the data we are looking for is at the end of the
318  file... when building in debug mode, the search is slower
319  because we have to skip over all the debugging symbols first
320  */
321 
322  if (! s || ! pattern || p_len > s_len) return -1;
323  ulong i, hs = 0, hp = 0, delta = s_len - p_len;
324 
325  for (i = 0; i < p_len; ++i) {
326  hs += s[delta + i];
327  hp += pattern[i];
328  }
329  i = delta;
330  for (;;) {
331  if (hs == hp && qstrncmp(s + i, pattern, p_len) == 0)
332  return i;
333  if (i == 0)
334  break;
335  --i;
336  hs -= s[i + p_len];
337  hs += s[i];
338  }
339 
340  return -1;
341 }
342 
343 /*
344  This opens the specified library, mmaps it into memory, and searches
345  for the QT_PLUGIN_VERIFICATION_DATA. The advantage of this approach is that
346  we can get the verification data without have to actually load the library.
347  This lets us detect mismatches more safely.
348 
349  Returns false if version/key information is not present, or if the
350  information could not be read.
351  Returns true if version/key information is present and successfully read.
352 */
353 static bool qt_unix_query(const QString &library, uint *version, bool *debug, QByteArray *key, QLibraryPrivate *lib = 0)
354 {
355  QFile file(library);
356  if (!file.open(QIODevice::ReadOnly)) {
357  if (lib)
358  lib->errorString = file.errorString();
359  if (qt_debug_component()) {
360  qWarning("%s: %s", (const char*) QFile::encodeName(library),
362  }
363  return false;
364  }
365 
367  const char *filedata = 0;
368  ulong fdlen = file.size();
369  filedata = (char *) file.map(0, fdlen);
370  if (filedata == 0) {
371  // try reading the data into memory instead
372  data = file.readAll();
373  filedata = data.constData();
374  fdlen = data.size();
375  }
376 
377  /*
378  ELF binaries on GNU, have .qplugin sections.
379  */
380  long pos = 0;
381  const char pattern[] = "pattern=QT_PLUGIN_VERIFICATION_DATA";
382  const ulong plen = qstrlen(pattern);
383 #if defined (Q_OF_ELF) && defined(Q_CC_GNU)
384  int r = QElfParser().parse(filedata, fdlen, library, lib, &pos, &fdlen);
385  if (r == QElfParser::NoQtSection) {
386  if (pos > 0) {
387  // find inside .rodata
388  long rel = qt_find_pattern(filedata + pos, fdlen, pattern, plen);
389  if (rel < 0) {
390  pos = -1;
391  } else {
392  pos += rel;
393  }
394  } else {
395  pos = qt_find_pattern(filedata, fdlen, pattern, plen);
396  }
397  } else if (r != QElfParser::Ok) {
398  if (lib && qt_debug_component()) {
399  qWarning("QElfParser: %s",qPrintable(lib->errorString));
400  }
401  return false;
402  }
403 #else
404  pos = qt_find_pattern(filedata, fdlen, pattern, plen);
405 #endif // defined(Q_OF_ELF) && defined(Q_CC_GNU)
406  bool ret = false;
407  if (pos >= 0)
408  ret = qt_parse_pattern(filedata + pos, version, debug, key);
409 
410  if (!ret && lib)
411  lib->errorString = QLibrary::tr("Plugin verification data mismatch in '%1'").arg(library);
412  file.close();
413  return ret;
414 }
415 
416 #endif // Q_OS_UNIX && !Q_OS_MAC && !defined(Q_OS_SYMBIAN) && !defined(QT_NO_PLUGIN_CHECK)
417 
419 
420 struct LibraryData {
421  LibraryMap libraryMap;
423 };
424 
425 Q_GLOBAL_STATIC(LibraryData, libraryData)
426 
427 static LibraryMap *libraryMap()
428 {
429  LibraryData *data = libraryData();
430  return data ? &data->libraryMap : 0;
431 }
432 
433 QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version)
434  :pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0), qt_version(0),
435  libraryRefCount(1), libraryUnloadCount(0), pluginState(MightBeAPlugin)
436 { libraryMap()->insert(canonicalFileName, this); }
437 
439 {
440  QMutexLocker locker(qt_library_mutex());
441  if (QLibraryPrivate *lib = libraryMap()->value(fileName)) {
442  lib->libraryRefCount.ref();
443  return lib;
444  }
445 
446  return new QLibraryPrivate(fileName, version);
447 }
448 
450 {
451  LibraryMap * const map = libraryMap();
452  if (map) {
453  QLibraryPrivate *that = map->take(fileName);
454  Q_ASSERT(this == that);
455  Q_UNUSED(that);
456  }
457 }
458 
459 void *QLibraryPrivate::resolve(const char *symbol)
460 {
461  if (!pHnd)
462  return 0;
463  return resolve_sys(symbol);
464 }
465 
466 
468 {
470  if (pHnd)
471  return true;
472  if (fileName.isEmpty())
473  return false;
474 
475  bool ret = load_sys();
476  if (ret) {
477  //when loading a library we add a reference to it so that the QLibraryPrivate won't get deleted
478  //this allows to unload the library at a later time
479  if (LibraryData *lib = libraryData()) {
480  lib->loadedLibs += this;
482  }
483  }
484 
485  return ret;
486 }
487 
489 {
490  if (!pHnd)
491  return false;
492  if (!libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to
493  delete inst.data();
494  if (unload_sys()) {
495  if (qt_debug_component())
496  qWarning() << "QLibraryPrivate::unload succeeded on" << fileName;
497  //when the library is unloaded, we release the reference on it so that 'this'
498  //can get deleted
499  if (LibraryData *lib = libraryData()) {
500  if (lib->loadedLibs.remove(this))
502  }
503  pHnd = 0;
504  }
505  }
506 
507  return (pHnd == 0);
508 }
509 
511 {
512  QMutexLocker locker(qt_library_mutex());
513  if (!libraryRefCount.deref())
514  delete this;
515 }
516 
518 {
519  if (instance) {
521  return true;
522  }
523  if (pluginState == IsNotAPlugin)
524  return false;
525  if (load()) {
526  instance = (QtPluginInstanceFunction)resolve("qt_plugin_instance");
527 #if defined(Q_OS_SYMBIAN)
528  if (!instance) {
529  // If resolving with function name failed (i.e. not STDDLL),
530  // try resolving using known ordinal, which for
531  // qt_plugin_instance function is always "2".
533  }
534 #endif
535  return instance;
536  }
537  if (qt_debug_component())
538  qWarning() << "QLibraryPrivate::loadPlugin failed on" << fileName << ":" << errorString;
540  return false;
541 }
542 
560 {
561 #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
562  return fileName.endsWith(QLatin1String(".dll"), Qt::CaseInsensitive);
563 #elif defined(Q_OS_SYMBIAN)
564  // Plugin stubs are also considered libraries in Symbian.
565  return (fileName.endsWith(QLatin1String(".dll")) ||
566  fileName.endsWith(QLatin1String(".qtplugin")));
567 #else
568  QString completeSuffix = QFileInfo(fileName).completeSuffix();
569  if (completeSuffix.isEmpty())
570  return false;
571  QStringList suffixes = completeSuffix.split(QLatin1Char('.'));
572 # if defined(Q_OS_DARWIN)
573 
574  // On Mac, libs look like libmylib.1.0.0.dylib
575  const QString lastSuffix = suffixes.at(suffixes.count() - 1);
576  const QString firstSuffix = suffixes.at(0);
577 
578  bool valid = (lastSuffix == QLatin1String("dylib")
579  || firstSuffix == QLatin1String("so")
580  || firstSuffix == QLatin1String("bundle"));
581 
582  return valid;
583 # else // Generic Unix
584  QStringList validSuffixList;
585 
586 # if defined(Q_OS_HPUX)
587 /*
588  See "HP-UX Linker and Libraries User's Guide", section "Link-time Differences between PA-RISC and IPF":
589  "In PA-RISC (PA-32 and PA-64) shared libraries are suffixed with .sl. In IPF (32-bit and 64-bit),
590  the shared libraries are suffixed with .so. For compatibility, the IPF linker also supports the .sl suffix."
591  */
592  validSuffixList << QLatin1String("sl");
593 # if defined __ia64
594  validSuffixList << QLatin1String("so");
595 # endif
596 # elif defined(Q_OS_AIX)
597  validSuffixList << QLatin1String("a") << QLatin1String("so");
598 # elif defined(Q_OS_UNIX)
599  validSuffixList << QLatin1String("so");
600 # endif
601 
602  // Examples of valid library names:
603  // libfoo.so
604  // libfoo.so.0
605  // libfoo.so.0.3
606  // libfoo-0.3.so
607  // libfoo-0.3.so.0.3.0
608 
609  int suffix;
610  int suffixPos = -1;
611  for (suffix = 0; suffix < validSuffixList.count() && suffixPos == -1; ++suffix)
612  suffixPos = suffixes.indexOf(validSuffixList.at(suffix));
613 
614  bool valid = suffixPos != -1;
615  for (int i = suffixPos + 1; i < suffixes.count() && valid; ++i)
616  if (i != suffixPos)
617  suffixes.at(i).toInt(&valid);
618  return valid;
619 # endif
620 #endif
621 
622 }
623 
624 #if defined (Q_OS_WIN) && defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(Q_CC_INTEL)
625 #define QT_USE_MS_STD_EXCEPTION 1
626 const char* qt_try_versioninfo(void *pfn, bool *exceptionThrown)
627 {
628  *exceptionThrown = false;
629  const char *szData = 0;
630  typedef const char * (*VerificationFunction)();
631  VerificationFunction func = reinterpret_cast<VerificationFunction>(pfn);
632  __try {
633  if(func)
634  szData = func();
635  } __except(EXCEPTION_EXECUTE_HANDLER) {
636  *exceptionThrown = true;
637  }
638  return szData;
639 }
640 #endif
641 
642 #ifdef Q_CC_BOR
643 typedef const char * __stdcall (*QtPluginQueryVerificationDataFunction)();
644 #else
645 typedef const char * (*QtPluginQueryVerificationDataFunction)();
646 #endif
647 
648 bool qt_get_verificationdata(QtPluginQueryVerificationDataFunction pfn, uint *qt_version, bool *debug, QByteArray *key, bool *exceptionThrown)
649 {
650  *exceptionThrown = false;
651  const char *szData = 0;
652  if (!pfn)
653  return false;
654 #ifdef QT_USE_MS_STD_EXCEPTION
655  szData = qt_try_versioninfo((void *)pfn, exceptionThrown);
656  if (*exceptionThrown)
657  return false;
658 #else
659  szData = pfn();
660 #endif
661 
662 #ifdef QT_NO_PLUGIN_CHECK
663  return true;
664 #else
665  return qt_parse_pattern(szData, qt_version, debug, key);
666 #endif
667 }
668 
670 {
671  errorString.clear();
673  return pluginState == IsAPlugin;
674 
675 #ifndef QT_NO_PLUGIN_CHECK
676  bool debug = !QLIBRARY_AS_DEBUG;
677  QByteArray key;
678  bool success = false;
679 
680 #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
681  if (fileName.endsWith(QLatin1String(".debug"))) {
682  // refuse to load a file that ends in .debug
683  // these are the debug symbols from the libraries
684  // the problem is that they are valid shared library files
685  // and dlopen is known to crash while opening them
686 
687  // pretend we didn't see the file
688  errorString = QLibrary::tr("The shared library was not found.");
690  return false;
691  }
692 #endif
693 
694  QFileInfo fileinfo(fileName);
695 
696 #ifndef QT_NO_DATESTRING
698 #endif
699  QString regkey = QString::fromLatin1("Qt Plugin Cache %1.%2.%3/%4")
700  .arg((QT_VERSION & 0xff0000) >> 16)
701  .arg((QT_VERSION & 0xff00) >> 8)
702  .arg(QLIBRARY_AS_DEBUG ? QLatin1String("debug") : QLatin1String("false"))
703  .arg(fileName);
704 #ifdef Q_WS_MAC
705  // On Mac, add the application arch to the reg key in order to
706  // cache plugin information separately for each arch. This prevents
707  // Qt from wrongly caching plugin load failures when the archs
708  // don't match.
709 #if defined(__x86_64__)
710  regkey += QLatin1String("-x86_64");
711 #elif defined(__i386__)
712  regkey += QLatin1String("-i386");
713 #elif defined(__ppc64__)
714  regkey += QLatin1String("-ppc64");
715 #elif defined(__ppc__)
716  regkey += QLatin1String("-ppc");
717 #endif
718 #endif // Q_WS_MAC
719 
720  QStringList reg;
721 #ifndef QT_NO_SETTINGS
722  if (!settings) {
724  }
725  reg = settings->value(regkey).toStringList();
726 #endif
727  if (reg.count() == 4 && lastModified == reg.at(3)) {
728  qt_version = reg.at(0).toUInt(0, 16);
729  debug = bool(reg.at(1).toInt());
730  key = reg.at(2).toLatin1();
731  success = qt_version != 0;
732  } else {
733 #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_SYMBIAN)
734  if (!pHnd) {
735  // use unix shortcut to avoid loading the library
736  success = qt_unix_query(fileName, &qt_version, &debug, &key, this);
737  } else
738 #endif
739  {
740  bool retryLoadLibrary = false; // Only used on Windows with MS compiler.(false in other cases)
741  do {
742  bool temporary_load = false;
743 #ifdef Q_OS_WIN
744  HMODULE hTempModule = 0;
745 #endif
746  if (!pHnd) {
747 #ifdef Q_OS_WIN
748  DWORD dwFlags = (retryLoadLibrary) ? 0: DONT_RESOLVE_DLL_REFERENCES;
749  //avoid 'Bad Image' message box
751  hTempModule = ::LoadLibraryEx((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, dwFlags);
752  SetErrorMode(oldmode);
753 #else
754 # if defined(Q_OS_SYMBIAN)
755  //Guard against accidentally trying to load non-plugin libraries by making sure the stub exists
756  if (fileinfo.exists())
757 # endif
758  temporary_load = load_sys();
759 #endif
760  }
761 #ifdef Q_OS_WIN
762  QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = hTempModule ? (QtPluginQueryVerificationDataFunction)
763 #ifdef Q_OS_WINCE
764  ::GetProcAddress(hTempModule, L"qt_plugin_query_verification_data")
765 #else
766  ::GetProcAddress(hTempModule, "qt_plugin_query_verification_data")
767 #endif
768  : (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
769 #else
770  QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = NULL;
771 # if defined(Q_OS_SYMBIAN)
772  if (temporary_load) {
773  qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
774  // If resolving with function name failed (i.e. not STDDLL), try resolving using known ordinal
775  if (!qtPluginQueryVerificationDataFunction)
776  qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("1");
777  }
778 # else
779  qtPluginQueryVerificationDataFunction = (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data");
780 # endif
781 #endif
782  bool exceptionThrown = false;
783  bool ret = qt_get_verificationdata(qtPluginQueryVerificationDataFunction,
784  &qt_version, &debug, &key, &exceptionThrown);
785  if (!exceptionThrown) {
786  if (!ret) {
787  qt_version = 0;
788  key = "unknown";
789  if (temporary_load)
790  unload_sys();
791  } else {
792  success = true;
793  }
794  retryLoadLibrary = false;
795  }
796 #ifdef QT_USE_MS_STD_EXCEPTION
797  else {
798  // An exception was thrown when calling qt_plugin_query_verification_data().
799  // This usually happens when plugin is compiled with the /clr compiler flag,
800  // & will only work if the dependencies are loaded & DLLMain() is called.
801  // LoadLibrary() will do this, try once with this & if it fails don't load.
802  retryLoadLibrary = !retryLoadLibrary;
803  }
804 #endif
805 #ifdef Q_OS_WIN
806  if (hTempModule) {
807  BOOL ok = ::FreeLibrary(hTempModule);
808  if (ok) {
809  hTempModule = 0;
810  }
811 
812  }
813 #endif
814  } while(retryLoadLibrary); // Will be 'false' in all cases other than when an
815  // exception is thrown(will happen only when using a MS compiler)
816  }
817 
818  // Qt 4.5 compatibility: stl doesn't affect binary compatibility
819  key.replace(" no-stl", "");
820 
821 #ifndef QT_NO_SETTINGS
822  QStringList queried;
823  queried << QString::number(qt_version,16)
824  << QString::number((int)debug)
825  << QLatin1String(key)
826  << lastModified;
827  settings->setValue(regkey, queried);
828 #endif
829  }
830 
831  if (!success) {
832  if (errorString.isEmpty()){
833  if (fileName.isEmpty())
834  errorString = QLibrary::tr("The shared library was not found.");
835  else
836  errorString = QLibrary::tr("The file '%1' is not a valid Qt plugin.").arg(fileName);
837  }
838  return false;
839  }
840 
841  pluginState = IsNotAPlugin; // be pessimistic
842 
843  if ((qt_version & 0x00ff00) > (QT_VERSION & 0x00ff00) || (qt_version & 0xff0000) != (QT_VERSION & 0xff0000)) {
844  if (qt_debug_component()) {
845  qWarning("In %s:\n"
846  " Plugin uses incompatible Qt library (%d.%d.%d) [%s]",
847  (const char*) QFile::encodeName(fileName),
848  (qt_version&0xff0000) >> 16, (qt_version&0xff00) >> 8, qt_version&0xff,
849  debug ? "debug" : "release");
850  }
851  errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5]")
852  .arg(fileName)
853  .arg((qt_version&0xff0000) >> 16)
854  .arg((qt_version&0xff00) >> 8)
855  .arg(qt_version&0xff)
856  .arg(debug ? QLatin1String("debug") : QLatin1String("release"));
857  } else if (key != QT_BUILD_KEY
858  // we may have some compatibility keys, try them too:
859 #ifdef QT_BUILD_KEY_COMPAT
860  && key != QT_BUILD_KEY_COMPAT
861 #endif
862 #ifdef QT_BUILD_KEY_COMPAT2
863  && key != QT_BUILD_KEY_COMPAT2
864 #endif
865 #ifdef QT_BUILD_KEY_COMPAT3
866  && key != QT_BUILD_KEY_COMPAT3
867 #endif
868  ) {
869  if (qt_debug_component()) {
870  qWarning("In %s:\n"
871  " Plugin uses incompatible Qt library\n"
872  " expected build key \"%s\", got \"%s\"",
873  (const char*) QFile::encodeName(fileName),
874  QT_BUILD_KEY,
875  key.isEmpty() ? "<null>" : (const char *) key);
876  }
877  errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library."
878  " Expected build key \"%2\", got \"%3\"")
879  .arg(fileName)
881  .arg(key.isEmpty() ? QLatin1String("<null>") : QLatin1String((const char *) key));
882 #ifndef QT_NO_DEBUG_PLUGIN_CHECK
883  } else if(debug != QLIBRARY_AS_DEBUG) {
884  //don't issue a qWarning since we will hopefully find a non-debug? --Sam
885  errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library."
886  " (Cannot mix debug and release libraries.)").arg(fileName);
887 #endif
888  } else {
890  }
891 
892  return pluginState == IsAPlugin;
893 #else
894  Q_UNUSED(settings);
895  return pluginState == MightBeAPlugin;
896 #endif
897 }
898 
910 {
911  if (!d)
912  return false;
913  if (did_load)
914  return d->pHnd;
915  did_load = true;
916  return d->load();
917 }
918 
935 {
936  if (did_load) {
937  did_load = false;
938  return d->unload();
939  }
940  return false;
941 }
942 
948 bool QLibrary::isLoaded() const
949 {
950  return d && d->pHnd;
951 }
952 
953 
958  :QObject(parent), d(0), did_load(false)
959 {
960 }
961 
962 
975  :QObject(parent), d(0), did_load(false)
976 {
977  setFileName(fileName);
978 }
979 
980 
994  :QObject(parent), d(0), did_load(false)
995 {
996  setFileNameAndVersion(fileName, verNum);
997 }
998 
1012  :QObject(parent), d(0), did_load(false)
1013 {
1014  setFileNameAndVersion(fileName, version);
1015 }
1016 
1026 {
1027  if (d)
1028  d->release();
1029 }
1030 
1031 
1059 {
1060  QLibrary::LoadHints lh;
1061  if (d) {
1062  lh = d->loadHints;
1063  d->release();
1064  d = 0;
1065  did_load = false;
1066  }
1067  d = QLibraryPrivate::findOrCreate(fileName);
1068  d->loadHints = lh;
1069 }
1070 
1072 {
1073  if (d)
1075  return QString();
1076 }
1077 
1093 {
1094  QLibrary::LoadHints lh;
1095  if (d) {
1096  lh = d->loadHints;
1097  d->release();
1098  d = 0;
1099  did_load = false;
1100  }
1101  d = QLibraryPrivate::findOrCreate(fileName, verNum >= 0 ? QString::number(verNum) : QString());
1102  d->loadHints = lh;
1103 }
1104 
1120 {
1121  QLibrary::LoadHints lh;
1122  if (d) {
1123  lh = d->loadHints;
1124  d->release();
1125  d = 0;
1126  did_load = false;
1127  }
1128  d = QLibraryPrivate::findOrCreate(fileName, version);
1129  d->loadHints = lh;
1130 }
1131 
1155 void *QLibrary::resolve(const char *symbol)
1156 {
1157  if (!isLoaded() && !load())
1158  return 0;
1159  return d->resolve(symbol);
1160 }
1161 
1181 void *QLibrary::resolve(const QString &fileName, const char *symbol)
1182 {
1183  QLibrary library(fileName);
1184  return library.resolve(symbol);
1185 }
1186 
1207 void *QLibrary::resolve(const QString &fileName, int verNum, const char *symbol)
1208 {
1209  QLibrary library(fileName, verNum);
1210  return library.resolve(symbol);
1211 }
1212 
1234 void *QLibrary::resolve(const QString &fileName, const QString &version, const char *symbol)
1235 {
1236  QLibrary library(fileName, version);
1237  return library.resolve(symbol);
1238 }
1239 
1268 {
1269  return (!d || d->errorString.isEmpty()) ? tr("Unknown error") : d->errorString;
1270 }
1271 
1304 void QLibrary::setLoadHints(LoadHints hints)
1305 {
1306  if (!d) {
1307  d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr
1308  d->errorString.clear();
1309  }
1310  d->loadHints = hints;
1311 }
1312 
1313 QLibrary::LoadHints QLibrary::loadHints() const
1314 {
1315  return d ? d->loadHints : (QLibrary::LoadHints)0;
1316 }
1317 
1318 /* Internal, for debugging */
1320 {
1321  static int debug_env = -1;
1322  if (debug_env == -1)
1323  debug_env = QT_PREPEND_NAMESPACE(qgetenv)("QT_DEBUG_PLUGINS").toInt();
1324 
1325  return debug_env != 0;
1326 }
1327 
1329 
1330 #endif // QT_NO_LIBRARY
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:6448
double d
Definition: qnumeric_p.h:62
LoadHints loadHints() const
QString qt_error_string(int errorCode)
Definition: qglobal.cpp:2600
bool isPlugin(QSettings *settings=0)
Definition: qlibrary.cpp:669
void setValue(const QString &key, const QVariant &value)
Sets the value of setting key to value.
Definition: qsettings.cpp:3328
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
void setFileNameAndVersion(const QString &fileName, int verNum)
Sets the fileName property and major version number to fileName and versionNumber respectively...
Definition: qlibrary.cpp:1092
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Returns the value for setting key.
Definition: qsettings.cpp:3460
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
#define QLIBRARY_AS_DEBUG
Definition: qlibrary.cpp:72
The QMutex class provides access serialization between threads.
Definition: qmutex.h:60
bool unload()
Unloads the library and returns true if the library could be unloaded; otherwise returns false...
Definition: qlibrary.cpp:934
const char * fields
Definition: qlibrary.cpp:191
LibraryMap libraryMap
Definition: qlibrary.cpp:421
int toInt(bool *ok=0, int base=10) const
Returns the string converted to an int using base base, which is 10 by default and must be between 2 ...
Definition: qstring.cpp:6090
QVector< T > & fill(const T &t, int size=-1)
Assigns value to all items in the vector.
Definition: qvector.h:665
bool open(OpenMode flags)
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition: qfile.cpp:1064
QWeakPointer< QObject > inst
Definition: qlibrary_p.h:94
The QSettings class provides persistent platform-independent application settings.
Definition: qsettings.h:73
static QLibraryPrivate * findOrCreate(const QString &fileName, const QString &version=QString())
Definition: qlibrary.cpp:438
QVector< const char * > results
Definition: qlibrary.cpp:194
#define at(className, varName)
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
QString errorString() const
Returns a human-readable description of the last device error that occurred.
Definition: qiodevice.cpp:1671
QLibraryPrivate(const QString &canonicalFileName, const QString &version)
Definition: qlibrary.cpp:433
QtPluginInstanceFunction instance
Definition: qlibrary_p.h:95
QString lastModified
Definition: qlibrary_p.h:97
#define SEM_FAILCRITICALERRORS
QLibrary(QObject *parent=0)
Constructs a library with the given parent.
Definition: qlibrary.cpp:957
QString completeSuffix() const
Returns the complete suffix of the file.
Definition: qfileinfo.cpp:811
static QString tr(const char *sourceText, const char *comment=0, int n=-1)
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
bool exists() const
Returns true if the file exists; otherwise returns false.
Definition: qfileinfo.cpp:675
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
bool ref()
Atomically increments the value of this QAtomicInt.
void * resolve(const char *symbol)
Returns the address of the exported symbol symbol.
Definition: qlibrary.cpp:1155
void * resolve(const char *)
Definition: qlibrary.cpp:459
The QString class provides a Unicode character string.
Definition: qstring.h:83
bool isLoaded() const
Returns true if the library is loaded; otherwise returns false.
Definition: qlibrary.cpp:948
QAtomicInt libraryRefCount
Definition: qlibrary_p.h:113
void setFileName(const QString &fileName)
Definition: qlibrary.cpp:1058
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QVector class is a template class that provides a dynamic array.
Definition: qdatastream.h:64
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
bool qt_get_verificationdata(QtPluginQueryVerificationDataFunction pfn, uint *qt_version, bool *debug, QByteArray *key, bool *exceptionThrown)
Definition: qlibrary.cpp:648
T * data() const
#define QT_BUILD_KEY
Definition: qglobal.h:1254
QString toString(Qt::DateFormat f=Qt::TextDate) const
Returns the datetime as a string in the format given.
Definition: qdatetime.cpp:2628
static bool isLibrary(const QString &fileName)
Returns true if fileName has a valid suffix for a loadable library; otherwise returns false...
Definition: qlibrary.cpp:559
QStringList toStringList() const
Returns the variant as a QStringList if the variant has type() StringList, String ...
Definition: qvariant.cpp:2259
int indexOf(const QRegExp &rx, int from=0) const
Returns the index position of the first exact match of rx in the list, searching forward from index p...
Definition: qstringlist.h:195
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
QObject *(* QtPluginInstanceFunction)()
Definition: qplugin.h:62
enum QLibraryPrivate::@42 pluginState
QString fileName
Definition: qlibrary_p.h:83
~QLibrary()
Destroys the QLibrary object.
Definition: qlibrary.cpp:1025
#define Q_GLOBAL_STATIC(TYPE, NAME)
Declares a global static variable with the given type and name.
Definition: qglobal.h:1968
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
bool deref()
Atomically decrements the value of this QAtomicInt.
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
static int toInt(const QByteArray &str)
Definition: generator.cpp:167
#define QT_PREPEND_NAMESPACE(name)
This macro qualifies identifier with the full namespace.
Definition: qglobal.h:87
Q_CORE_EXPORT void qWarning(const char *,...)
void * resolve_sys(const char *)
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
static LibraryMap * libraryMap()
Definition: qlibrary.cpp:427
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
unsigned long ulong
Definition: qglobal.h:997
HINSTANCE pHnd
Definition: qlibrary_p.h:81
qint64 size() const
Returns the size of the file.
Definition: qfile.cpp:1707
static QSettings * trolltechConf()
#define SetErrorMode(a)
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
qt_token_info(const char *f, const ulong fc)
Definition: qlibrary.cpp:184
uint qstrlen(const char *str)
Definition: qbytearray.h:79
QLibraryPrivate * d
Definition: qlibrary.h:108
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
QString arg(qlonglong a, int fieldwidth=0, int base=10, const QChar &fillChar=QLatin1Char(' ')) const Q_REQUIRED_RESULT
Definition: qstring.cpp:7186
QString errorString
Definition: qlibrary_p.h:99
Definition: qbezier.cpp:259
bool load()
Loads the library and returns true if the library was loaded successfully; otherwise returns false...
Definition: qlibrary.cpp:909
The QFile class provides an interface for reading from and writing to files.
Definition: qfile.h:65
QVector< ulong > lengths
Definition: qlibrary.cpp:195
QSet< QLibraryPrivate * > loadedLibs
Definition: qlibrary.cpp:422
const ulong field_count
Definition: qlibrary.cpp:192
void clear()
Clears the contents of the string and makes it empty.
Definition: qstring.h:723
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
iterator insert(const Key &key, const T &value)
Inserts a new item with the key key and a value of value.
Definition: qmap.h:559
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
int key
QByteArray suffix
int qstrncmp(const char *str1, const char *str2, uint len)
Definition: qbytearray.h:101
uint toUInt(bool *ok=0, int base=10) const
Returns the string converted to an unsigned int using base base, which is 10 by default and must be b...
Definition: qstring.cpp:6120
#define SEM_NOOPENFILEERRORBOX
QByteArray readAll()
Reads all available data from the device, and returns it as a QByteArray.
Definition: qiodevice.cpp:1025
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
void setLoadHints(LoadHints hints)
Definition: qlibrary.cpp:1304
static QByteArray encodeName(const QString &fileName)
By default, this function converts fileName to the local 8-bit encoding determined by the user&#39;s loca...
Definition: qfile.cpp:528
bool loadPlugin()
Definition: qlibrary.cpp:517
QByteArray & replace(int index, int len, const char *s)
This is an overloaded member function, provided for convenience. It differs from the above function o...
T take(const Key &key)
Removes the item with the key key from the map and returns the value associated with it...
Definition: qmap.h:692
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
QStringList split(const QString &sep, SplitBehavior behavior=KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const Q_REQUIRED_RESULT
Splits the string into substrings wherever sep occurs, and returns the list of those strings...
Definition: qstring.cpp:6526
bool did_load
Definition: qlibrary.h:109
uchar * map(qint64 offset, qint64 size, MemoryMapFlags flags=NoOptions)
Maps size bytes of the file into memory starting at offset.
Definition: qfile.cpp:1460
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:3796
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:60
static QString toNativeSeparators(const QString &pathName)
Returns pathName with the &#39;/&#39; separators converted to separators that are appropriate for the underly...
Definition: qdir.cpp:812
virtual void close()
Calls QFile::flush() and closes the file.
Definition: qfile.cpp:1680
uint toUInt(bool *ok=0, int base=10) const
Returns the byte array converted to an {unsigned int} using base base, which is 10 by default and mus...
QLibrary::LoadHints loadHints
Definition: qlibrary_p.h:100
#define qPrintable(string)
Definition: qglobal.h:1750
QString qualifiedFileName
Definition: qlibrary_p.h:83
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
static bool qt_parse_pattern(const char *s, uint *version, bool *debug, QByteArray *key)
Definition: qlibrary.cpp:262
static QString fileName(const QString &fileUrl)
static int qt_tokenize(const char *s, ulong s_len, ulong *advance, qt_token_info &token_info)
Definition: qlibrary.cpp:204
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
bool qt_debug_component()
Definition: qlibrary.cpp:1319
QMap< QString, QLibraryPrivate * > LibraryMap
Definition: qlibrary.cpp:418
QString errorString() const
Returns a text string with the description of the last error that occurred.
Definition: qlibrary.cpp:1267
const char *(* QtPluginQueryVerificationDataFunction)()
Definition: qlibrary.cpp:645
int errno
The QLibrary class loads shared libraries at runtime.
Definition: qlibrary.h:62
QString fileName() const
QAtomicInt libraryUnloadCount
Definition: qlibrary_p.h:114
#define QT_VERSION
This macro expands a numeric value of the form 0xMMNNPP (MM = major, NN = minor, PP = patch) that spe...
Definition: qglobal.h:51
QDateTime lastModified() const
Returns the date and time when the file was last modified.
Definition: qfileinfo.cpp:1296