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"