Find libssl on linux using paths of loaded libraries
authorShane Kearns <ext-shane.2.kearns@nokia.com>
Wed, 28 Mar 2012 15:06:57 +0000 (16:06 +0100)
committerQt by Nokia <qt-info@nokia.com>
Thu, 5 Apr 2012 13:37:53 +0000 (15:37 +0200)
The installed path of libssl may include an element describing the
architecture, e.g. x86_64-linux-gnu or i386-linux-gnu.
In most cases, the libraries already loaded (static dependencies of
Qt, such as libc) will include the path where libssl is installed.

Use dl_iterate_phdr to find the paths. This is a linux specific
function, but it does provide "/lib/<arch>" and "/usr/lib/<arch>"
at the point ssl symbols are being resolved when running the
qsslsocket autotest (which has less dependencies than a typical
Qt app).

Task-number: QTBUG-24694
Change-Id: I9af8081f41bb85c2fcff450a2acda5672a7f7518
Reviewed-by: Harald Fernengel <harald.fernengel@nokia.com>
src/network/ssl/qsslsocket_openssl_symbols.cpp

index aa25215..b5374d1 100644 (file)
@@ -53,6 +53,9 @@
 #if defined(Q_OS_UNIX)
 #include <QtCore/qdir.h>
 #endif
+#ifdef Q_OS_LINUX
+#include <link.h>
+#endif
 
 QT_BEGIN_NAMESPACE
 
@@ -347,6 +350,23 @@ static bool libGreaterThan(const QString &lhs, const QString &rhs)
     return true;
 }
 
+#ifdef Q_OS_LINUX
+static int dlIterateCallback(struct dl_phdr_info *info, size_t size, void *data)
+{
+    if (size < sizeof (info->dlpi_addr) + sizeof (info->dlpi_name))
+        return 1;
+    QSet<QString> *paths = (QSet<QString> *)data;
+    QString path = QString::fromLocal8Bit(info->dlpi_name);
+    if (!path.isEmpty()) {
+        QFileInfo fi(path);
+        path = fi.absolutePath();
+        if (!path.isEmpty())
+            paths->insert(path);
+    }
+    return 0;
+}
+#endif
+
 static QStringList findAllLibSsl()
 {
     QStringList paths;
@@ -358,6 +378,12 @@ static QStringList findAllLibSsl()
             .split(QLatin1Char(':'), QString::SkipEmptyParts);
 #  endif
     paths << QLatin1String("/lib") << QLatin1String("/usr/lib") << QLatin1String("/usr/local/lib");
+#ifdef Q_OS_LINUX
+    // discover paths of already loaded libraries
+    QSet<QString> loadedPaths;
+    dl_iterate_phdr(dlIterateCallback, &loadedPaths);
+    paths.append(loadedPaths.toList());
+#endif
 
     QStringList foundSsls;
     foreach (const QString &path, paths) {