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 bool b = parseImpl(IndexData); 34 if (!b) { 35 // Make sure we don't try to dump anything 36 Header.NumBuckets = 0; 37 // Release any partially initialized data. 38 ColumnKinds.reset(); 39 Rows.reset(); 40 } 41 return b; 42 } 43 44 bool DWARFUnitIndex::parseImpl(DataExtractor IndexData) { 45 uint32_t Offset = 0; 46 if (!Header.parse(IndexData, &Offset)) 47 return false; 48 49 if (!IndexData.isValidOffsetForDataOfSize( 50 Offset, Header.NumBuckets * (8 + 4) + 51 (2 * Header.NumUnits + 1) * 4 * Header.NumColumns)) 52 return false; 53 54 Rows = llvm::make_unique<Entry[]>(Header.NumBuckets); 55 auto Contribs = 56 llvm::make_unique<Entry::SectionContribution *[]>(Header.NumUnits); 57 ColumnKinds = llvm::make_unique<DWARFSectionKind[]>(Header.NumColumns); 58 59 // Read Hash Table of Signatures 60 for (unsigned i = 0; i != Header.NumBuckets; ++i) 61 Rows[i].Signature = IndexData.getU64(&Offset); 62 63 // Read Parallel Table of Indexes 64 for (unsigned i = 0; i != Header.NumBuckets; ++i) { 65 auto Index = IndexData.getU32(&Offset); 66 if (!Index) 67 continue; 68 Rows[i].Index = this; 69 Rows[i].Contributions = 70 llvm::make_unique<Entry::SectionContribution[]>(Header.NumColumns); 71 Contribs[Index - 1] = Rows[i].Contributions.get(); 72 } 73 74 // Read the Column Headers 75 for (unsigned i = 0; i != Header.NumColumns; ++i) { 76 ColumnKinds[i] = static_cast<DWARFSectionKind>(IndexData.getU32(&Offset)); 77 if (ColumnKinds[i] == InfoColumnKind) { 78 if (InfoColumn != -1) 79 return false; 80 InfoColumn = i; 81 } 82 } 83 84 if (InfoColumn == -1) 85 return false; 86 87 // Read Table of Section Offsets 88 for (unsigned i = 0; i != Header.NumUnits; ++i) { 89 auto *Contrib = Contribs[i]; 90 for (unsigned i = 0; i != Header.NumColumns; ++i) 91 Contrib[i].Offset = IndexData.getU32(&Offset); 92 } 93 94 // Read Table of Section Sizes 95 for (unsigned i = 0; i != Header.NumUnits; ++i) { 96 auto *Contrib = Contribs[i]; 97 for (unsigned i = 0; i != Header.NumColumns; ++i) 98 Contrib[i].Length = IndexData.getU32(&Offset); 99 } 100 101 return true; 102 } 103 104 StringRef DWARFUnitIndex::getColumnHeader(DWARFSectionKind DS) { 105 #define CASE(DS) \ 106 case DW_SECT_##DS: \ 107 return #DS; 108 switch (DS) { 109 CASE(INFO); 110 CASE(TYPES); 111 CASE(ABBREV); 112 CASE(LINE); 113 CASE(LOC); 114 CASE(STR_OFFSETS); 115 CASE(MACINFO); 116 CASE(MACRO); 117 } 118 llvm_unreachable("unknown DWARFSectionKind"); 119 } 120 121 void DWARFUnitIndex::dump(raw_ostream &OS) const { 122 if (!Header.NumBuckets) 123 return; 124 125 Header.dump(OS); 126 OS << "Index Signature "; 127 for (unsigned i = 0; i != Header.NumColumns; ++i) 128 OS << ' ' << left_justify(getColumnHeader(ColumnKinds[i]), 24); 129 OS << "\n----- ------------------"; 130 for (unsigned i = 0; i != Header.NumColumns; ++i) 131 OS << " ------------------------"; 132 OS << '\n'; 133 for (unsigned i = 0; i != Header.NumBuckets; ++i) { 134 auto &Row = Rows[i]; 135 if (auto *Contribs = Row.Contributions.get()) { 136 OS << format("%5u 0x%016" PRIx64 " ", i + 1, Row.Signature); 137 for (unsigned i = 0; i != Header.NumColumns; ++i) { 138 auto &Contrib = Contribs[i]; 139 OS << format("[0x%08x, 0x%08x) ", Contrib.Offset, 140 Contrib.Offset + Contrib.Length); 141 } 142 OS << '\n'; 143 } 144 } 145 } 146 147 const DWARFUnitIndex::Entry::SectionContribution * 148 DWARFUnitIndex::Entry::getOffset(DWARFSectionKind Sec) const { 149 uint32_t i = 0; 150 for (; i != Index->Header.NumColumns; ++i) 151 if (Index->ColumnKinds[i] == Sec) 152 return &Contributions[i]; 153 return nullptr; 154 } 155 const DWARFUnitIndex::Entry::SectionContribution * 156 DWARFUnitIndex::Entry::getOffset() const { 157 return &Contributions[Index->InfoColumn]; 158 } 159 160 const DWARFUnitIndex::Entry * 161 DWARFUnitIndex::getFromOffset(uint32_t Offset) const { 162 for (uint32_t i = 0; i != Header.NumBuckets; ++i) 163 if (const auto &Contribs = Rows[i].Contributions) 164 if (Contribs[InfoColumn].Offset == Offset) 165 return &Rows[i]; 166 return nullptr; 167 } 168 } 169