Line | Source Code | Coverage |
---|
1 | /**************************************************************************** | - |
2 | ** | - |
3 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). | - |
4 | ** Contact: http://www.qt-project.org/legal | - |
5 | ** | - |
6 | ** This file is part of the QtCore module of the Qt Toolkit. | - |
7 | ** | - |
8 | ** $QT_BEGIN_LICENSE:LGPL$ | - |
9 | ** Commercial License Usage | - |
10 | ** Licensees holding valid commercial Qt licenses may use this file in | - |
11 | ** accordance with the commercial license agreement provided with the | - |
12 | ** Software or, alternatively, in accordance with the terms contained in | - |
13 | ** a written agreement between you and Digia. For licensing terms and | - |
14 | ** conditions see http://qt.digia.com/licensing. For further information | - |
15 | ** use the contact form at http://qt.digia.com/contact-us. | - |
16 | ** | - |
17 | ** GNU Lesser General Public License Usage | - |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - |
19 | ** General Public License version 2.1 as published by the Free Software | - |
20 | ** Foundation and appearing in the file LICENSE.LGPL included in the | - |
21 | ** packaging of this file. Please review the following information to | - |
22 | ** ensure the GNU Lesser General Public License version 2.1 requirements | - |
23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | - |
24 | ** | - |
25 | ** In addition, as a special exception, Digia gives you certain additional | - |
26 | ** rights. These rights are described in the Digia Qt LGPL Exception | - |
27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | - |
28 | ** | - |
29 | ** GNU General Public License Usage | - |
30 | ** Alternatively, this file may be used under the terms of the GNU | - |
31 | ** General Public License version 3.0 as published by the Free Software | - |
32 | ** Foundation and appearing in the file LICENSE.GPL included in the | - |
33 | ** packaging of this file. Please review the following information to | - |
34 | ** ensure the GNU General Public License version 3.0 requirements will be | - |
35 | ** met: http://www.gnu.org/copyleft/gpl.html. | - |
36 | ** | - |
37 | ** | - |
38 | ** $QT_END_LICENSE$ | - |
39 | ** | - |
40 | ****************************************************************************/ | - |
41 | | - |
42 | #include "qplatformdefs.h" | - |
43 | | - |
44 | #include <qfile.h> | - |
45 | #include "qlibrary_p.h" | - |
46 | #include <qcoreapplication.h> | - |
47 | #include <private/qfilesystementry_p.h> | - |
48 | | - |
49 | #ifndef QT_NO_LIBRARY | - |
50 | | - |
51 | #ifdef Q_OS_MAC | - |
52 | # include <private/qcore_mac_p.h> | - |
53 | #endif | - |
54 | | - |
55 | #if defined(QT_AOUT_UNDERSCORE) | - |
56 | #include <string.h> | - |
57 | #endif | - |
58 | | - |
59 | #if defined(Q_OS_VXWORKS) || defined (Q_OS_NACL) | - |
60 | #define QT_NO_DYNAMIC_LIBRARY | - |
61 | #endif | - |
62 | | - |
63 | QT_BEGIN_NAMESPACE | - |
64 | | - |
65 | #if !defined(QT_HPUX_LD) && !defined(QT_NO_DYNAMIC_LIBRARY) | - |
66 | QT_BEGIN_INCLUDE_NAMESPACE | - |
67 | #include <dlfcn.h> | - |
68 | QT_END_INCLUDE_NAMESPACE | - |
69 | #endif | - |
70 | | - |
71 | static QString qdlerror() | - |
72 | { | - |
73 | #if defined(QT_NO_DYNAMIC_LIBRARY) | - |
74 | const char *err = "This platform does not support dynamic libraries."; | - |
75 | #elif !defined(QT_HPUX_LD) | - |
76 | const char *err = dlerror(); executed (the execution status of this line is deduced): const char *err = dlerror(); | - |
77 | #else | - |
78 | const char *err = strerror(errno); | - |
79 | #endif | - |
80 | return err ? QLatin1Char('(') + QString::fromLocal8Bit(err) + QLatin1Char(')'): QString(); executed: return err ? QLatin1Char('(') + QString::fromLocal8Bit(err) + QLatin1Char(')'): QString(); Execution Count:55 | 55 |
81 | } | - |
82 | | - |
83 | QStringList QLibraryPrivate::suffixes_sys(const QString& fullVersion) | - |
84 | { | - |
85 | QStringList suffixes; executed (the execution status of this line is deduced): QStringList suffixes; | - |
86 | #if defined(Q_OS_HPUX) | - |
87 | // according to | - |
88 | // http://docs.hp.com/en/B2355-90968/linkerdifferencesiapa.htm | - |
89 | | - |
90 | // In PA-RISC (PA-32 and PA-64) shared libraries are suffixed | - |
91 | // with .sl. In IPF (32-bit and 64-bit), the shared libraries | - |
92 | // are suffixed with .so. For compatibility, the IPF linker | - |
93 | // also supports the .sl suffix. | - |
94 | | - |
95 | // But since we don't know if we are built on HPUX or HPUXi, | - |
96 | // we support both .sl (and .<version>) and .so suffixes but | - |
97 | // .so is preferred. | - |
98 | # if defined(__ia64) | - |
99 | if (!fullVersion.isEmpty()) { | - |
100 | suffixes << QString::fromLatin1(".so.%1").arg(fullVersion); | - |
101 | } else { | - |
102 | suffixes << QLatin1String(".so"); | - |
103 | } | - |
104 | # endif | - |
105 | if (!fullVersion.isEmpty()) { | - |
106 | suffixes << QString::fromLatin1(".sl.%1").arg(fullVersion); | - |
107 | suffixes << QString::fromLatin1(".%1").arg(fullVersion); | - |
108 | } else { | - |
109 | suffixes << QLatin1String(".sl"); | - |
110 | } | - |
111 | #elif defined(Q_OS_AIX) | - |
112 | suffixes << ".a"; | - |
113 | | - |
114 | #else | - |
115 | if (!fullVersion.isEmpty()) { evaluated: !fullVersion.isEmpty() yes Evaluation Count:55 | yes Evaluation Count:40 |
| 40-55 |
116 | suffixes << QString::fromLatin1(".so.%1").arg(fullVersion); executed (the execution status of this line is deduced): suffixes << QString::fromLatin1(".so.%1").arg(fullVersion); | - |
117 | } else { executed: } Execution Count:55 | 55 |
118 | suffixes << QLatin1String(".so"); executed (the execution status of this line is deduced): suffixes << QLatin1String(".so"); | - |
119 | } executed: } Execution Count:40 | 40 |
120 | #endif | - |
121 | # ifdef Q_OS_MAC | - |
122 | if (!fullVersion.isEmpty()) { | - |
123 | suffixes << QString::fromLatin1(".%1.bundle").arg(fullVersion); | - |
124 | suffixes << QString::fromLatin1(".%1.dylib").arg(fullVersion); | - |
125 | } else { | - |
126 | suffixes << QLatin1String(".bundle") << QLatin1String(".dylib"); | - |
127 | } | - |
128 | #endif | - |
129 | return suffixes; executed: return suffixes; Execution Count:95 | 95 |
130 | } | - |
131 | | - |
132 | QStringList QLibraryPrivate::prefixes_sys() | - |
133 | { | - |
134 | return QStringList() << QLatin1String("lib"); executed: return QStringList() << QLatin1String("lib"); Execution Count:95 | 95 |
135 | } | - |
136 | | - |
137 | bool QLibraryPrivate::load_sys() | - |
138 | { | - |
139 | QString attempt; executed (the execution status of this line is deduced): QString attempt; | - |
140 | #if !defined(QT_NO_DYNAMIC_LIBRARY) | - |
141 | QFileSystemEntry fsEntry(fileName); executed (the execution status of this line is deduced): QFileSystemEntry fsEntry(fileName); | - |
142 | | - |
143 | QString path = fsEntry.path(); executed (the execution status of this line is deduced): QString path = fsEntry.path(); | - |
144 | QString name = fsEntry.fileName(); executed (the execution status of this line is deduced): QString name = fsEntry.fileName(); | - |
145 | if (path == QLatin1String(".") && !fileName.startsWith(path)) evaluated: path == QLatin1String(".") yes Evaluation Count:68 | yes Evaluation Count:192 |
partially evaluated: !fileName.startsWith(path) yes Evaluation Count:68 | no Evaluation Count:0 |
| 0-192 |
146 | path.clear(); executed: path.clear(); Execution Count:68 | 68 |
147 | else | - |
148 | path += QLatin1Char('/'); executed: path += QLatin1Char('/'); Execution Count:192 | 192 |
149 | | - |
150 | QStringList suffixes; executed (the execution status of this line is deduced): QStringList suffixes; | - |
151 | QStringList prefixes; executed (the execution status of this line is deduced): QStringList prefixes; | - |
152 | if (pluginState != IsAPlugin) { evaluated: pluginState != IsAPlugin yes Evaluation Count:93 | yes Evaluation Count:167 |
| 93-167 |
153 | prefixes = prefixes_sys(); executed (the execution status of this line is deduced): prefixes = prefixes_sys(); | - |
154 | suffixes = suffixes_sys(fullVersion); executed (the execution status of this line is deduced): suffixes = suffixes_sys(fullVersion); | - |
155 | } executed: } Execution Count:93 | 93 |
156 | int dlFlags = 0; executed (the execution status of this line is deduced): int dlFlags = 0; | - |
157 | #if defined(QT_HPUX_LD) | - |
158 | dlFlags = DYNAMIC_PATH | BIND_NONFATAL; | - |
159 | if (loadHints & QLibrary::ResolveAllSymbolsHint) { | - |
160 | dlFlags |= BIND_IMMEDIATE; | - |
161 | } else { | - |
162 | dlFlags |= BIND_DEFERRED; | - |
163 | } | - |
164 | #else | - |
165 | if (loadHints & QLibrary::ResolveAllSymbolsHint) { evaluated: loadHints & QLibrary::ResolveAllSymbolsHint yes Evaluation Count:4 | yes Evaluation Count:256 |
| 4-256 |
166 | dlFlags |= RTLD_NOW; executed (the execution status of this line is deduced): dlFlags |= 0x00002; | - |
167 | } else { executed: } Execution Count:4 | 4 |
168 | dlFlags |= RTLD_LAZY; executed (the execution status of this line is deduced): dlFlags |= 0x00001; | - |
169 | } executed: } Execution Count:256 | 256 |
170 | if (loadHints & QLibrary::ExportExternalSymbolsHint) { partially evaluated: loadHints & QLibrary::ExportExternalSymbolsHint no Evaluation Count:0 | yes Evaluation Count:260 |
| 0-260 |
171 | dlFlags |= RTLD_GLOBAL; never executed (the execution status of this line is deduced): dlFlags |= 0x00100; | - |
172 | } | 0 |
173 | #if !defined(Q_OS_CYGWIN) | - |
174 | else { | - |
175 | #if defined(Q_OS_MAC) | - |
176 | if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) | - |
177 | #endif | - |
178 | dlFlags |= RTLD_LOCAL; executed (the execution status of this line is deduced): dlFlags |= 0; | - |
179 | } executed: } Execution Count:260 | 260 |
180 | #endif | - |
181 | | - |
182 | // Provide access to RTLD_NODELETE flag on Unix | - |
183 | // From GNU documentation on RTLD_NODELETE: | - |
184 | // Do not unload the library during dlclose(). Consequently, the | - |
185 | // library's specific static variables are not reinitialized if the | - |
186 | // library is reloaded with dlopen() at a later time. | - |
187 | #ifdef RTLD_NODELETE | - |
188 | if (loadHints & QLibrary::PreventUnloadHint) { partially evaluated: loadHints & QLibrary::PreventUnloadHint no Evaluation Count:0 | yes Evaluation Count:260 |
| 0-260 |
189 | dlFlags |= RTLD_NODELETE; never executed (the execution status of this line is deduced): dlFlags |= 0x01000; | - |
190 | } | 0 |
191 | #endif | - |
192 | | - |
193 | #if defined(Q_OS_AIX) // Not sure if any other platform actually support this thing. | - |
194 | if (loadHints & QLibrary::LoadArchiveMemberHint) { | - |
195 | dlFlags |= RTLD_MEMBER; | - |
196 | } | - |
197 | #endif | - |
198 | #endif // QT_HPUX_LD | - |
199 | | - |
200 | // If the filename is an absolute path then we want to try that first as it is most likely | - |
201 | // what the callee wants. If we have been given a non-absolute path then lets try the | - |
202 | // native library name first to avoid unnecessary calls to dlopen(). | - |
203 | if (fsEntry.isAbsolute()) { evaluated: fsEntry.isAbsolute() yes Evaluation Count:192 | yes Evaluation Count:68 |
| 68-192 |
204 | suffixes.prepend(QString()); executed (the execution status of this line is deduced): suffixes.prepend(QString()); | - |
205 | prefixes.prepend(QString()); executed (the execution status of this line is deduced): prefixes.prepend(QString()); | - |
206 | } else { executed: } Execution Count:192 | 192 |
207 | suffixes.append(QString()); executed (the execution status of this line is deduced): suffixes.append(QString()); | - |
208 | prefixes.append(QString()); executed (the execution status of this line is deduced): prefixes.append(QString()); | - |
209 | } executed: } Execution Count:68 | 68 |
210 | | - |
211 | bool retry = true; executed (the execution status of this line is deduced): bool retry = true; | - |
212 | for(int prefix = 0; retry && !pHnd && prefix < prefixes.size(); prefix++) { evaluated: retry yes Evaluation Count:534 | yes Evaluation Count:3 |
evaluated: !pHnd yes Evaluation Count:281 | yes Evaluation Count:253 |
evaluated: prefix < prefixes.size() yes Evaluation Count:277 | yes Evaluation Count:4 |
| 3-534 |
213 | for(int suffix = 0; retry && !pHnd && suffix < suffixes.size(); suffix++) { evaluated: retry yes Evaluation Count:585 | yes Evaluation Count:3 |
evaluated: !pHnd yes Evaluation Count:332 | yes Evaluation Count:253 |
evaluated: suffix < suffixes.size() yes Evaluation Count:311 | yes Evaluation Count:21 |
| 3-585 |
214 | if (!prefixes.at(prefix).isEmpty() && name.startsWith(prefixes.at(prefix))) evaluated: !prefixes.at(prefix).isEmpty() yes Evaluation Count:101 | yes Evaluation Count:210 |
partially evaluated: name.startsWith(prefixes.at(prefix)) no Evaluation Count:0 | yes Evaluation Count:101 |
| 0-210 |
215 | continue; never executed: continue; | 0 |
216 | if (!suffixes.at(suffix).isEmpty() && name.endsWith(suffixes.at(suffix))) evaluated: !suffixes.at(suffix).isEmpty() yes Evaluation Count:101 | yes Evaluation Count:210 |
partially evaluated: name.endsWith(suffixes.at(suffix)) no Evaluation Count:0 | yes Evaluation Count:101 |
| 0-210 |
217 | continue; never executed: continue; | 0 |
218 | if (loadHints & QLibrary::LoadArchiveMemberHint) { partially evaluated: loadHints & QLibrary::LoadArchiveMemberHint no Evaluation Count:0 | yes Evaluation Count:311 |
| 0-311 |
219 | attempt = name; never executed (the execution status of this line is deduced): attempt = name; | - |
220 | int lparen = attempt.indexOf(QLatin1Char('(')); never executed (the execution status of this line is deduced): int lparen = attempt.indexOf(QLatin1Char('(')); | - |
221 | if (lparen == -1) never evaluated: lparen == -1 | 0 |
222 | lparen = attempt.count(); never executed: lparen = attempt.count(); | 0 |
223 | attempt = path + prefixes.at(prefix) + attempt.insert(lparen, suffixes.at(suffix)); never executed (the execution status of this line is deduced): attempt = path + prefixes.at(prefix) + attempt.insert(lparen, suffixes.at(suffix)); | - |
224 | } else { | 0 |
225 | attempt = path + prefixes.at(prefix) + name + suffixes.at(suffix); executed (the execution status of this line is deduced): attempt = path + prefixes.at(prefix) + name + suffixes.at(suffix); | - |
226 | } executed: } Execution Count:311 | 311 |
227 | #if defined(QT_HPUX_LD) | - |
228 | pHnd = (void*)shl_load(QFile::encodeName(attempt), dlFlags, 0); | - |
229 | #else | - |
230 | pHnd = dlopen(QFile::encodeName(attempt), dlFlags); executed (the execution status of this line is deduced): pHnd = dlopen(QFile::encodeName(attempt), dlFlags); | - |
231 | #endif | - |
232 | | - |
233 | if (!pHnd && fileName.startsWith(QLatin1Char('/')) && QFile::exists(attempt)) { evaluated: !pHnd yes Evaluation Count:58 | yes Evaluation Count:253 |
evaluated: fileName.startsWith(QLatin1Char('/')) yes Evaluation Count:54 | yes Evaluation Count:4 |
evaluated: QFile::exists(attempt) yes Evaluation Count:3 | yes Evaluation Count:51 |
| 3-253 |
234 | // We only want to continue if dlopen failed due to that the shared library did not exist. | - |
235 | // However, we are only able to apply this check for absolute filenames (since they are | - |
236 | // not influenced by the content of LD_LIBRARY_PATH, /etc/ld.so.cache, DT_RPATH etc...) | - |
237 | // This is all because dlerror is flawed and cannot tell us the reason why it failed. | - |
238 | retry = false; executed (the execution status of this line is deduced): retry = false; | - |
239 | } executed: } Execution Count:3 | 3 |
240 | } executed: } Execution Count:311 | 311 |
241 | } executed: } Execution Count:277 | 277 |
242 | | - |
243 | #ifdef Q_OS_MAC | - |
244 | if (!pHnd) { | - |
245 | QByteArray utf8Bundle = fileName.toUtf8(); | - |
246 | QCFType<CFURLRef> bundleUrl = CFURLCreateFromFileSystemRepresentation(NULL, reinterpret_cast<const UInt8*>(utf8Bundle.data()), utf8Bundle.length(), true); | - |
247 | QCFType<CFBundleRef> bundle = CFBundleCreate(NULL, bundleUrl); | - |
248 | if(bundle) { | - |
249 | QCFType<CFURLRef> url = CFBundleCopyExecutableURL(bundle); | - |
250 | char executableFile[FILENAME_MAX]; | - |
251 | CFURLGetFileSystemRepresentation(url, true, reinterpret_cast<UInt8*>(executableFile), FILENAME_MAX); | - |
252 | attempt = QString::fromUtf8(executableFile); | - |
253 | pHnd = dlopen(QFile::encodeName(attempt), dlFlags); | - |
254 | } | - |
255 | } | - |
256 | #endif | - |
257 | #endif // QT_NO_DYNAMIC_LIBRARY | - |
258 | if (!pHnd) { evaluated: !pHnd yes Evaluation Count:7 | yes Evaluation Count:253 |
| 7-253 |
259 | errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qdlerror()); executed (the execution status of this line is deduced): errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qdlerror()); | - |
260 | } executed: } Execution Count:7 | 7 |
261 | if (pHnd) { evaluated: pHnd yes Evaluation Count:253 | yes Evaluation Count:7 |
| 7-253 |
262 | qualifiedFileName = attempt; executed (the execution status of this line is deduced): qualifiedFileName = attempt; | - |
263 | errorString.clear(); executed (the execution status of this line is deduced): errorString.clear(); | - |
264 | } executed: } Execution Count:253 | 253 |
265 | return (pHnd != 0); executed: return (pHnd != 0); Execution Count:260 | 260 |
266 | } | - |
267 | | - |
268 | bool QLibraryPrivate::unload_sys() | - |
269 | { | - |
270 | #if !defined(QT_NO_DYNAMIC_LIBRARY) | - |
271 | # if defined(QT_HPUX_LD) | - |
272 | if (shl_unload((shl_t)pHnd)) { | - |
273 | # else | - |
274 | if (dlclose(pHnd)) { partially evaluated: dlclose(pHnd) no Evaluation Count:0 | yes Evaluation Count:943 |
| 0-943 |
275 | # endif | - |
276 | errorString = QLibrary::tr("Cannot unload library %1: %2").arg(fileName).arg(qdlerror()); never executed (the execution status of this line is deduced): errorString = QLibrary::tr("Cannot unload library %1: %2").arg(fileName).arg(qdlerror()); | - |
277 | return false; never executed: return false; | 0 |
278 | } | - |
279 | #endif | - |
280 | errorString.clear(); executed (the execution status of this line is deduced): errorString.clear(); | - |
281 | return true; executed: return true; Execution Count:943 | 943 |
282 | } | - |
283 | | - |
284 | #ifdef Q_OS_LINUX | - |
285 | Q_CORE_EXPORT QFunctionPointer qt_linux_find_symbol_sys(const char *symbol) | - |
286 | { | - |
287 | return QFunctionPointer(dlsym(RTLD_DEFAULT, symbol)); never executed: return QFunctionPointer(dlsym(((void *) 0), symbol)); | 0 |
288 | } | - |
289 | #endif | - |
290 | | - |
291 | #ifdef Q_OS_MAC | - |
292 | Q_CORE_EXPORT QFunctionPointer qt_mac_resolve_sys(void *handle, const char *symbol) | - |
293 | { | - |
294 | return QFunctionPointer(dlsym(handle, symbol)); | - |
295 | } | - |
296 | #endif | - |
297 | | - |
298 | QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol) | - |
299 | { | - |
300 | #if defined(QT_AOUT_UNDERSCORE) | - |
301 | // older a.out systems add an underscore in front of symbols | - |
302 | char* undrscr_symbol = new char[strlen(symbol)+2]; | - |
303 | undrscr_symbol[0] = '_'; | - |
304 | strcpy(undrscr_symbol+1, symbol); | - |
305 | QFunctionPointer address = QFunctionPointer(dlsym(pHnd, undrscr_symbol)); | - |
306 | delete [] undrscr_symbol; | - |
307 | #elif defined(QT_HPUX_LD) | - |
308 | QFunctionPointer address = 0; | - |
309 | if (shl_findsym((shl_t*)&pHnd, symbol, TYPE_UNDEFINED, &address) < 0) | - |
310 | address = 0; | - |
311 | #elif defined (QT_NO_DYNAMIC_LIBRARY) | - |
312 | QFunctionPointer address = 0; | - |
313 | #else | - |
314 | QFunctionPointer address = QFunctionPointer(dlsym(pHnd, symbol)); executed (the execution status of this line is deduced): QFunctionPointer address = QFunctionPointer(dlsym(pHnd, symbol)); | - |
315 | #endif | - |
316 | if (!address) { evaluated: !address yes Evaluation Count:48 | yes Evaluation Count:3427 |
| 48-3427 |
317 | errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg( executed (the execution status of this line is deduced): errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg( | - |
318 | QString::fromLatin1(symbol)).arg(fileName).arg(qdlerror()); executed (the execution status of this line is deduced): QString::fromLatin1(symbol)).arg(fileName).arg(qdlerror()); | - |
319 | } else { executed: } Execution Count:48 | 48 |
320 | errorString.clear(); executed (the execution status of this line is deduced): errorString.clear(); | - |
321 | } executed: } Execution Count:3427 | 3427 |
322 | return address; executed: return address; Execution Count:3475 | 3475 |
323 | } | - |
324 | | - |
325 | QT_END_NAMESPACE | - |
326 | | - |
327 | #endif // QT_NO_LIBRARY | - |
328 | | - |
| | |