diff options
author | Arvid Ephraim Picciani <arvid.picciani@nokia.com> | 2010-08-30 08:45:44 (GMT) |
---|---|---|
committer | Arvid Ephraim Picciani <arvid.picciani@nokia.com> | 2010-08-30 13:00:37 (GMT) |
commit | e4f12672ab7a70dbaac2feb81499a9ee816f677f (patch) | |
tree | 27c08bbbfcb35bc4b9cd42fcf45d715bed639994 | |
parent | 9678de93f4b3d0f59436d086de80d821b4694e98 (diff) | |
download | Qt-e4f12672ab7a70dbaac2feb81499a9ee816f677f.zip Qt-e4f12672ab7a70dbaac2feb81499a9ee816f677f.tar.gz Qt-e4f12672ab7a70dbaac2feb81499a9ee816f677f.tar.bz2 |
find .rodata in qt plugins to optimize loading of plugins with no qt section
Reviewed-by: janarve
-rw-r--r-- | src/corelib/plugin/qelfparser_p.cpp | 42 | ||||
-rw-r--r-- | src/corelib/plugin/qelfparser_p.h | 2 | ||||
-rw-r--r-- | src/corelib/plugin/qlibrary.cpp | 29 | ||||
-rw-r--r-- | src/corelib/plugin/qplugin.h | 5 |
4 files changed, 41 insertions, 37 deletions
diff --git a/src/corelib/plugin/qelfparser_p.cpp b/src/corelib/plugin/qelfparser_p.cpp index d837006..f815a77 100644 --- a/src/corelib/plugin/qelfparser_p.cpp +++ b/src/corelib/plugin/qelfparser_p.cpp @@ -60,13 +60,13 @@ const char *QElfParser::parseSectionHeader(const char *data, ElfSectionHeader *s return data; } -int QElfParser::parse(const char *dataStart, ulong *fdlen, const QString &library, uint *version, bool *debug, QByteArray *key, QLibraryPrivate *lib, long *pos) +int QElfParser::parse(const char *dataStart, ulong fdlen, const QString &library, QLibraryPrivate *lib, long *pos, ulong *sectionlen) { #if defined(QELFPARSER_DEBUG) qDebug() << "QElfParser::parse " << library; #endif - if (*fdlen < 64){ + if (fdlen < 64){ if (lib) lib->errorString = QLibrary::tr("'%1' is not an ELF object (%2)").arg(library).arg(QLatin1String("file too small")); return NotElf; @@ -114,7 +114,7 @@ int QElfParser::parse(const char *dataStart, ulong *fdlen, const QString &librar qelfhalf_t e_shsize = read<qelfhalf_t> (data); - if (e_shsize > *fdlen) { + if (e_shsize > fdlen) { if (lib) lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library).arg(QLatin1String("unexpected e_shsize")); return Corrupt; @@ -137,7 +137,7 @@ int QElfParser::parse(const char *dataStart, ulong *fdlen, const QString &librar qelfhalf_t e_shtrndx = read<qelfhalf_t> (data); data += sizeof(qelfhalf_t); // e_shtrndx - if ((e_shnum * e_shentsize) >= *fdlen) { + if ((e_shnum * e_shentsize) > fdlen) { if (lib) lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) .arg(QLatin1String("announced %2 sections, each %3 bytes, exceed file size")) @@ -152,7 +152,7 @@ int QElfParser::parse(const char *dataStart, ulong *fdlen, const QString &librar ElfSectionHeader strtab; qulonglong soff = e_shoff + e_shentsize * (e_shtrndx); - if ((soff + e_shentsize) >= *fdlen || soff % 8 || soff == 0) { + if ((soff + e_shentsize) > fdlen || soff % 8 || soff == 0) { if (lib) lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) .arg(QLatin1String("strtab section seems to be at %1")) @@ -163,7 +163,7 @@ int QElfParser::parse(const char *dataStart, ulong *fdlen, const QString &librar parseSectionHeader(dataStart + soff, &strtab); m_stringTableFileOffset = strtab.offset; - if ((m_stringTableFileOffset + e_shentsize) >= *fdlen || m_stringTableFileOffset == 0) { + if ((m_stringTableFileOffset + e_shentsize) >= fdlen || m_stringTableFileOffset == 0) { if (lib) lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) .arg(QLatin1String("string table seems to be at %1")) @@ -185,7 +185,7 @@ int QElfParser::parse(const char *dataStart, ulong *fdlen, const QString &librar } const char *shnam = dataStart + m_stringTableFileOffset + sh.name; - if (m_stringTableFileOffset + sh.name >= *fdlen) { + if (m_stringTableFileOffset + sh.name > fdlen) { if (lib) lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) .arg(QLatin1String("section name %2 of %3 behind end of file")) @@ -197,8 +197,14 @@ int QElfParser::parse(const char *dataStart, ulong *fdlen, const QString &librar qDebug() << "++++" << i << shnam; #endif - if (qstrncmp(shnam, ".qplugin", 8) == 0) { + if (qstrcmp(shnam, ".qtplugin") == 0 || qstrcmp(shnam, ".rodata") == 0) { if (!(sh.type & 0x1)) { + if (shnam[1] == 'r') { + if (lib) + lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) + .arg(QLatin1String("empty .rodata. not a library.")); + return Corrupt; + } #if defined(QELFPARSER_DEBUG) qDebug()<<"section is not program data. skipped."; #endif @@ -206,26 +212,16 @@ int QElfParser::parse(const char *dataStart, ulong *fdlen, const QString &librar continue; } - if (sh.offset == 0 || (sh.offset + sh.size) >= *fdlen) { + if (sh.offset == 0 || (sh.offset + sh.size) > fdlen) { if (lib) lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) .arg(QLatin1String("missing section data. This is not a library.")); return Corrupt; } - QList<QByteArray> shname = QByteArray::fromRawData(shnam,strlen(shnam)).split('.'); - if (shname.count() < 4) { - if (lib) - lib->errorString = QLibrary::tr("'%1' is an invalid ELF object (%2)").arg(library) - .arg(QLatin1String("incompatible .qtplugin section name")); - return Corrupt; - } - - *debug = (shname.last() == "d"); - *version = (shname.at(2).toUInt() << 16) | (shname.at(3).toUInt() << 8) | shname.at(4).toUInt(); - *key = QByteArray(dataStart + sh.offset,sh.size-1); - *pos = sh.offset; - *fdlen = sh.size - 1; - return Ok; + *pos = sh.offset; + *sectionlen = sh.size - 1; + if (shnam[1] == 'q') + return Ok; } s += e_shentsize; } diff --git a/src/corelib/plugin/qelfparser_p.h b/src/corelib/plugin/qelfparser_p.h index 2259a51..16c6a72 100644 --- a/src/corelib/plugin/qelfparser_p.h +++ b/src/corelib/plugin/qelfparser_p.h @@ -74,6 +74,6 @@ public: } const char *parseSectionHeader(const char* s, ElfSectionHeader *sh); - int parse(const char *m_s, ulong *fdlen, const QString &library, uint *version, bool *debug, QByteArray *key, QLibraryPrivate *lib, long *pos); + int parse(const char *m_s, ulong fdlen, const QString &library, QLibraryPrivate *lib, long *pos, ulong *sectionlen); }; diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index 451c244..eb464c7 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -295,7 +295,6 @@ static bool qt_parse_pattern(const char *s, uint *version, bool *debug, QByteArr #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_SYMBIAN) && !defined(QT_NO_PLUGIN_CHECK) -#if !defined (Q_OF_ELF) || !defined(Q_CC_GNU) static long qt_find_pattern(const char *s, ulong s_len, const char *pattern, ulong p_len) { @@ -331,7 +330,6 @@ static long qt_find_pattern(const char *s, ulong s_len, return -1; } -#endif // !defined (Q_OF_ELF) || !defined(Q_CC_GNU) /* This opens the specified library, mmaps it into memory, and searches @@ -371,15 +369,27 @@ static bool qt_unix_query(const QString &library, uint *version, bool *debug, QB ELF binaries on GNU, have .qplugin sections. */ long pos = 0; -#if defined (Q_OF_ELF) && defined(Q_CC_GNU) - int r = QElfParser().parse(filedata, &fdlen, library, version, debug, key, lib, &pos); - return (r == QElfParser::Ok); -#else const char pattern[] = "pattern=QT_PLUGIN_VERIFICATION_DATA"; const ulong plen = qstrlen(pattern); - if (pos == 0) - pos = qt_find_pattern(filedata, fdlen, pattern, plen); - +#if defined (Q_OF_ELF) && defined(Q_CC_GNU) + int r = QElfParser().parse(filedata, fdlen, library, lib, &pos, &fdlen); + if (r == QElfParser::NoQtSection) { + if (pos > 0) { + // find inside .rodata + long rel = qt_find_pattern(filedata + pos, fdlen, pattern, plen); + if (rel < 0) { + pos = -1; + } else { + pos += rel; + } + } else { + pos = qt_find_pattern(filedata, fdlen, pattern, plen); + } + } else if (r != QElfParser::Ok) + return false; +#else + pos = qt_find_pattern(filedata, fdlen, pattern, plen); +#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU) bool ret = false; if (pos >= 0) ret = qt_parse_pattern(filedata + pos, version, debug, key); @@ -388,7 +398,6 @@ static bool qt_unix_query(const QString &library, uint *version, bool *debug, QB lib->errorString = QLibrary::tr("Plugin verification data mismatch in '%1'").arg(library); file.close(); return ret; -#endif // defined(Q_OF_ELF) && defined(Q_CC_GNU) } #endif // Q_OS_UNIX && !Q_OS_MAC && !defined(Q_OS_SYMBIAN) && !defined(QT_NO_PLUGIN_CHECK) diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h index 30c0c82..bd49b15 100644 --- a/src/corelib/plugin/qplugin.h +++ b/src/corelib/plugin/qplugin.h @@ -122,7 +122,7 @@ void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunctio # if defined (Q_OF_ELF) && defined (Q_CC_GNU) # define Q_PLUGIN_VERIFICATION_SECTION \ - __attribute__ ((section (".qplugin."QT_VERSION_STR QPLUGIN_SECTION_DEBUG_STR))) __attribute__((used)) static const char qt_plugin_build_key[] = QT_BUILD_KEY; + __attribute__ ((section (".qtplugin"))) __attribute__((used)) # else # define Q_PLUGIN_VERIFICATION_SECTION # endif @@ -134,8 +134,7 @@ void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunctio # endif # define Q_EXPORT_PLUGIN2(PLUGIN, PLUGINCLASS) \ - Q_PLUGIN_VERIFICATION_SECTION \ - Q_PLUGIN_VERIFICATION_DATA \ + Q_PLUGIN_VERIFICATION_SECTION Q_PLUGIN_VERIFICATION_DATA \ Q_EXTERN_C Q_DECL_EXPORT \ const char * Q_STANDARD_CALL qt_plugin_query_verification_data() \ { return qt_plugin_verification_data; } \ |