Remove elfreader and other unix leftovers from windeployqt

Back then elfreader and other unix functionality was added for the
purpose of having one generic deployment tool but it was never used.
Remove the code to be more clear on what to expect.

Change-Id: I2b7a759de04afe0c5fb210ad65f1c86e32934f18
Reviewed-by: Timothée Keller <timothee.keller@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
(cherry picked from commit 68b16974a72a35e33e4e947f7edfabd6ccd5f6a1)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Oliver Wolff 2023-08-01 13:43:45 +02:00 committed by Qt Cherry-pick Bot
parent 04efbda0df
commit 14d8d5099e
6 changed files with 18 additions and 654 deletions

View File

@ -12,7 +12,6 @@ qt_internal_add_tool(${target_name}
INSTALL_VERSIONED_LINK
TARGET_DESCRIPTION "Qt Windows Deployment Tool"
SOURCES
elfreader.cpp elfreader.h
qmlutils.cpp qmlutils.h
qtmoduleinfo.cpp qtmoduleinfo.h
utils.cpp utils.h

View File

@ -1,417 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "elfreader.h"
#include <QDir>
QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
/* This is a copy of the ELF reader contained in Qt Creator (src/libs/utils),
* extended by the dependencies() function to read out the dependencies of a dynamic executable. */
quint16 getHalfWord(const unsigned char *&s, const ElfData &context)
{
quint16 res;
if (context.endian == Elf_ELFDATA2MSB)
res = qFromBigEndian<quint16>(s);
else
res = qFromLittleEndian<quint16>(s);
s += 2;
return res;
}
quint32 getWord(const unsigned char *&s, const ElfData &context)
{
quint32 res;
if (context.endian == Elf_ELFDATA2MSB)
res = qFromBigEndian<quint32>(s);
else
res = qFromLittleEndian<quint32>(s);
s += 4;
return res;
}
quint64 getAddress(const unsigned char *&s, const ElfData &context)
{
quint64 res;
if (context.elfclass == Elf_ELFCLASS32) {
if (context.endian == Elf_ELFDATA2MSB)
res = qFromBigEndian<quint32>(s);
else
res = qFromLittleEndian<quint32>(s);
s += 4;
} else {
if (context.endian == Elf_ELFDATA2MSB)
res = qFromBigEndian<quint64>(s);
else
res = qFromLittleEndian<quint64>(s);
s += 8;
}
return res;
}
quint64 getOffset(const unsigned char *&s, const ElfData &context)
{
return getAddress(s, context);
}
static void parseSectionHeader(const uchar *s, ElfSectionHeader *sh, const ElfData &context)
{
sh->index = getWord(s, context);
sh->type = getWord(s, context);
sh->flags = quint32(getOffset(s, context));
sh->addr = getAddress(s, context);
sh->offset = getOffset(s, context);
sh->size = getOffset(s, context);
}
static void parseProgramHeader(const uchar *s, ElfProgramHeader *sh, const ElfData &context)
{
sh->type = getWord(s, context);
sh->offset = getOffset(s, context);
/* p_vaddr = */ getAddress(s, context);
/* p_paddr = */ getAddress(s, context);
sh->filesz = getWord(s, context);
sh->memsz = getWord(s, context);
}
class ElfMapper
{
public:
ElfMapper(const ElfReader *reader) : file(reader->m_binary) {}
bool map()
{
if (!file.open(QIODevice::ReadOnly))
return false;
fdlen = quint64(file.size());
ustart = file.map(0, qint64(fdlen));
if (ustart == 0) {
// Try reading the data into memory instead.
raw = file.readAll();
start = raw.constData();
fdlen = quint64(raw.size());
}
return true;
}
public:
QFile file;
QByteArray raw;
union { const char *start; const uchar *ustart; };
quint64 fdlen;
};
ElfReader::ElfReader(const QString &binary)
: m_binary(binary)
{
}
ElfData ElfReader::readHeaders()
{
readIt();
return m_elfData;
}
static inline QString msgInvalidElfObject(const QString &binary, const QString &why)
{
return QStringLiteral("'%1' is an invalid ELF object (%2)")
.arg(QDir::toNativeSeparators(binary), why);
}
ElfReader::Result ElfReader::readIt()
{
if (!m_elfData.sectionHeaders.isEmpty())
return Ok;
if (!m_elfData.programHeaders.isEmpty())
return Ok;
ElfMapper mapper(this);
if (!mapper.map())
return Corrupt;
const quint64 fdlen = mapper.fdlen;
if (fdlen < 64) {
m_errorString = QStringLiteral("'%1' is not an ELF object (file too small)").arg(QDir::toNativeSeparators(m_binary));
return NotElf;
}
if (strncmp(mapper.start, "\177ELF", 4) != 0) {
m_errorString = QStringLiteral("'%1' is not an ELF object").arg(QDir::toNativeSeparators(m_binary));
return NotElf;
}
// 32 or 64 bit
m_elfData.elfclass = ElfClass(mapper.start[4]);
const bool is64Bit = m_elfData.elfclass == Elf_ELFCLASS64;
if (m_elfData.elfclass != Elf_ELFCLASS32 && m_elfData.elfclass != Elf_ELFCLASS64) {
m_errorString = msgInvalidElfObject(m_binary, QStringLiteral("odd cpu architecture"));
return Corrupt;
}
// int bits = (data[4] << 5);
// If you remove this check to read ELF objects of a different arch,
// please make sure you modify the typedefs
// to match the _plugin_ architecture.
// if ((sizeof(void*) == 4 && bits != 32)
// || (sizeof(void*) == 8 && bits != 64)) {
// if (errorString)
// *errorString = QLibrary::QStringLiteral("'%1' is an invalid ELF object (%2)")
// .arg(m_binary).arg("wrong cpu architecture"_L1);
// return Corrupt;
// }
// Read Endianhness.
m_elfData.endian = ElfEndian(mapper.ustart[5]);
if (m_elfData.endian != Elf_ELFDATA2LSB && m_elfData.endian != Elf_ELFDATA2MSB) {
m_errorString = msgInvalidElfObject(m_binary, QStringLiteral("odd endianness"));
return Corrupt;
}
const uchar *data = mapper.ustart + 16; // e_ident
m_elfData.elftype = ElfType(getHalfWord(data, m_elfData));
m_elfData.elfmachine = ElfMachine(getHalfWord(data, m_elfData));
/* e_version = */ getWord(data, m_elfData);
m_elfData.entryPoint = getAddress(data, m_elfData);
quint64 e_phoff = getOffset(data, m_elfData);
quint64 e_shoff = getOffset(data, m_elfData);
/* e_flags = */ getWord(data, m_elfData);
quint32 e_shsize = getHalfWord(data, m_elfData);
if (e_shsize > fdlen) {
m_errorString = msgInvalidElfObject(m_binary, QStringLiteral("unexpected e_shsize"));
return Corrupt;
}
quint32 e_phentsize = getHalfWord(data, m_elfData);
if (e_phentsize != (is64Bit ? 56 : 32)) {
m_errorString = msgInvalidElfObject(m_binary, QStringLiteral("invalid structure"));
return ElfReader::Corrupt;
}
quint32 e_phnum = getHalfWord(data, m_elfData);
quint32 e_shentsize = getHalfWord(data, m_elfData);
if (e_shentsize % 4) {
m_errorString = msgInvalidElfObject(m_binary, QStringLiteral("unexpected e_shentsize"));
return Corrupt;
}
quint32 e_shnum = getHalfWord(data, m_elfData);
quint32 e_shtrndx = getHalfWord(data, m_elfData);
if (data != mapper.ustart + (is64Bit ? 64 : 52)) {
m_errorString = msgInvalidElfObject(m_binary, QStringLiteral("unexpected e_phentsize"));
return ElfReader::Corrupt;
}
if (quint64(e_shnum) * e_shentsize > fdlen) {
const QString reason = QStringLiteral("announced %1 sections, each %2 bytes, exceed file size").arg(e_shnum).arg(e_shentsize);
m_errorString = msgInvalidElfObject(m_binary, reason);
return Corrupt;
}
quint64 soff = e_shoff + e_shentsize * e_shtrndx;
// if ((soff + e_shentsize) > fdlen || soff % 4 || soff == 0) {
// m_errorString = QLibrary::QStringLiteral("'%1' is an invalid ELF object (%2)")
// .arg(m_binary)
// .arg("shstrtab section header seems to be at %1"_L1)
// .arg(QString::number(soff, 16));
// return Corrupt;
// }
if (e_shoff) {
ElfSectionHeader strtab;
parseSectionHeader(mapper.ustart + soff, &strtab, m_elfData);
const quint64 stringTableFileOffset = strtab.offset;
if (quint32(stringTableFileOffset + e_shentsize) >= fdlen
|| stringTableFileOffset == 0) {
const QString reason = QStringLiteral("string table seems to be at 0x%1").arg(soff, 0, 16);
m_errorString = msgInvalidElfObject(m_binary, reason);
return Corrupt;
}
for (quint32 i = 0; i < e_shnum; ++i) {
const uchar *s = mapper.ustart + e_shoff + i * e_shentsize;
ElfSectionHeader sh;
parseSectionHeader(s, &sh, m_elfData);
if (stringTableFileOffset + sh.index > fdlen) {
const QString reason = QStringLiteral("section name %1 of %2 behind end of file")
.arg(i).arg(e_shnum);
m_errorString = msgInvalidElfObject(m_binary, reason);
return Corrupt;
}
sh.name = mapper.start + stringTableFileOffset + sh.index;
if (sh.name == ".gdb_index") {
m_elfData.symbolsType = FastSymbols;
} else if (sh.name == ".debug_info") {
m_elfData.symbolsType = PlainSymbols;
} else if (sh.name == ".gnu_debuglink") {
m_elfData.debugLink = QByteArray(mapper.start + sh.offset);
m_elfData.symbolsType = LinkedSymbols;
} else if (sh.name == ".note.gnu.build-id") {
m_elfData.symbolsType = BuildIdSymbols;
if (sh.size > 16)
m_elfData.buildId = QByteArray(mapper.start + sh.offset + 16,
int(sh.size) - 16).toHex();
}
m_elfData.sectionHeaders.append(sh);
}
}
if (e_phoff) {
for (quint32 i = 0; i < e_phnum; ++i) {
const uchar *s = mapper.ustart + e_phoff + i * e_phentsize;
ElfProgramHeader ph;
parseProgramHeader(s, &ph, m_elfData);
m_elfData.programHeaders.append(ph);
}
}
return Ok;
}
QByteArray ElfReader::readSection(const QByteArray &name)
{
readIt();
int i = m_elfData.indexOf(name);
if (i == -1)
return QByteArray();
ElfMapper mapper(this);
if (!mapper.map())
return QByteArray();
const ElfSectionHeader &section = m_elfData.sectionHeaders.at(i);
return QByteArray(mapper.start + section.offset, int(section.size));
}
static QByteArray cutout(const char *s)
{
QByteArray res(s, 80);
const int pos = res.indexOf('\0');
if (pos != -1)
res.resize(pos - 1);
return res;
}
QByteArray ElfReader::readCoreName(bool *isCore)
{
*isCore = false;
readIt();
ElfMapper mapper(this);
if (!mapper.map())
return QByteArray();
if (m_elfData.elftype != Elf_ET_CORE)
return QByteArray();
*isCore = true;
for (int i = 0, n = m_elfData.sectionHeaders.size(); i != n; ++i)
if (m_elfData.sectionHeaders.at(i).type == Elf_SHT_NOTE) {
const ElfSectionHeader &header = m_elfData.sectionHeaders.at(i);
return cutout(mapper.start + header.offset + 0x40);
}
for (int i = 0, n = m_elfData.programHeaders.size(); i != n; ++i)
if (m_elfData.programHeaders.at(i).type == Elf_PT_NOTE) {
const ElfProgramHeader &header = m_elfData.programHeaders.at(i);
return cutout(mapper.start + header.offset + 0xec);
}
return QByteArray();
}
int ElfData::indexOf(const QByteArray &name) const
{
for (int i = 0, n = sectionHeaders.size(); i != n; ++i)
if (sectionHeaders.at(i).name == name)
return i;
return -1;
}
/* Helpers for reading out the .dynamic section containing the dependencies.
* The ".dynamic" section is an array of
* typedef struct {
* Elf32_Sword d_tag;
* union {
* Elf32_Word d_val;
* dElf32_Addr d_ptr;
* } d_un;
* } Elf32_Dyn
* with entries where a tag DT_NEEDED indicates that m_val is an offset into
* the string table ".dynstr". The documentation states that entries with the
* tag DT_STRTAB contain an offset for the string table to be used, but that
* has been found not to contain valid entries. */
enum DynamicSectionTags {
DT_NULL = 0,
DT_NEEDED = 1,
DT_STRTAB = 5,
DT_SONAME = 14,
DT_RPATH = 15
};
QList<QByteArray> ElfReader::dependencies()
{
QList<QByteArray> result;
ElfMapper mapper(this);
if (!mapper.map()) {
m_errorString = QStringLiteral("Mapper failure");
return result;
}
quint64 dynStrOffset = 0;
quint64 dynamicOffset = 0;
quint64 dynamicSize = 0;
const QList<ElfSectionHeader> &headers = readHeaders().sectionHeaders;
for (const ElfSectionHeader &eh : headers) {
if (eh.name == QByteArrayLiteral(".dynstr")) {
dynStrOffset = eh.offset;
} else if (eh.name == QByteArrayLiteral(".dynamic")) {
dynamicOffset = eh.offset;
dynamicSize = eh.size;
}
if (dynStrOffset && dynamicOffset)
break;
}
if (!dynStrOffset || !dynamicOffset) {
m_errorString = QStringLiteral("Not a dynamically linked executable.");
return result;
}
const unsigned char *dynamicData = mapper.ustart + dynamicOffset;
const unsigned char *dynamicDataEnd = dynamicData + dynamicSize;
while (dynamicData < dynamicDataEnd) {
const quint32 tag = getWord(dynamicData, m_elfData);
if (tag == DT_NULL)
break;
if (m_elfData.elfclass == Elf_ELFCLASS64)
dynamicData += sizeof(quint32); // padding to d_val/d_ptr.
if (tag == DT_NEEDED) {
const quint32 offset = getWord(dynamicData, m_elfData);
if (m_elfData.elfclass == Elf_ELFCLASS64)
dynamicData += sizeof(quint32); // past d_ptr.
const char *name = mapper.start + dynStrOffset + offset;
result.push_back(name);
} else {
dynamicData += m_elfData.elfclass == Elf_ELFCLASS64 ? 8 : 4;
}
}
return result;
}
QT_END_NAMESPACE

View File

@ -1,151 +0,0 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#ifndef ELFREADER_H
#define ELFREADER_H
#include <QtCore/QList>
#include <QtCore/QString>
#include <QtCore/QtEndian>
QT_BEGIN_NAMESPACE
enum ElfProgramHeaderType
{
Elf_PT_NULL = 0,
Elf_PT_LOAD = 1,
Elf_PT_DYNAMIC = 2,
Elf_PT_INTERP = 3,
Elf_PT_NOTE = 4,
Elf_PT_SHLIB = 5,
Elf_PT_PHDR = 6,
Elf_PT_TLS = 7,
Elf_PT_NUM = 8
};
enum ElfSectionHeaderType
{
Elf_SHT_NULL = 0,
Elf_SHT_PROGBITS = 1,
Elf_SHT_SYMTAB = 2,
Elf_SHT_STRTAB = 3,
Elf_SHT_RELA = 4,
Elf_SHT_HASH = 5,
Elf_SHT_DYNAMIC = 6,
Elf_SHT_NOTE = 7,
Elf_SHT_NOBITS = 8,
Elf_SHT_REL = 9,
Elf_SHT_SHLIB = 10,
Elf_SHT_DYNSYM = 11,
Elf_SHT_INIT_ARRAY = 14,
Elf_SHT_FINI_ARRAY = 15,
Elf_SHT_PREINIT_ARRAY = 16,
Elf_SHT_GROUP = 17,
Elf_SHT_SYMTAB_SHNDX = 18
};
enum ElfEndian
{
Elf_ELFDATANONE = 0,
Elf_ELFDATA2LSB = 1,
Elf_ELFDATA2MSB = 2,
Elf_ELFDATANUM = 3
};
enum ElfClass
{
Elf_ELFCLASS32 = 1,
Elf_ELFCLASS64 = 2
};
enum ElfType
{
Elf_ET_NONE = 0,
Elf_ET_REL = 1,
Elf_ET_EXEC = 2,
Elf_ET_DYN = 3,
Elf_ET_CORE = 4
};
enum ElfMachine
{
Elf_EM_386 = 3,
Elf_EM_ARM = 40,
Elf_EM_X86_64 = 62
};
enum DebugSymbolsType
{
UnknownSymbols = 0, // Unknown.
NoSymbols = 1, // No usable symbols.
LinkedSymbols = 2, // Link to symbols available.
BuildIdSymbols = 4, // BuildId available.
PlainSymbols = 8, // Ordinary symbols available.
FastSymbols = 16 // Dwarf index available.
};
class ElfSectionHeader
{
public:
QByteArray name;
quint32 index;
quint32 type;
quint32 flags;
quint64 offset;
quint64 size;
quint64 addr;
};
class ElfProgramHeader
{
public:
quint32 name;
quint32 type;
quint64 offset;
quint64 filesz;
quint64 memsz;
};
class ElfData
{
public:
ElfData() : symbolsType(UnknownSymbols) {}
int indexOf(const QByteArray &name) const;
public:
ElfEndian endian;
ElfType elftype;
ElfMachine elfmachine;
ElfClass elfclass;
quint64 entryPoint;
QByteArray debugLink;
QByteArray buildId;
DebugSymbolsType symbolsType;
QList<ElfSectionHeader> sectionHeaders;
QList<ElfProgramHeader> programHeaders;
};
class ElfReader
{
public:
explicit ElfReader(const QString &binary);
enum Result { Ok, NotElf, Corrupt };
ElfData readHeaders();
QByteArray readSection(const QByteArray &sectionName);
QString errorString() const { return m_errorString; }
QByteArray readCoreName(bool *isCore);
QList<QByteArray> dependencies();
private:
friend class ElfMapper;
Result readIt();
QString m_binary;
QString m_errorString;
ElfData m_elfData;
};
QT_END_NAMESPACE
#endif // ELFREADER_H

View File

@ -116,8 +116,6 @@ static QByteArray formatQtModules(const ModuleBitset &mask, bool option = false)
static Platform platformFromMkSpec(const QString &xSpec)
{
if (xSpec == "linux-g++"_L1)
return Unix;
if (xSpec.startsWith("win32-"_L1)) {
if (xSpec.contains("clang-g++"_L1))
return WindowsDesktopClangMinGW;
@ -712,7 +710,8 @@ static bool findDependentQtLibraries(const QString &qtBinDir, const QString &bin
QStringList dependentLibs;
if (directDependencyCount)
*directDependencyCount = 0;
if (!readExecutable(binary, platform, errorMessage, &dependentLibs, wordSize, isDebug, machineArch)) {
if (!readPeExecutable(binary, errorMessage, &dependentLibs, wordSize, isDebug,
platform == WindowsDesktopMinGW, machineArch)) {
errorMessage->prepend("Unable to find dependent libraries of "_L1 +
QDir::toNativeSeparators(binary) + " :"_L1);
return false;
@ -937,19 +936,9 @@ QStringList findQtPlugins(ModuleBitset *usedQtModules, const ModuleBitset &disab
QString filter;
const bool isPlatformPlugin = subDirName == "platforms"_L1;
if (isPlatformPlugin) {
switch (platform) {
case WindowsDesktopMsvc:
case WindowsDesktopMinGW:
filter = QStringLiteral("qwindows");
if (!infix.isEmpty())
filter += infix;
break;
case Unix:
filter = QStringLiteral("libqxcb");
break;
case UnknownPlatform:
break;
}
filter = QStringLiteral("qwindows");
if (!infix.isEmpty())
filter += infix;
} else {
filter = u"*"_s;
}
@ -1055,17 +1044,11 @@ static QString libraryPath(const QString &libraryLocation, const char *name,
const QString &infix, Platform platform, bool debug)
{
QString result = libraryLocation + u'/';
if (platform & WindowsBased) {
result += QLatin1StringView(name);
result += infix;
if (debug && platformHasDebugSuffix(platform))
result += u'd';
} else if (platform.testFlag(UnixBased)) {
result += QStringLiteral("lib");
result += QLatin1StringView(name);
result += infix;
}
result += sharedLibrarySuffix(platform);
result += QLatin1StringView(name);
result += infix;
if (debug && platformHasDebugSuffix(platform))
result += u'd';
result += sharedLibrarySuffix();
return result;
}
@ -1112,7 +1095,7 @@ static QStringList findMinGWRuntimePaths(const QString &qtBinDir, Platform platf
QStringList result;
const bool isClang = platform == WindowsDesktopClangMinGW;
QStringList filters;
const QString suffix = u'*' + sharedLibrarySuffix(platform);
const QString suffix = u'*' + sharedLibrarySuffix();
for (const auto &minGWRuntime : runtimeFilters)
filters.append(minGWRuntime + suffix);
@ -1244,9 +1227,7 @@ static DeployResult deploy(const Options &options, const QMap<QString, QString>
const QChar slash = u'/';
const QString qtBinDir = qtpathsVariables.value(QStringLiteral("QT_INSTALL_BINS"));
const QString libraryLocation = options.platform == Unix
? qtpathsVariables.value(QStringLiteral("QT_INSTALL_LIBS"))
: qtBinDir;
const QString libraryLocation = qtBinDir;
const QString infix = qtpathsVariables.value(QLatin1StringView(qmakeInfixKey));
const int version = qtVersion(qtpathsVariables);
Q_UNUSED(version);
@ -1325,7 +1306,7 @@ static DeployResult deploy(const Options &options, const QMap<QString, QString>
const QStringList qtLibs = dependentQtLibs.filter(QStringLiteral("Qt6Core"), Qt::CaseInsensitive)
+ dependentQtLibs.filter(QStringLiteral("Qt5WebKit"), Qt::CaseInsensitive);
for (const QString &qtLib : qtLibs) {
QStringList icuLibs = findDependentLibraries(qtLib, options.platform, errorMessage).filter(QStringLiteral("ICU"), Qt::CaseInsensitive);
QStringList icuLibs = findDependentLibraries(qtLib, errorMessage).filter(QStringLiteral("ICU"), Qt::CaseInsensitive);
if (!icuLibs.isEmpty()) {
// Find out the ICU version to add the data library icudtXX.dll, which does not show
// as a dependency.
@ -1456,7 +1437,7 @@ static DeployResult deploy(const Options &options, const QMap<QString, QString>
}
if (options.platform.testFlag(WindowsBased) && !qtGuiLibrary.isEmpty()) {
const QStringList guiLibraries = findDependentLibraries(qtGuiLibrary, options.platform, errorMessage);
const QStringList guiLibraries = findDependentLibraries(qtGuiLibrary, errorMessage);
const bool dependsOnOpenGl = !guiLibraries.filter(QStringLiteral("opengl32"), Qt::CaseInsensitive).isEmpty();
if (options.softwareRasterizer && !dependsOnOpenGl) {
const QFileInfo softwareRasterizer(qtBinDir + slash + QStringLiteral("opengl32sw") + QLatin1StringView(windowsSharedLibrarySuffix));

View File

@ -2,7 +2,6 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "utils.h"
#include "elfreader.h"
#include <QtCore/QString>
#include <QtCore/QDebug>
@ -95,7 +94,7 @@ QStringList findSharedLibraries(const QDir &directory, Platform platform,
nameFilter += u'*';
if (debugMatchMode == MatchDebug && platformHasDebugSuffix(platform))
nameFilter += u'd';
nameFilter += sharedLibrarySuffix(platform);
nameFilter += sharedLibrarySuffix();
QStringList result;
QString errorMessage;
const QFileInfoList &dlls = directory.entryInfoList(QStringList(nameFilter), QDir::Files);
@ -553,37 +552,6 @@ bool updateFile(const QString &sourceFileName, const QStringList &nameFilters,
return true;
}
bool readElfExecutable(const QString &elfExecutableFileName, QString *errorMessage,
QStringList *dependentLibraries, unsigned *wordSize,
bool *isDebug)
{
ElfReader elfReader(elfExecutableFileName);
const ElfData data = elfReader.readHeaders();
if (data.sectionHeaders.isEmpty()) {
*errorMessage = QStringLiteral("Unable to read ELF binary \"")
+ QDir::toNativeSeparators(elfExecutableFileName) + QStringLiteral("\": ")
+ elfReader.errorString();
return false;
}
if (wordSize)
*wordSize = data.elfclass == Elf_ELFCLASS64 ? 64 : 32;
if (dependentLibraries) {
dependentLibraries->clear();
const QList<QByteArray> libs = elfReader.dependencies();
if (libs.isEmpty()) {
*errorMessage = QStringLiteral("Unable to read dependenices of ELF binary \"")
+ QDir::toNativeSeparators(elfExecutableFileName) + QStringLiteral("\": ")
+ elfReader.errorString();
return false;
}
for (const QByteArray &l : libs)
dependentLibraries->push_back(QString::fromLocal8Bit(l));
}
if (isDebug)
*isDebug = data.symbolsType != UnknownSymbols && data.symbolsType != NoSymbols;
return true;
}
#ifdef Q_OS_WIN
static inline QString stringFromRvaPtr(const void *rvaPtr)

View File

@ -20,7 +20,6 @@ QT_BEGIN_NAMESPACE
enum PlatformFlag {
// OS
WindowsBased = 0x00001,
UnixBased = 0x00002,
// CPU
IntelBased = 0x00010,
ArmBased = 0x00020,
@ -34,7 +33,6 @@ enum PlatformFlag {
WindowsDesktopMinGW = WindowsBased + IntelBased + MinGW,
WindowsDesktopClangMsvc = WindowsBased + IntelBased + ClangMsvc,
WindowsDesktopClangMinGW = WindowsBased + IntelBased + ClangMinGW,
Unix = UnixBased,
UnknownPlatform
};
@ -137,9 +135,8 @@ inline QString normalizeFileName(const QString &name) { return name; }
#endif // !Q_OS_WIN
static const char windowsSharedLibrarySuffix[] = ".dll";
static const char unixSharedLibrarySuffix[] = ".so";
inline QString sharedLibrarySuffix(Platform platform) { return QLatin1StringView((platform & WindowsBased) ? windowsSharedLibrarySuffix : unixSharedLibrarySuffix); }
inline QString sharedLibrarySuffix() { return QLatin1StringView(windowsSharedLibrarySuffix); }
bool isBuildDirectory(Platform platform, const QString &dirName);
bool createSymbolicLink(const QFileInfo &source, const QString &target, QString *errorMessage);
@ -170,19 +167,6 @@ bool runProcess(const QString &binary, const QStringList &args,
bool readPeExecutable(const QString &peExecutableFileName, QString *errorMessage,
QStringList *dependentLibraries = 0, unsigned *wordSize = 0,
bool *isDebug = 0, bool isMinGW = false, unsigned short *machineArch = nullptr);
bool readElfExecutable(const QString &elfExecutableFileName, QString *errorMessage,
QStringList *dependentLibraries = 0, unsigned *wordSize = 0,
bool *isDebug = 0);
inline bool readExecutable(const QString &executableFileName, Platform platform,
QString *errorMessage, QStringList *dependentLibraries = 0,
unsigned *wordSize = 0, bool *isDebug = 0, unsigned short *machineArch = nullptr)
{
return platform == Unix ?
readElfExecutable(executableFileName, errorMessage, dependentLibraries, wordSize, isDebug) :
readPeExecutable(executableFileName, errorMessage, dependentLibraries, wordSize, isDebug,
(platform == WindowsDesktopMinGW), machineArch);
}
#ifdef Q_OS_WIN
# if !defined(IMAGE_FILE_MACHINE_ARM64)
@ -193,10 +177,10 @@ QString getArchString (unsigned short machineArch);
// Return dependent modules of executable files.
inline QStringList findDependentLibraries(const QString &executableFileName, Platform platform, QString *errorMessage)
inline QStringList findDependentLibraries(const QString &executableFileName, QString *errorMessage)
{
QStringList result;
readExecutable(executableFileName, platform, errorMessage, &result);
readPeExecutable(executableFileName, errorMessage, &result);
return result;
}