From 6e38027b4ff72ac177f91e34f03326a92f924d77 Mon Sep 17 00:00:00 2001 From: dt <qtc-committer@nokia.com> Date: Mon, 27 Jul 2009 18:27:29 +0200 Subject: [PATCH] The patched pluginloader was unused. Thiago changed the way buildkeys are parsed, thus to reintroduce the patched plugin loader, the changes to the build parser must be ported to the patched plugin loader. Or the patches to make the plugin loader faster to the current state of the qt plugin loader. --- .../extensionsystem/patchedpluginloader.cpp | 1148 ----------------- 1 file changed, 1148 deletions(-) delete mode 100644 src/libs/extensionsystem/patchedpluginloader.cpp diff --git a/src/libs/extensionsystem/patchedpluginloader.cpp b/src/libs/extensionsystem/patchedpluginloader.cpp deleted file mode 100644 index 7898c91d730..00000000000 --- a/src/libs/extensionsystem/patchedpluginloader.cpp +++ /dev/null @@ -1,1148 +0,0 @@ - -#ifdef Q_WS_WIN -# include "QtCore/qt_windows.h" -#endif -#include "QtCore/qlibrary.h" -#include "QtCore/qpointer.h" -#include "QtCore/qstringlist.h" -#include "QtCore/qplugin.h" - - -#include "qplatformdefs.h" - -#include "qplugin.h" -#include "qpluginloader.h" -#include <qfileinfo.h> -#include "qdebug.h" - -#include "qplatformdefs.h" -#include "qlibrary.h" - -#include <qstringlist.h> -#include <qfile.h> -#include <qfileinfo.h> -#include <qmutex.h> -#include <qmap.h> -#include <qsettings.h> -#include <qdatetime.h> -#include <qcoreapplication.h> -#include <qvector.h> -#include <qdir.h> - - -#ifdef Q_OS_MAC -# include <private/qcore_mac_p.h> -#endif -#ifndef NO_ERRNO_H -#include <errno.h> -#endif // NO_ERROR_H - -#include "qplatformdefs.h" - -#ifdef Q_OS_MAC -# include <private/qcore_mac_p.h> -#endif - -#if defined(QT_AOUT_UNDERSCORE) -#include <string.h> -#endif - - -#if !defined(QT_HPUX_LD) -#include <dlfcn.h> -#endif - -QT_BEGIN_NAMESPACE - -bool qt_debug_component(); - -class PatchedLibraryPrivate -{ -public: - -#ifdef Q_WS_WIN - HINSTANCE -#else - void * -#endif - pHnd; - - QString fileName, qualifiedFileName; - QString fullVersion; - - bool load(); - bool loadPlugin(); // loads and resolves instance - bool unload(); - void release(); - void *resolve(const char *); - - static PatchedLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString()); - - QtPluginInstanceFunction instance; - uint qt_version; - QString lastModified; - - QString errorString; - QLibrary::LoadHints loadHints; - - bool isPlugin(QSettings *settings = 0); - - -private: - explicit PatchedLibraryPrivate(const QString &canonicalFileName, const QString &version); - ~PatchedLibraryPrivate(); - - bool load_sys(); - bool unload_sys(); - void *resolve_sys(const char *); - - QAtomicInt libraryRefCount; - QAtomicInt libraryUnloadCount; - - enum {IsAPlugin, IsNotAPlugin, MightBeAPlugin } pluginState; - friend class PatchedLibraryPrivateHasFriends; -}; - -class PatchedPluginLoader -{ - Q_PROPERTY(QString fileName READ fileName WRITE setFileName) - Q_PROPERTY(QLibrary::LoadHints loadHints READ loadHints WRITE setLoadHints) -public: - explicit PatchedPluginLoader(QObject *parent = 0); - explicit PatchedPluginLoader(const QString &fileName, QObject *parent = 0); - ~PatchedPluginLoader(); - - QObject *instance(); - - bool load(); - bool unload(); - bool isLoaded() const; - - void setFileName(const QString &fileName); - QString fileName() const; - - QString errorString() const; - - void setLoadHints(QLibrary::LoadHints loadHints); - QLibrary::LoadHints loadHints() const; - -private: - PatchedLibraryPrivate *d; - bool did_load; - Q_DISABLE_COPY(PatchedPluginLoader) -}; - -//#define QT_DEBUG_COMPONENT - -#ifdef QT_NO_DEBUG -# define QLIBRARY_AS_DEBUG false -#else -# define QLIBRARY_AS_DEBUG true -#endif - -#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) -// We don't use separate debug and release libs on UNIX, so we want -// to allow loading plugins, regardless of how they were built. -# define QT_NO_DEBUG_PLUGIN_CHECK -#endif - -Q_GLOBAL_STATIC(QMutex, patched_qt_library_mutex) - - -#ifndef QT_NO_PLUGIN_CHECK -struct qt_token_info -{ - qt_token_info(const char *f, const ulong fc) - : fields(f), field_count(fc), results(fc), lengths(fc) - { - results.fill(0); - lengths.fill(0); - } - - const char *fields; - const ulong field_count; - - QVector<const char *> results; - QVector<ulong> lengths; -}; - -/* - return values: - 1 parse ok - 0 eos - -1 parse error -*/ -static int qt_tokenize(const char *s, ulong s_len, ulong *advance, - qt_token_info &token_info) -{ - ulong pos = 0, field = 0, fieldlen = 0; - char current; - int ret = -1; - *advance = 0; - for (;;) { - current = s[pos]; - - // next char - ++pos; - ++fieldlen; - ++*advance; - - if (! current || pos == s_len + 1) { - // save result - token_info.results[(int)field] = s; - token_info.lengths[(int)field] = fieldlen - 1; - - // end of string - ret = 0; - break; - } - - if (current == token_info.fields[field]) { - // save result - token_info.results[(int)field] = s; - token_info.lengths[(int)field] = fieldlen - 1; - - // end of field - fieldlen = 0; - ++field; - if (field == token_info.field_count - 1) { - // parse ok - ret = 1; - } - if (field == token_info.field_count) { - // done parsing - break; - } - - // reset string and its length - s = s + pos; - s_len -= pos; - pos = 0; - } - } - - return ret; -} - -/* - returns true if the string s was correctly parsed, false otherwise. -*/ -static bool qt_parse_pattern(const char *s, uint *version, bool *debug, QByteArray *key) -{ - bool ret = true; - - qt_token_info pinfo("=\n", 2); - int parse; - ulong at = 0, advance, parselen = qstrlen(s); - do { - parse = qt_tokenize(s + at, parselen, &advance, pinfo); - if (parse == -1) { - ret = false; - break; - } - - at += advance; - parselen -= advance; - - if (qstrncmp("version", pinfo.results[0], pinfo.lengths[0]) == 0) { - // parse version string - qt_token_info pinfo2("..-", 3); - if (qt_tokenize(pinfo.results[1], pinfo.lengths[1], - &advance, pinfo2) != -1) { - QByteArray m(pinfo2.results[0], pinfo2.lengths[0]); - QByteArray n(pinfo2.results[1], pinfo2.lengths[1]); - QByteArray p(pinfo2.results[2], pinfo2.lengths[2]); - *version = (m.toUInt() << 16) | (n.toUInt() << 8) | p.toUInt(); - } else { - ret = false; - break; - } - } else if (qstrncmp("debug", pinfo.results[0], pinfo.lengths[0]) == 0) { - *debug = qstrncmp("true", pinfo.results[1], pinfo.lengths[1]) == 0; - } else if (qstrncmp("buildkey", pinfo.results[0], - pinfo.lengths[0]) == 0){ - // save buildkey - *key = QByteArray(pinfo.results[1], pinfo.lengths[1]); - } - } while (parse == 1 && parselen > 0); - - return ret; -} -#endif // QT_NO_PLUGIN_CHECK - -#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(QT_NO_PLUGIN_CHECK) - -#if defined(Q_OS_FREEBSD) || defined(Q_OS_LINUX) -# define USE_MMAP -QT_BEGIN_INCLUDE_NAMESPACE -# include <sys/types.h> -# include <sys/mman.h> -QT_END_INCLUDE_NAMESPACE -#endif // Q_OS_FREEBSD || Q_OS_LINUX - -static long qt_find_pattern(const char *s, ulong s_len, - const char *pattern, ulong p_len) -{ - /* - we search from the end of the file because on the supported - systems, the read-only data/text segments are placed at the end - of the file. HOWEVER, when building with debugging enabled, all - the debug symbols are placed AFTER the data/text segments. - - what does this mean? when building in release mode, the search - is fast because the data we are looking for is at the end of the - file... when building in debug mode, the search is slower - because we have to skip over all the debugging symbols first - */ - - if (! s || ! pattern || p_len > s_len) return -1; - ulong i, hs = 0, hp = 0, delta = s_len - p_len; - - for (i = 0; i < p_len; ++i) { - hs += s[delta + i]; - hp += pattern[i]; - } - i = delta; - for (;;) { - if (hs == hp && qstrncmp(s + i, pattern, p_len) == 0) - return i; - if (i == 0) - break; - --i; - hs -= s[i + p_len]; - hs += s[i]; - } - - return -1; -} - -/* - This opens the specified library, mmaps it into memory, and searches - for the QT_PLUGIN_VERIFICATION_DATA. The advantage of this approach is that - we can get the verification data without have to actually load the library. - This lets us detect mismatches more safely. - - Returns false if version/key information is not present, or if the - information could not be read. - Returns true if version/key information is present and successfully read. -*/ -static bool qt_unix_query(const QString &library, uint *version, bool *debug, QByteArray *key, PatchedLibraryPrivate *lib = 0) -{ - QFile file(library); - if (!file.open(QIODevice::ReadOnly)) { - if (lib) - lib->errorString = file.errorString(); - if (qt_debug_component()) { - qWarning("%s: %s", (const char*) QFile::encodeName(library), - qPrintable(qt_error_string(errno))); - } - return false; - } - - QByteArray data; - char *filedata = 0; - ulong fdlen = 0; - -#ifdef USE_MMAP - char *mapaddr = 0; - size_t maplen = file.size(); - mapaddr = (char *) mmap(mapaddr, maplen, PROT_READ, MAP_PRIVATE, file.handle(), 0); - if (mapaddr != MAP_FAILED) { - // mmap succeeded - filedata = mapaddr; - fdlen = maplen; - } else { - // mmap failed - if (qt_debug_component()) { - qWarning("mmap: %s", qPrintable(qt_error_string(errno))); - } - if (lib) - lib->errorString = QLibrary::tr("Could not mmap '%1': %2") - .arg(library) - .arg(qt_error_string()); -#endif // USE_MMAP - // try reading the data into memory instead - data = file.readAll(); - filedata = data.data(); - fdlen = data.size(); -#ifdef USE_MMAP - } -#endif // USE_MMAP - - // verify that the pattern is present in the plugin - const char pattern[] = "pattern=QT_PLUGIN_VERIFICATION_DATA"; - const ulong plen = qstrlen(pattern); - long pos = qt_find_pattern(filedata, fdlen, pattern, plen); - - bool ret = false; - if (pos >= 0) - ret = qt_parse_pattern(filedata + pos, version, debug, key); - - if (!ret && lib) - lib->errorString = QLibrary::tr("Plugin verification data mismatch in '%1'").arg(library); -#ifdef USE_MMAP - if (mapaddr != MAP_FAILED && munmap(mapaddr, maplen) != 0) { - if (qt_debug_component()) - qWarning("munmap: %s", qPrintable(qt_error_string(errno))); - if (lib) - lib->errorString = QLibrary::tr("Could not unmap '%1': %2") - .arg(library) - .arg( qt_error_string() ); - } -#endif // USE_MMAP - - file.close(); - return ret; -} - -#endif // Q_OS_UNIX && !Q_OS_MAC && !defined(QT_NO_PLUGIN_CHECK) - -typedef QMap<QString, PatchedLibraryPrivate*> LibraryMap; -Q_GLOBAL_STATIC(LibraryMap, libraryMap) - -PatchedLibraryPrivate::PatchedLibraryPrivate(const QString &canonicalFileName, const QString &version) - :pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0), qt_version(0), - libraryRefCount(1), libraryUnloadCount(0), pluginState(MightBeAPlugin) -{ libraryMap()->insert(canonicalFileName, this); } - -PatchedLibraryPrivate *PatchedLibraryPrivate::findOrCreate(const QString &fileName, const QString &version) -{ - QMutexLocker locker(patched_qt_library_mutex()); - if (PatchedLibraryPrivate *lib = libraryMap()->value(fileName)) { - lib->libraryRefCount.ref(); - return lib; - } - - return new PatchedLibraryPrivate(fileName, version); -} - -PatchedLibraryPrivate::~PatchedLibraryPrivate() -{ - LibraryMap * const map = libraryMap(); - if (map) { - PatchedLibraryPrivate *that = map->take(fileName); - Q_ASSERT(this == that); - Q_UNUSED(that) - } -} - -void *PatchedLibraryPrivate::resolve(const char *symbol) -{ - if (!pHnd) - return 0; - return resolve_sys(symbol); -} - - -bool PatchedLibraryPrivate::load() -{ - libraryUnloadCount.ref(); - if (pHnd) - return true; - if (fileName.isEmpty()) - return false; - return load_sys(); -} - -bool PatchedLibraryPrivate::unload() -{ - if (!pHnd) - return false; - if (!libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to - if (instance) - delete instance(); - if (unload_sys()) { - instance = 0; - pHnd = 0; - } - } - - return (pHnd == 0); -} - -void PatchedLibraryPrivate::release() -{ - QMutexLocker locker(patched_qt_library_mutex()); - if (!libraryRefCount.deref()) - delete this; -} - -bool PatchedLibraryPrivate::loadPlugin() -{ - if (instance) { - libraryUnloadCount.ref(); - return true; - } - if (load()) { - instance = (QtPluginInstanceFunction)resolve("qt_plugin_instance"); - return instance; - } - return false; -} - -/*! - Returns true if \a fileName has a valid suffix for a loadable - library; otherwise returns false. - - \table - \header \i Platform \i Valid suffixes - \row \i Windows \i \c .dll - \row \i Unix/Linux \i \c .so - \row \i AIX \i \c .a - \row \i HP-UX \i \c .sl, \c .so (HP-UXi) - \row \i Mac OS X \i \c .dylib, \c .bundle, \c .so - \endtable - - Trailing versioning numbers on Unix are ignored. - */ -bool QLibrary::isLibrary(const QString &fileName) -{ -#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) - return fileName.endsWith(QLatin1String(".dll")); -#else - QString completeSuffix = QFileInfo(fileName).completeSuffix(); - if (completeSuffix.isEmpty()) - return false; - QStringList suffixes = completeSuffix.split(QLatin1Char('.')); -# if defined(Q_OS_DARWIN) - - // On Mac, libs look like libmylib.1.0.0.dylib - const QString lastSuffix = suffixes.at(suffixes.count() - 1); - const QString firstSuffix = suffixes.at(0); - - bool valid = (lastSuffix == QLatin1String("dylib") - || firstSuffix == QLatin1String("so") - || firstSuffix == QLatin1String("bundle")); - - return valid; -# else // Generic Unix - QStringList validSuffixList; - -# if defined(Q_OS_HPUX) -/* - See "HP-UX Linker and Libraries User's Guide", section "Link-time Differences between PA-RISC and IPF": - "In PA-RISC (PA-32 and PA-64) shared libraries are suffixed with .sl. In IPF (32-bit and 64-bit), - the shared libraries are suffixed with .so. For compatibility, the IPF linker also supports the .sl suffix." - */ - validSuffixList << QLatin1String("sl"); -# if defined __ia64 - validSuffixList << QLatin1String("so"); -# endif -# elif defined(Q_OS_AIX) - validSuffixList << QLatin1String("a") << QLatin1String("so"); -# elif defined(Q_OS_UNIX) - validSuffixList << QLatin1String("so"); -# endif - - // Examples of valid library names: - // libfoo.so - // libfoo.so.0 - // libfoo.so.0.3 - // libfoo-0.3.so - // libfoo-0.3.so.0.3.0 - - int suffix; - int suffixPos = -1; - for (suffix = 0; suffix < validSuffixList.count() && suffixPos == -1; ++suffix) - suffixPos = suffixes.indexOf(validSuffixList.at(suffix)); - - bool valid = suffixPos != -1; - for (int i = suffixPos + 1; i < suffixes.count() && valid; ++i) - if (i != suffixPos) - suffixes.at(i).toInt(&valid); - return valid; -# endif -#endif - -} - -bool PatchedLibraryPrivate::isPlugin(QSettings *settings) -{ - errorString.clear(); - if (pluginState != MightBeAPlugin) - return pluginState == IsAPlugin; - -#ifndef QT_NO_PLUGIN_CHECK - bool debug = !QLIBRARY_AS_DEBUG; - QByteArray key; - bool success = false; - - QFileInfo fileinfo(fileName); - -#ifndef QT_NO_DATESTRING - lastModified = fileinfo.lastModified().toString(Qt::ISODate); -#endif - QString regkey = QString::fromLatin1("Qt Plugin Cache %1.%2.%3/%4") - .arg((QT_VERSION & 0xff0000) >> 16) - .arg((QT_VERSION & 0xff00) >> 8) - .arg(QLIBRARY_AS_DEBUG ? QLatin1String("debug") : QLatin1String("false")) - .arg(fileName); - QStringList reg; -#ifndef QT_NO_SETTINGS - if (!settings) { - static QSettings *staticSettings = - new QSettings(QSettings::UserScope, QLatin1String("Trolltech")); - settings = staticSettings; - } - reg = settings->value(regkey).toStringList(); -#endif - if (reg.count() == 4 && lastModified == reg.at(3)) { - qt_version = reg.at(0).toUInt(0, 16); - debug = bool(reg.at(1).toInt()); - key = reg.at(2).toLatin1(); - success = qt_version != 0; - } else { -#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) - if (!pHnd) { - // use unix shortcut to avoid loading the library - success = qt_unix_query(fileName, &qt_version, &debug, &key, this); - } else -#endif - { - bool temporary_load = false; -#ifdef Q_OS_WIN - HMODULE hTempModule = 0; -#endif - if (!pHnd) { -#ifdef Q_OS_WIN - QT_WA({ - hTempModule = ::LoadLibraryExW((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, DONT_RESOLVE_DLL_REFERENCES); - } , { - temporary_load = load_sys(); - }); -#else - temporary_load = load_sys(); -#endif - } -# ifdef Q_CC_BOR - typedef const char * __stdcall (*QtPluginQueryVerificationDataFunction)(); -# else - typedef const char * (*QtPluginQueryVerificationDataFunction)(); -# endif -#ifdef Q_OS_WIN - QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = hTempModule - ? (QtPluginQueryVerificationDataFunction) -#ifdef Q_OS_WINCE - ::GetProcAddressW(hTempModule, L"qt_plugin_query_verification_data") -#else - ::GetProcAddress(hTempModule, "qt_plugin_query_verification_data") -#endif - : (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data"); -#else - QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = - (QtPluginQueryVerificationDataFunction) resolve("qt_plugin_query_verification_data"); -#endif - - if (!qtPluginQueryVerificationDataFunction - || !qt_parse_pattern(qtPluginQueryVerificationDataFunction(), &qt_version, &debug, &key)) { - qt_version = 0; - key = "unknown"; - if (temporary_load) - unload_sys(); - } else { - success = true; - } -#ifdef Q_OS_WIN - if (hTempModule) { - BOOL ok = ::FreeLibrary(hTempModule); - if (ok) { - hTempModule = 0; - } - - } -#endif - } - - QStringList queried; - queried << QString::number(qt_version,16) - << QString::number((int)debug) - << QLatin1String(key) - << lastModified; -#ifndef QT_NO_SETTINGS - settings->setValue(regkey, queried); -#endif - } - - if (!success) { - if (errorString.isEmpty()){ - if (fileName.isEmpty()) - errorString = QLibrary::tr("The shared library was not found."); - else - errorString = QLibrary::tr("The file '%1' is not a valid Qt plugin.").arg(fileName); - } - return false; - } - - pluginState = IsNotAPlugin; // be pessimistic - - if ((qt_version > QT_VERSION) || ((QT_VERSION & 0xff0000) > (qt_version & 0xff0000))) { - if (qt_debug_component()) { - qWarning("In %s:\n" - " Plugin uses incompatible Qt library (%d.%d.%d) [%s]", - (const char*) QFile::encodeName(fileName), - (qt_version&0xff0000) >> 16, (qt_version&0xff00) >> 8, qt_version&0xff, - debug ? "debug" : "release"); - } - errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5]") - .arg(fileName) - .arg((qt_version&0xff0000) >> 16) - .arg((qt_version&0xff00) >> 8) - .arg(qt_version&0xff) - .arg(debug ? QLatin1String("debug") : QLatin1String("release")); - } else if (key != QT_BUILD_KEY -#ifdef QT_BUILD_KEY_COMPAT - // be sure to load plugins using an older but compatible build key - && key != QT_BUILD_KEY_COMPAT -#endif - ) { - if (qt_debug_component()) { - qWarning("In %s:\n" - " Plugin uses incompatible Qt library\n" - " expected build key \"%s\", got \"%s\"", - (const char*) QFile::encodeName(fileName), - QT_BUILD_KEY, - key.isEmpty() ? "<null>" : (const char *) key); - } - errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library." - " Expected build key \"%2\", got \"%3\"") - .arg(fileName) - .arg(QLatin1String(QT_BUILD_KEY)) - .arg(key.isEmpty() ? QLatin1String("<null>") : QLatin1String((const char *) key)); -#ifndef QT_NO_DEBUG_PLUGIN_CHECK - } else if(debug != QLIBRARY_AS_DEBUG) { - //don't issue a qWarning since we will hopefully find a non-debug? --Sam - errorString = QLibrary::tr("The plugin '%1' uses incompatible Qt library." - " (Cannot mix debug and release libraries.)").arg(fileName); -#endif - } else { - pluginState = IsAPlugin; - } - - return pluginState == IsAPlugin; -#else - Q_UNUSED(settings) - return pluginState == MightBeAPlugin; -#endif -} - -/* Internal, for debugging */ -bool qt_debug_component() -{ -#if defined(QT_DEBUG_COMPONENT) - return true; //compatibility? -#else - static int debug_env = -1; - if (debug_env == -1) - debug_env = QT_PREPEND_NAMESPACE(qgetenv)("QT_DEBUG_PLUGINS").toInt(); - - return debug_env != 0; -#endif -} - -PatchedPluginLoader::PatchedPluginLoader(QObject *) - : d(0), did_load(false) -{ -} - -PatchedPluginLoader::PatchedPluginLoader(const QString &fileName, QObject *) - : d(0), did_load(false) -{ - setFileName(fileName); -} - -PatchedPluginLoader::~PatchedPluginLoader() -{ - if (d) - d->release(); -} - -QObject *PatchedPluginLoader::instance() -{ - if (!load()) - return 0; - if (d->instance) - return d->instance(); - return 0; -} - -bool PatchedPluginLoader::load() -{ - if (!d || d->fileName.isEmpty()) - return false; - if (did_load) - return d->pHnd && d->instance; - if (!d->isPlugin()) - return false; - did_load = true; - return d->loadPlugin(); -} - -bool PatchedPluginLoader::unload() -{ - if (did_load) { - did_load = false; - return d->unload(); - } - if (d) // Ouch - d->errorString = QLibrary::tr("The plugin was not loaded."); - return false; -} - -bool PatchedPluginLoader::isLoaded() const -{ - return d && d->pHnd && d->instance; -} - -void PatchedPluginLoader::setFileName(const QString &fileName) -{ -#if defined(QT_SHARED) - QLibrary::LoadHints lh; - if (d) { - lh = d->loadHints; - d->release(); - d = 0; - did_load = false; - } - QString fn = QFileInfo(fileName).canonicalFilePath(); - d = PatchedLibraryPrivate::findOrCreate(fn); - d->loadHints = lh; - if (fn.isEmpty()) - d->errorString = QLibrary::tr("The shared library was not found."); -#else - if (qt_debug_component()) { - qWarning("Cannot load %s into a statically linked Qt library.", - (const char*)QFile::encodeName(fileName)); - } - Q_UNUSED(fileName) -#endif -} - -QString PatchedPluginLoader::fileName() const -{ - if (d) - return d->fileName; - return QString(); -} - -QString PatchedPluginLoader::errorString() const -{ - return (!d || d->errorString.isEmpty()) ? QLibrary::tr("Unknown error") : d->errorString; -} - -void PatchedPluginLoader::setLoadHints(QLibrary::LoadHints loadHints) -{ - if (!d) { - d = PatchedLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr - d->errorString.clear(); - } - d->loadHints = loadHints; -} - -QLibrary::LoadHints PatchedPluginLoader::loadHints() const -{ - if (!d) { - PatchedPluginLoader *that = const_cast<PatchedPluginLoader *>(this); - that->d = PatchedLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr - that->d->errorString.clear(); - } - return d->loadHints; -} - - - - -#ifdef Q_OS_UNIX - - - -static QString qdlerror() -{ -#if !defined(QT_HPUX_LD) - const char *err = dlerror(); -#else - const char *err = strerror(errno); -#endif - return err ? QLatin1String("(")+QString::fromLocal8Bit(err) + QLatin1String(")"): QString(); -} - -bool PatchedLibraryPrivate::load_sys() -{ - QFileInfo fi(fileName); - QString path = fi.path(); - QString name = fi.fileName(); - if (path == QLatin1String(".") && !fileName.startsWith(path)) - path.clear(); - else - path += QLatin1Char('/'); - - // The first filename we want to attempt to load is the filename as the callee specified. - // Thus, the first attempt we do must be with an empty prefix and empty suffix. - QStringList suffixes(QLatin1String("")), prefixes(QLatin1String("")); - if (pluginState != IsAPlugin) { - prefixes << QLatin1String("lib"); -#if defined(Q_OS_HPUX) - // according to - // http://docs.hp.com/en/B2355-90968/linkerdifferencesiapa.htm - - // In PA-RISC (PA-32 and PA-64) shared libraries are suffixed - // with .sl. In IPF (32-bit and 64-bit), the shared libraries - // are suffixed with .so. For compatibility, the IPF linker - // also supports the .sl suffix. - - // But since we don't know if we are built on HPUX or HPUXi, - // we support both .sl (and .<version>) and .so suffixes but - // .so is preferred. -# if defined(__ia64) - if (!fullVersion.isEmpty()) { - suffixes << QString::fromLatin1(".so.%1").arg(fullVersion); - } else { - suffixes << QLatin1String(".so"); - } -# endif - if (!fullVersion.isEmpty()) { - suffixes << QString::fromLatin1(".sl.%1").arg(fullVersion); - suffixes << QString::fromLatin1(".%1").arg(fullVersion); - } else { - suffixes << QLatin1String(".sl"); - } -#elif defined(Q_OS_AIX) - suffixes << ".a"; -#else - if (!fullVersion.isEmpty()) { - suffixes << QString::fromLatin1(".so.%1").arg(fullVersion); - } else { - suffixes << QLatin1String(".so"); - } -#endif -# ifdef Q_OS_MAC - if (!fullVersion.isEmpty()) { - suffixes << QString::fromLatin1(".%1.bundle").arg(fullVersion); - suffixes << QString::fromLatin1(".%1.dylib").arg(fullVersion); - } else { - suffixes << QLatin1String(".bundle") << QLatin1String(".dylib"); - } -#endif - } - int dlFlags = 0; -#if defined(QT_HPUX_LD) - dlFlags = DYNAMIC_PATH | BIND_NONFATAL; - if (loadHints & QLibrary::ResolveAllSymbolsHint) { - dlFlags |= BIND_IMMEDIATE; - } else { - dlFlags |= BIND_DEFERRED; - } -#else - if (loadHints & QLibrary::ResolveAllSymbolsHint) { - dlFlags |= RTLD_NOW; - } else { - dlFlags |= RTLD_LAZY; - } - if (loadHints & QLibrary::ExportExternalSymbolsHint) { - dlFlags |= RTLD_GLOBAL; - } -#if !defined(Q_OS_CYGWIN) - else { -#if defined(Q_OS_MAC) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) -#endif - dlFlags |= RTLD_LOCAL; - } -#endif -#if defined(Q_OS_AIX) // Not sure if any other platform actually support this thing. - if (loadHints & QLibrary::LoadArchiveMemberHint) { - dlFlags |= RTLD_MEMBER; - } -#endif -#endif // QT_HPUX_LD - QString attempt; - bool retry = true; - for(int prefix = 0; retry && !pHnd && prefix < prefixes.size(); prefix++) { - for(int suffix = 0; retry && !pHnd && suffix < suffixes.size(); suffix++) { - if (!prefixes.at(prefix).isEmpty() && name.startsWith(prefixes.at(prefix))) - continue; - if (!suffixes.at(suffix).isEmpty() && name.endsWith(suffixes.at(suffix))) - continue; - if (loadHints & QLibrary::LoadArchiveMemberHint) { - attempt = name; - int lparen = attempt.indexOf(QLatin1Char('(')); - if (lparen == -1) - lparen = attempt.count(); - attempt = path + prefixes.at(prefix) + attempt.insert(lparen, suffixes.at(suffix)); - } else { - attempt = path + prefixes.at(prefix) + name + suffixes.at(suffix); - } -#if defined(QT_HPUX_LD) - pHnd = (void*)shl_load(QFile::encodeName(attempt), dlFlags, 0); -#else - pHnd = dlopen(QFile::encodeName(attempt), dlFlags); -#endif - if (!pHnd && fileName.startsWith(QLatin1Char('/')) && QFile::exists(attempt)) { - // We only want to continue if dlopen failed due to that the shared library did not exist. - // However, we are only able to apply this check for absolute filenames (since they are - // not influenced by the content of LD_LIBRARY_PATH, /etc/ld.so.cache, DT_RPATH etc...) - // This is all because dlerror is flawed and cannot tell us the reason why it failed. - retry = false; - } - } - } - -#ifdef Q_OS_MAC - if (!pHnd) { - if (CFBundleRef bundle = CFBundleGetBundleWithIdentifier(QCFString(fileName))) { - QCFType<CFURLRef> url = CFBundleCopyExecutableURL(bundle); - QCFString str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); - pHnd = dlopen(QFile::encodeName(str), dlFlags); - attempt = str; - } - } -# endif - if (!pHnd) { - errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qdlerror()); - } - if (pHnd) { - qualifiedFileName = attempt; - errorString.clear(); - } - return (pHnd != 0); -} - -bool PatchedLibraryPrivate::unload_sys() -{ -#if defined(QT_HPUX_LD) - if (shl_unload((shl_t)pHnd)) { -#else - if (dlclose(pHnd)) { -#endif - errorString = QLibrary::tr("Cannot unload library %1: %2").arg(fileName).arg(qdlerror()); - return false; - } - errorString.clear(); - return true; -} - -void* PatchedLibraryPrivate::resolve_sys(const char* symbol) -{ -#if defined(QT_AOUT_UNDERSCORE) - // older a.out systems add an underscore in front of symbols - char* undrscr_symbol = new char[strlen(symbol)+2]; - undrscr_symbol[0] = '_'; - strcpy(undrscr_symbol+1, symbol); - void* address = dlsym(pHnd, undrscr_symbol); - delete [] undrscr_symbol; -#elif defined(QT_HPUX_LD) - void* address = 0; - if (shl_findsym((shl_t*)&pHnd, symbol, TYPE_UNDEFINED, &address) < 0) - address = 0; -#else - void* address = dlsym(pHnd, symbol); -#endif - if (!address) { - errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg( - QString::fromAscii(symbol)).arg(fileName).arg(qdlerror()); - } else { - errorString.clear(); - } - return address; -} - -#endif // Q_OS_UNIX - - - - - -#ifdef Q_OS_WIN - -extern QString qt_error_string(int code); - -bool PatchedLibraryPrivate::load_sys() -{ -#ifdef Q_OS_WINCE - QString attempt = QFileInfo(fileName).absoluteFilePath(); -#else - QString attempt = fileName; -#endif - - //avoid 'Bad Image' message box - UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - QT_WA({ - pHnd = LoadLibraryW((TCHAR*)QDir::toNativeSeparators(attempt).utf16()); - } , { - pHnd = LoadLibraryA(QFile::encodeName(QDir::toNativeSeparators(attempt)).data()); - }); - - if (pluginState != IsAPlugin) { -#if defined(Q_OS_WINCE) - if (!pHnd && ::GetLastError() == ERROR_MOD_NOT_FOUND) { - QString secondAttempt = fileName; - QT_WA({ - pHnd = LoadLibraryW((TCHAR*)QDir::toNativeSeparators(secondAttempt).utf16()); - } , { - pHnd = LoadLibraryA(QFile::encodeName(QDir::toNativeSeparators(secondAttempt)).data()); - }); - } -#endif - if (!pHnd && ::GetLastError() == ERROR_MOD_NOT_FOUND) { - attempt += QLatin1String(".dll"); - QT_WA({ - pHnd = LoadLibraryW((TCHAR*)QDir::toNativeSeparators(attempt).utf16()); - } , { - pHnd = LoadLibraryA(QFile::encodeName(QDir::toNativeSeparators(attempt)).data()); - }); - } - } - - SetErrorMode(oldmode); - if (!pHnd) { - errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qt_error_string()); - } - if (pHnd) { - errorString.clear(); - QT_WA({ - TCHAR buffer[MAX_PATH + 1]; - ::GetModuleFileNameW(pHnd, buffer, MAX_PATH); - attempt = QString::fromUtf16(reinterpret_cast<const ushort *>(&buffer)); - }, { - char buffer[MAX_PATH + 1]; - ::GetModuleFileNameA(pHnd, buffer, MAX_PATH); - attempt = QString::fromLocal8Bit(buffer); - }); - const QDir dir = QFileInfo(fileName).dir(); - const QString realfilename = attempt.mid(attempt.lastIndexOf(QLatin1Char('\\')) + 1); - if (dir.path() == QLatin1String(".")) - qualifiedFileName = realfilename; - else - qualifiedFileName = dir.filePath(realfilename); - } - return (pHnd != 0); -} - -bool PatchedLibraryPrivate::unload_sys() -{ - if (!FreeLibrary(pHnd)) { - errorString = QLibrary::tr("Cannot unload library %1: %2").arg(fileName).arg(qt_error_string()); - return false; - } - errorString.clear(); - return true; -} - -void* PatchedLibraryPrivate::resolve_sys(const char* symbol) -{ -#ifdef Q_OS_WINCE - void* address = (void*)GetProcAddress(pHnd, (const wchar_t*)QString::fromLatin1(symbol).utf16()); -#else - void* address = (void*)GetProcAddress(pHnd, symbol); -#endif - if (!address) { - errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg( - QString::fromAscii(symbol)).arg(fileName).arg(qt_error_string()); - } else { - errorString.clear(); - } - return address; -} - -#endif // Q_OS_WIN - -QT_END_NAMESPACE -- GitLab