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
parse(DataExtractor IndexData,uint32_t * OffsetPtr)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
dump(raw_ostream & OS) const28 void DWARFUnitIndex::Header::dump(raw_ostream &OS) const {
29 OS << format("version = %u slots = %u\n\n", Version, NumBuckets);
30 }
31
parse(DataExtractor IndexData)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
parseImpl(DataExtractor IndexData)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
getColumnHeader(DWARFSectionKind DS)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
dump(raw_ostream & OS) const121 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 *
getOffset(DWARFSectionKind Sec) const148 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 *
getOffset() const156 DWARFUnitIndex::Entry::getOffset() const {
157 return &Contributions[Index->InfoColumn];
158 }
159
160 const DWARFUnitIndex::Entry *
getFromOffset(uint32_t Offset) const161 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