summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArvid Ephraim Picciani <arvid.picciani@nokia.com>2010-08-30 08:45:44 (GMT)
committerArvid Ephraim Picciani <arvid.picciani@nokia.com>2010-08-30 13:00:37 (GMT)
commite4f12672ab7a70dbaac2feb81499a9ee816f677f (patch)
tree27c08bbbfcb35bc4b9cd42fcf45d715bed639994
parent9678de93f4b3d0f59436d086de80d821b4694e98 (diff)
downloadQt-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.cpp42
-rw-r--r--src/corelib/plugin/qelfparser_p.h2
-rw-r--r--src/corelib/plugin/qlibrary.cpp29
-rw-r--r--src/corelib/plugin/qplugin.h5
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; } \