File indexing completed on 2024-05-12 03:54:59
0001 /* 0002 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0003 SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org> 0004 */ 0005 0006 #include "klibexec.h" 0007 #include <config-util.h> 0008 0009 #if HAVE_DLADDR 0010 #include <dlfcn.h> 0011 #elif defined(Q_OS_WIN) 0012 #include <windows.h> 0013 0014 #include <QVarLengthArray> 0015 #endif 0016 0017 #include <QCoreApplication> 0018 #include <QDir> 0019 #include <QLibraryInfo> 0020 0021 #include <kcoreaddons_debug.h> 0022 0023 static QString libraryPathFromAddress(void *address) 0024 { 0025 #if HAVE_DLADDR 0026 Dl_info info{}; 0027 if (dladdr(address, &info) == 0) { 0028 qCWarning(KCOREADDONS_DEBUG) << "Failed to match address to shared object."; 0029 // Do not call dlerror. It's only expected to return something useful on freebsd! 0030 return {}; 0031 } 0032 return QFile::decodeName(info.dli_fname); 0033 #elif defined(Q_OS_WIN) 0034 HMODULE hModule = nullptr; 0035 if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, static_cast<LPWSTR>(address), &hModule)) { 0036 qCWarning(KCOREADDONS_DEBUG) << "Failed to GetModuleHandleExW" << GetLastError(); 0037 return {}; 0038 } 0039 if (!hModule) { 0040 qCWarning(KCOREADDONS_DEBUG) << "hModule null unexpectedly"; 0041 return {}; 0042 } 0043 0044 QVarLengthArray<wchar_t, MAX_PATH> pathArray; 0045 DWORD pathSize = pathArray.size(); 0046 while (pathSize == pathArray.size()) { // pathSize doesn't include the null byte on success, so this only ever true if we need to grow 0047 pathArray.resize(pathArray.size() + MAX_PATH); 0048 pathSize = GetModuleFileNameW(hModule, pathArray.data(), pathArray.size()); 0049 if (pathSize == 0) { 0050 qCWarning(KCOREADDONS_DEBUG) << "Failed to GetModuleFileNameW" << GetLastError(); 0051 return {}; 0052 } 0053 } 0054 return QDir::fromNativeSeparators(QString::fromWCharArray(pathArray.data())); 0055 #else // unsupported 0056 return {}; 0057 #endif 0058 } 0059 0060 QString KLibexec::pathFromAddress(const QString &relativePath, void *address) 0061 { 0062 const QString libraryPath = libraryPathFromAddress(address); 0063 const QString absoluteDirPath = QFileInfo(libraryPath).absolutePath(); 0064 const QString libexecPath = QFileInfo(absoluteDirPath + QLatin1Char('/') + relativePath).absoluteFilePath(); 0065 return libexecPath; 0066 } 0067 0068 QStringList KLibexec::pathCandidates(const QString &relativePath) 0069 { 0070 const QString qLibexec = QLibraryInfo::path(QLibraryInfo::LibraryExecutablesPath); 0071 const QString qLibexecKF6 = qLibexec + QLatin1String("/kf6"); 0072 0073 return { 0074 QCoreApplication::applicationDirPath(), // look where our application binary is located 0075 qLibexec, // look where libexec path is (can be set in qt.conf) 0076 qLibexecKF6, // on !win32 we use a kf6 suffix 0077 relativePath, 0078 }; 0079 }