File indexing completed on 2024-04-28 05:41:05
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 <dwarf/dwarfdie.h> 0019 #include <dwarf/dwarfcudie.h> 0020 #include <dwarf/dwarfinfo.h> 0021 #include <dwarf/dwarfranges.h> 0022 #include <dwarf/dwarfaddressranges.h> 0023 0024 #include <QtTest/qtest.h> 0025 #include <QObject> 0026 0027 #include <dwarf.h> 0028 0029 class DwarfDieTest : public QObject 0030 { 0031 Q_OBJECT 0032 private slots: 0033 void testCU() 0034 { 0035 ElfFile f(QStringLiteral(BINDIR "single-executable")); 0036 QVERIFY(f.open(QFile::ReadOnly)); 0037 QVERIFY(f.dwarfInfo()); 0038 QVERIFY(f.dwarfInfo()->compilationUnits().size() > 0); 0039 0040 DwarfDie *cu = nullptr; 0041 foreach (auto die, f.dwarfInfo()->compilationUnits()) { 0042 if (die->name().contains("single-executable")) { 0043 cu = die; 0044 break; 0045 } 0046 } 0047 0048 QVERIFY(cu); 0049 QCOMPARE(cu->tag(), (Dwarf_Half)DW_TAG_compile_unit); 0050 QVERIFY(cu->children().size() > 0); 0051 QVERIFY(cu->attributes().size() > 0); 0052 } 0053 0054 void testAttribute_AT_ranges() 0055 { 0056 ElfFile f(QStringLiteral(BINDIR "single-executable")); 0057 QVERIFY(f.open(QFile::ReadOnly)); 0058 QVERIFY(f.dwarfInfo()); 0059 QVERIFY(f.dwarfInfo()->compilationUnits().size() > 0); 0060 0061 foreach (auto cu, f.dwarfInfo()->compilationUnits()) { 0062 const auto lowPC = cu->attribute(DW_AT_low_pc); 0063 const auto ranges = cu->attribute(DW_AT_ranges); 0064 if (lowPC.isNull() && ranges.isNull()) 0065 continue; 0066 0067 QVERIFY(lowPC.isNull() != ranges.isNull()); // exactly one of them must be present 0068 if (lowPC.isNull()) { 0069 const auto r = ranges.value<DwarfRanges>(); 0070 QVERIFY(r.isValid()); 0071 QVERIFY(r.size() > 0); 0072 } else { 0073 const auto textSection = f.section<ElfSection>(f.indexOfSection(".text")); 0074 QVERIFY(lowPC.value<uint64_t>() >= textSection->header()->virtualAddress()); 0075 QVERIFY(lowPC.value<uint64_t>() < textSection->header()->virtualAddress() + textSection->header()->size()); 0076 } 0077 } 0078 } 0079 0080 void testArange() 0081 { 0082 ElfFile f(QStringLiteral(BINDIR "single-executable")); 0083 QVERIFY(f.open(QFile::ReadOnly)); 0084 QVERIFY(f.dwarfInfo()); 0085 QVERIFY(f.dwarfInfo()->addressRanges()->isValid()); 0086 0087 QVector<DwarfDie*> dieQueue; 0088 dieQueue.resize(f.dwarfInfo()->compilationUnits().size()); 0089 auto cus = f.dwarfInfo()->compilationUnits(); 0090 std::copy(cus.constBegin(), cus.constEnd(), dieQueue.begin()); 0091 while (!dieQueue.isEmpty()) { 0092 const auto die = dieQueue.takeFirst(); 0093 dieQueue += die->children(); 0094 0095 const auto lowPC = die->attribute(DW_AT_low_pc).toULongLong(); 0096 if (lowPC <= 0) 0097 continue; 0098 0099 const auto lookupCU = f.dwarfInfo()->addressRanges()->compilationUnitForAddress(lowPC); 0100 auto cuDie = die; 0101 while (cuDie && cuDie->tag() != DW_TAG_compile_unit) 0102 cuDie = cuDie->parentDie(); 0103 QCOMPARE(cuDie, lookupCU); 0104 0105 if (die->tag() == DW_TAG_compile_unit) 0106 continue; 0107 0108 const auto lookupDie = f.dwarfInfo()->addressRanges()->dieForAddress(lowPC); 0109 QVERIFY(die == lookupDie || lowPC == lookupDie->attribute(DW_AT_low_pc).toULongLong()); 0110 } 0111 } 0112 }; 0113 0114 QTEST_MAIN(DwarfDieTest) 0115 0116 #include "dwarfdietest.moc"