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 "config-elf-dissector.h" 0019 #include <elf/elffile.h> 0020 #include <elf/elfgnuhashsection.h> 0021 #include <elf/elfhashsection.h> 0022 #include <elf/elfsymboltablesection.h> 0023 0024 #include <QtTest/qtest.h> 0025 #include <QObject> 0026 0027 #include <elf.h> 0028 #include <algorithm> 0029 0030 class ElfHashTest: public QObject 0031 { 0032 Q_OBJECT 0033 private slots: 0034 void testHashSection() 0035 { 0036 ElfFile f(QStringLiteral(BINDIR "/elf-dissector")); 0037 QVERIFY(f.open(QFile::ReadOnly)); 0038 QVERIFY(f.isValid()); 0039 0040 const auto hashIndex = f.indexOfSection(SHT_HASH); 0041 const auto gnuHashIndex = f.indexOfSection(SHT_GNU_HASH); 0042 QVERIFY(hashIndex >= 0 || gnuHashIndex >= 0); 0043 if (hashIndex < 0) 0044 return; 0045 0046 const auto hashSection = f.section<ElfHashSection>(hashIndex); 0047 QVERIFY(hashSection); 0048 0049 const auto symTab = hashSection->linkedSection<ElfSymbolTableSection>(); 0050 QVERIFY(symTab); 0051 0052 QVERIFY(hashSection->bucketCount() > 0); 0053 QCOMPARE((uint64_t)hashSection->chainCount(), symTab->header()->entryCount()); 0054 // EXPECTED_FAIL: the .hash section is broken with --hash-style=both and gold of binutils <= 2.24 (works with the old ld, fixed in 2.25) 0055 #if BINUTILS_VERSION >= BINUTILS_VERSION_CHECK(2, 25) 0056 for (uint32_t i = 0; i < symTab->header()->entryCount(); ++i) { 0057 const auto entry = symTab->entry(i); 0058 if (strcmp(entry->name(), "") == 0) 0059 continue; 0060 QCOMPARE(hashSection->lookup(entry->name()), entry); 0061 } 0062 #endif 0063 0064 const auto hist = hashSection->histogram(); 0065 const uint32_t sum = std::accumulate(hist.begin(), hist.end(), 0); 0066 QCOMPARE(sum, hashSection->bucketCount()); 0067 } 0068 0069 void testGnuHashSection() 0070 { 0071 ElfFile f(QStringLiteral(BINDIR "/elf-dissector")); 0072 QVERIFY(f.open(QFile::ReadOnly)); 0073 QVERIFY(f.isValid()); 0074 0075 const auto hashIndex = f.indexOfSection(SHT_GNU_HASH); 0076 const auto sysvHashIndex = f.indexOfSection(SHT_HASH); 0077 QVERIFY(hashIndex >= 0 || sysvHashIndex >= 0); 0078 if (hashIndex < 0) 0079 return; 0080 0081 const auto hashSection = f.section<ElfGnuHashSection>(hashIndex); 0082 QVERIFY(hashSection); 0083 0084 const auto symTab = hashSection->linkedSection<ElfSymbolTableSection>(); 0085 QVERIFY(symTab); 0086 0087 QVERIFY(hashSection->bucketCount() > 0); 0088 QVERIFY(hashSection->symbolIndex() > 0); 0089 QVERIFY(hashSection->symbolIndex() < symTab->header()->entryCount()); 0090 QCOMPARE((uint64_t)hashSection->chainCount(), symTab->header()->entryCount() - hashSection->symbolIndex()); 0091 0092 for (uint32_t i = hashSection->symbolIndex(); i < symTab->header()->entryCount(); ++i) { 0093 const auto entry = symTab->entry(i); 0094 QCOMPARE(hashSection->lookup(entry->name()), entry); 0095 } 0096 0097 const auto hist = hashSection->histogram(); 0098 const uint32_t sum = std::accumulate(hist.begin(), hist.end(), 0); 0099 QCOMPARE(sum, hashSection->bucketCount()); 0100 } 0101 }; 0102 0103 QTEST_MAIN(ElfHashTest) 0104 0105 #include "elfhashtest.moc"