File indexing completed on 2024-04-28 05:41:06
0001 /* 0002 Copyright (C) 2015 Volker Krause <vkrause@kde.org> 0003 0004 This program is free software; you can redistribute it and/or modify it 0005 under the terms of the GNU Library General Public License as published by 0006 the Free Software Foundation; either version 2 of the License, or (at your 0007 option) any later version. 0008 0009 This program is distributed in the hope that it will be useful, but WITHOUT 0010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0011 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 0012 License for more details. 0013 0014 You should have received a copy of the GNU General Public License 0015 along with this program. If not, see <https://www.gnu.org/licenses/>. 0016 */ 0017 0018 #include <elf/elffile.h> 0019 #include <elf/elfsymboltablesection.h> 0020 #include <elf/elfheader.h> 0021 #include <elf/elfpltsection.h> 0022 #include <elf/elfrelocationsection.h> 0023 #include <elf/elfgotsection.h> 0024 0025 #include <QtTest/qtest.h> 0026 #include <QObject> 0027 0028 #include <elf.h> 0029 0030 class ElfFileTest : public QObject 0031 { 0032 Q_OBJECT 0033 private slots: 0034 void testLoad_data() 0035 { 0036 QTest::addColumn<QString>("executable"); 0037 QTest::newRow("single-executable") << QStringLiteral(BINDIR "single-executable"); 0038 QTest::newRow("structures") << QStringLiteral(BINDIR "structures"); 0039 } 0040 void testLoad() 0041 { 0042 QFETCH(QString, executable); 0043 0044 ElfFile f(executable); 0045 QVERIFY(f.open(QFile::ReadOnly)); 0046 QCOMPARE(f.isValid(), true); 0047 QCOMPARE(f.byteOrder(), ELFDATA2LSB); 0048 0049 QVERIFY(f.header()); 0050 QVERIFY(f.header()->programHeaderCount() > 0); 0051 QVERIFY(f.header()->programHeaderEntrySize() > 0); 0052 QVERIFY(f.header()->programHeaderTableOffset() > 0); 0053 QVERIFY(f.header()->sectionHeaderCount() > 0); 0054 QVERIFY(f.header()->sectionHeaderEntrySize() > 0); 0055 QVERIFY(f.header()->sectionHeaderTableOffset() > 0); 0056 0057 QCOMPARE(f.sectionHeaders().isEmpty(), false); 0058 QCOMPARE((uint16_t)f.sectionHeaders().size(), f.header()->sectionHeaderCount()); 0059 QCOMPARE((uint16_t)f.sectionCount(), f.header()->sectionHeaderCount()); 0060 QVERIFY(f.size() > 0); 0061 QVERIFY(f.indexOfSection(".dynsym") >= 0); 0062 QCOMPARE(f.indexOfSection(".doesnotexist"), -1); 0063 0064 QVERIFY(f.dynamicSection()); 0065 QVERIFY(f.dynamicSection()->size() > 0); 0066 QVERIFY(f.symbolTable()); 0067 QVERIFY(f.symbolTable()->size() > 0); 0068 0069 if (f.indexOfSection(".plt") > 0) { 0070 auto pltSection = f.section<ElfPltSection>(f.indexOfSection(".plt")); 0071 QVERIFY(pltSection); 0072 #ifdef Q_OS_FREEBSD 0073 QEXPECT_FAIL("", "FreeBSD no plt entries", Continue); 0074 #endif 0075 QVERIFY(pltSection->header()->entryCount() > 0); 0076 QVERIFY(pltSection->gotSection()); 0077 for (uint i = 1; i < pltSection->header()->entryCount(); ++i) { 0078 auto pltEntry = pltSection->entry(i); 0079 QVERIFY(pltEntry); 0080 QVERIFY(pltEntry->gotEntry()); 0081 } 0082 } 0083 0084 QVERIFY(f.reverseRelocator()); 0085 0086 for (int i = 0; i < f.header()->sectionHeaderCount(); ++i) { 0087 auto shdr = f.sectionHeaders().at(i); 0088 if (shdr->type() == SHT_REL || shdr->type() == SHT_RELA) { 0089 auto section = f.section<ElfRelocationSection>(i); 0090 QVERIFY(section); 0091 QVERIFY(section->header()->entryCount() > 0); 0092 } 0093 0094 if (QByteArray(shdr->name()).startsWith(".got")) { 0095 auto section = f.section<ElfGotSection>(i); 0096 QVERIFY(section); 0097 uint startIndex = 0; 0098 if (strcmp(shdr->name(), ".got.plt") == 0) 0099 startIndex = 3; // the first 3 entries are placeholders for lazy symbol resolution 0100 for (uint i = startIndex; i < section->header()->entryCount(); ++i) { 0101 auto gotEntry = section->entry(i); 0102 QVERIFY(f.reverseRelocator()->find(gotEntry->address())); 0103 } 0104 } 0105 } 0106 0107 #ifdef Q_OS_FREEBSD 0108 // Doesn't seem to have a buildId (w/ clang, anyway) 0109 QVERIFY(f.buildId().isEmpty()); 0110 #else 0111 QVERIFY(f.buildId().size() >= 16); 0112 #endif 0113 0114 QCOMPARE((uint16_t)f.segmentHeaders().size(), f.header()->programHeaderCount()); 0115 } 0116 0117 void testFailedLoad_data() 0118 { 0119 QTest::addColumn<QString>("executable"); 0120 QTest::newRow("not existing") << QStringLiteral("not-existing"); 0121 QTest::newRow("text file") << QStringLiteral(BINDIR "../CMakeCache.txt"); 0122 } 0123 0124 void testFailedLoad() 0125 { 0126 QFETCH(QString, executable); 0127 0128 ElfFile f(executable); 0129 QCOMPARE(f.open(QFile::ReadOnly), false); 0130 QCOMPARE(f.isValid(), false); 0131 } 0132 }; 0133 0134 QTEST_MAIN(ElfFileTest) 0135 0136 #include "elffiletest.moc"