Commit cb7cca79 authored by Tobias Hunger's avatar Tobias Hunger
Browse files

Detect ABIs of static libs

parent f20591e7
......@@ -34,11 +34,11 @@
#include "abi.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QFile>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QSysInfo>
#include <QtCore/QDebug>
namespace ProjectExplorer {
......@@ -63,6 +63,48 @@ static Abi macAbiForCpu(quint32 type) {
}
}
static QList<Abi> parseCoffHeader(const QByteArray &data)
{
QList<Abi> result;
if (data.size() < 20)
return result;
Abi::Architecture arch = Abi::UnknownArchitecture;
Abi::OSFlavor flavor = Abi::UnknownFlavor;
int width = 0;
// Get machine field from COFF file header
quint16 machine = (data.at(1) << 8) + data.at(0);
switch (machine) {
case 0x8664: // x86_64
arch = Abi::X86Architecture;
width = 64;
break;
case 0x014c: // i386
arch = Abi::X86Architecture;
width = 32;
break;
case 0x0200: // ia64
arch = Abi::ItaniumArchitecture;
width = 64;
break;
}
if (data.size() >= 68) {
// Get Major and Minor Image Version from optional header fields
quint32 image = (data.at(67) << 24) + (data.at(66) << 16) + (data.at(65) << 8) + data.at(64);
if (image == 1) // Image is 1 for mingw and higher for MSVC (4.something in some encoding)
flavor = Abi::WindowsMSysFlavor;
else
flavor = Abi::WindowsMsvcFlavor;
}
if (arch != Abi::UnknownArchitecture && width != 0)
result.append(Abi(arch, Abi::WindowsOS, flavor, Abi::PEFormat, width));
return result;
}
static QList<Abi> abiOf(const QByteArray &data)
{
QList<Abi> result;
......@@ -119,39 +161,8 @@ static QList<Abi> abiOf(const QByteArray &data)
// Windows PE
// Windows can have its magic bytes everywhere...
int pePos = data.indexOf(QByteArray("PE\0\0", 4));
if (pePos >= 0 && pePos + 72 < data.size()) {
Abi::Architecture arch = Abi::UnknownArchitecture;
Abi::OSFlavor flavor = Abi::UnknownFlavor;
int width = 0;
// Get machine field from COFF file header
quint16 machine = (data.at(pePos + 5) << 8) + data.at(pePos + 4);
switch (machine) {
case 0x8664: // x86_64
arch = Abi::X86Architecture;
width = 64;
break;
case 0x014c: // i386
arch = Abi::X86Architecture;
width = 32;
break;
case 0x0200: // ia64
arch = Abi::ItaniumArchitecture;
width = 64;
break;
}
// Get Major and Minor Image Version from optional header fields
quint32 image = (data.at(pePos + 71) << 24) + (data.at(pePos + 70) << 16)
+ (data.at(pePos + 69) << 8) + data.at(pePos + 68);
if (image == 1) // Image is 1 for mingw and 4.something for MSVC
flavor = Abi::WindowsMSysFlavor;
else
flavor = Abi::WindowsMsvcFlavor;
if (arch != Abi::UnknownArchitecture && flavor != Abi::UnknownFlavor && width != 0)
result.append(Abi(arch, Abi::WindowsOS, flavor, Abi::PEFormat, width));
}
if (pePos >= 0)
result = parseCoffHeader(data.mid(pePos + 4));
}
return result;
}
......@@ -454,6 +465,8 @@ QList<Abi> Abi::abisOfBinary(const QString &path)
if (!f.exists())
return result;
bool windowsStatic = path.endsWith(QLatin1String(".lib"));
f.open(QFile::ReadOnly);
QByteArray data = f.read(1024);
if (data.size() >= 67
......@@ -467,7 +480,7 @@ QList<Abi> Abi::abisOfBinary(const QString &path)
quint64 offset = 8;
while (!data.isEmpty()) {
if (data.at(58) != 0x60 || data.at(59) != 0x0a) {
if ((data.at(58) != 0x60 || data.at(59) != 0x0a)) {
qWarning() << path << ": Thought it was an ar-file, but it is not!";
break;
}
......@@ -478,13 +491,18 @@ QList<Abi> Abi::abisOfBinary(const QString &path)
fileNameOffset = fileName.mid(3).toInt();
const QString fileLength = QString::fromAscii(data.mid(48, 10));
data = data.mid(60 + fileNameOffset);
int toSkip = 60 + fileNameOffset;
offset += fileLength.toInt() + 60 /* header */;
result = abiOf(data);
if (windowsStatic) {
if (fileName == QLatin1String("/0 "))
result = parseCoffHeader(data.mid(toSkip, 20));
} else {
result = abiOf(data.mid(toSkip));
}
if (!result.isEmpty())
break;
f.seek(offset);
f.seek(offset + (offset % 2)); // ar is 2 byte alligned
data = f.read(1024);
}
} else {
......
......@@ -1589,9 +1589,10 @@ QString QtVersion::qtCorePath() const
{
QList<QDir> dirs;
dirs << QDir(libraryInstallPath()) << QDir(versionInfo().value(QLatin1String("QT_INSTALL_BINS")));
QFileInfoList staticLibs;
foreach (const QDir &d, dirs) {
QFileInfoList infoList = d.entryInfoList();
QFileInfoList staticLibs;
foreach (const QFileInfo &info, infoList) {
const QString file = info.fileName();
if (info.isDir()
......@@ -1605,7 +1606,7 @@ QString QtVersion::qtCorePath() const
if (file.startsWith(QLatin1String("libQtCore"))
|| file.startsWith(QLatin1String("QtCore"))) {
// Only handle static libs if we can not find dynamic ones:
if (file.endsWith(".a"))
if (file.endsWith(".a") || file.endsWith(".lib"))
staticLibs.append(info);
else if (file.endsWith(QLatin1String(".dll"))
|| file.endsWith(QString::fromLatin1(".so.") + qtVersionString()))
......@@ -1613,10 +1614,10 @@ QString QtVersion::qtCorePath() const
}
}
}
// Return path to first static library found:
if (!staticLibs.isEmpty())
return staticLibs.at(0).absoluteFilePath();
}
// Return path to first static library found:
if (!staticLibs.isEmpty())
return staticLibs.at(0).absoluteFilePath();
return QString();
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment