1 //===-- DWARFUnitIndex.cpp ------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" 11 12 #include "llvm/ADT/StringRef.h" 13 #include "llvm/Support/ErrorHandling.h" 14 15 namespace llvm { 16 17 bool DWARFUnitIndex::Header::parse(DataExtractor IndexData, 18 uint32_t *OffsetPtr) { 19 if (!IndexData.isValidOffsetForDataOfSize(*OffsetPtr, 16)) 20 return false; 21 Version = IndexData.getU32(OffsetPtr); 22 NumColumns = IndexData.getU32(OffsetPtr); 23 NumUnits = IndexData.getU32(OffsetPtr); 24 NumBuckets = IndexData.getU32(OffsetPtr); 25 return Version <= 2; 26 } 27 28 void DWARFUnitIndex::Header::dump(raw_ostream &OS) const { 29 OS << format("version = %u slots = %u\n\n", Version, NumBuckets); 30 } 31 32 bool DWARFUnitIndex::parse(DataExtractor IndexData) { 33 uint32_t Offset = 0; 34 if (!Header.parse(IndexData, &Offset)) 35 return false; 36 37 if (!IndexData.isValidOffsetForDataOfSize( 38 Offset, Header.NumBuckets * (8 + 4) + 39 (2 * Header.NumUnits + 1) * 4 * Header.NumColumns)) 40 return false; 41 42 Rows = llvm::make_unique<Entry[]>(Header.NumBuckets); 43 auto Contribs = 44 llvm::make_unique<Entry::SectionContribution *[]>(Header.NumUnits); 45 ColumnKinds = llvm::make_unique<DWARFSectionKind[]>(Header.NumColumns); 46 47 // Read Hash Table of Signatures 48 for (unsigned i = 0; i != Header.NumBuckets; ++i) 49 Rows[i].Signature = IndexData.getU64(&Offset); 50 51 // Read Parallel Table of Indexes 52 for (unsigned i = 0; i != Header.NumBuckets; ++i) { 53 auto Index = IndexData.getU32(&Offset); 54 if (!Index) 55 continue; 56 Rows[i].Index = this; 57 Rows[i].Contributions = 58 llvm::make_unique<Entry::SectionContribution[]>(Header.NumColumns); 59 Contribs[Index - 1] = Rows[i].Contributions.get(); 60 } 61 62 // Read the Column Headers 63 for (unsigned i = 0; i != Header.NumColumns; ++i) { 64 ColumnKinds[i] = static_cast<DWARFSectionKind>(IndexData.getU32(&Offset)); 65 if (ColumnKinds[i] == DW_SECT_INFO || ColumnKinds[i] == DW_SECT_TYPES) { 66 if (InfoColumn != -1) 67 return false; 68 InfoColumn = i; 69 } 70 } 71 72 if (InfoColumn == -1) 73 return false; 74 75 // Read Table of Section Offsets 76 for (unsigned i = 0; i != Header.NumUnits; ++i) { 77 auto *Contrib = Contribs[i]; 78 for (unsigned i = 0; i != Header.NumColumns; ++i) 79 Contrib[i].Offset = IndexData.getU32(&Offset); 80 } 81 82 // Read Table of Section Sizes 83 for (unsigned i = 0; i != Header.NumUnits; ++i) { 84 auto *Contrib = Contribs[i]; 85 for (unsigned i = 0; i != Header.NumColumns; ++i) 86 Contrib[i].Length = IndexData.getU32(&Offset); 87 } 88 89 return true; 90 } 91 92 StringRef DWARFUnitIndex::getColumnHeader(DWARFSectionKind DS) { 93 #define CASE(DS) \ 94 case DW_SECT_##DS: \ 95 return #DS; 96 switch (DS) { 97 CASE(INFO); 98 CASE(TYPES); 99 CASE(ABBREV); 100 CASE(LINE); 101 CASE(LOC); 102 CASE(STR_OFFSETS); 103 CASE(MACINFO); 104 CASE(MACRO); 105 } 106 llvm_unreachable("unknown DWARFSectionKind"); 107 } 108 109 void DWARFUnitIndex::dump(raw_ostream &OS) const { 110 Header.dump(OS); 111 OS << "Index Signature "; 112 for (unsigned i = 0; i != Header.NumColumns; ++i) 113 OS << ' ' << left_justify(getColumnHeader(ColumnKinds[i]), 24); 114 OS << "\n----- ------------------"; 115 for (unsigned i = 0; i != Header.NumColumns; ++i) 116 OS << " ------------------------"; 117 OS << '\n'; 118 for (unsigned i = 0; i != Header.NumBuckets; ++i) { 119 auto &Row = Rows[i]; 120 if (auto *Contribs = Row.Contributions.get()) { 121 OS << format("%5u 0x%016" PRIx64 " ", i, Row.Signature); 122 for (unsigned i = 0; i != Header.NumColumns; ++i) { 123 auto &Contrib = Contribs[i]; 124 OS << format("[0x%08x, 0x%08x) ", Contrib.Offset, 125 Contrib.Offset + Contrib.Length); 126 } 127 OS << '\n'; 128 } 129 } 130 } 131 132 const DWARFUnitIndex::Entry::SectionContribution * 133 DWARFUnitIndex::Entry::getOffset(DWARFSectionKind Sec) const { 134 uint32_t i = 0; 135 for (; i != Index->Header.NumColumns; ++i) 136 if (Index->ColumnKinds[i] == Sec) 137 return &Contributions[i]; 138 return nullptr; 139 } 140 const DWARFUnitIndex::Entry::SectionContribution * 141 DWARFUnitIndex::Entry::getOffset() const { 142 return &Contributions[Index->InfoColumn]; 143 } 144 145 const DWARFUnitIndex::Entry * 146 DWARFUnitIndex::getFromOffset(uint32_t Offset) const { 147 for (uint32_t i = 0; i != Header.NumBuckets; ++i) 148 if (const auto &Contribs = Rows[i].Contributions) 149 if (Contribs[InfoColumn].Offset == Offset) 150 return &Rows[i]; 151 return nullptr; 152 } 153 } 154