Line data Source code
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 : #include "llvm/ADT/STLExtras.h"
12 : #include "llvm/ADT/StringRef.h"
13 : #include "llvm/Support/ErrorHandling.h"
14 : #include "llvm/Support/Format.h"
15 : #include "llvm/Support/raw_ostream.h"
16 : #include <cinttypes>
17 : #include <cstdint>
18 :
19 : using namespace llvm;
20 :
21 87 : bool DWARFUnitIndex::Header::parse(DataExtractor IndexData,
22 : uint32_t *OffsetPtr) {
23 87 : if (!IndexData.isValidOffsetForDataOfSize(*OffsetPtr, 16))
24 : return false;
25 29 : Version = IndexData.getU32(OffsetPtr);
26 29 : NumColumns = IndexData.getU32(OffsetPtr);
27 29 : NumUnits = IndexData.getU32(OffsetPtr);
28 29 : NumBuckets = IndexData.getU32(OffsetPtr);
29 29 : return Version <= 2;
30 : }
31 :
32 16 : void DWARFUnitIndex::Header::dump(raw_ostream &OS) const {
33 32 : OS << format("version = %u slots = %u\n\n", Version, NumBuckets);
34 16 : }
35 :
36 87 : bool DWARFUnitIndex::parse(DataExtractor IndexData) {
37 87 : bool b = parseImpl(IndexData);
38 87 : if (!b) {
39 : // Make sure we don't try to dump anything
40 58 : Header.NumBuckets = 0;
41 : // Release any partially initialized data.
42 : ColumnKinds.reset();
43 : Rows.reset();
44 : }
45 87 : return b;
46 : }
47 :
48 87 : bool DWARFUnitIndex::parseImpl(DataExtractor IndexData) {
49 87 : uint32_t Offset = 0;
50 87 : if (!Header.parse(IndexData, &Offset))
51 : return false;
52 :
53 29 : if (!IndexData.isValidOffsetForDataOfSize(
54 29 : Offset, Header.NumBuckets * (8 + 4) +
55 29 : (2 * Header.NumUnits + 1) * 4 * Header.NumColumns))
56 : return false;
57 :
58 29 : Rows = llvm::make_unique<Entry[]>(Header.NumBuckets);
59 : auto Contribs =
60 29 : llvm::make_unique<Entry::SectionContribution *[]>(Header.NumUnits);
61 58 : ColumnKinds = llvm::make_unique<DWARFSectionKind[]>(Header.NumColumns);
62 :
63 : // Read Hash Table of Signatures
64 172 : for (unsigned i = 0; i != Header.NumBuckets; ++i)
65 286 : Rows[i].Signature = IndexData.getU64(&Offset);
66 :
67 : // Read Parallel Table of Indexes
68 172 : for (unsigned i = 0; i != Header.NumBuckets; ++i) {
69 143 : auto Index = IndexData.getU32(&Offset);
70 143 : if (!Index)
71 : continue;
72 60 : Rows[i].Index = this;
73 : Rows[i].Contributions =
74 120 : llvm::make_unique<Entry::SectionContribution[]>(Header.NumColumns);
75 120 : Contribs[Index - 1] = Rows[i].Contributions.get();
76 : }
77 :
78 : // Read the Column Headers
79 141 : for (unsigned i = 0; i != Header.NumColumns; ++i) {
80 224 : ColumnKinds[i] = static_cast<DWARFSectionKind>(IndexData.getU32(&Offset));
81 112 : if (ColumnKinds[i] == InfoColumnKind) {
82 29 : if (InfoColumn != -1)
83 : return false;
84 29 : InfoColumn = i;
85 : }
86 : }
87 :
88 29 : if (InfoColumn == -1)
89 : return false;
90 :
91 : // Read Table of Section Offsets
92 89 : for (unsigned i = 0; i != Header.NumUnits; ++i) {
93 120 : auto *Contrib = Contribs[i];
94 292 : for (unsigned i = 0; i != Header.NumColumns; ++i)
95 232 : Contrib[i].Offset = IndexData.getU32(&Offset);
96 : }
97 :
98 : // Read Table of Section Sizes
99 89 : for (unsigned i = 0; i != Header.NumUnits; ++i) {
100 120 : auto *Contrib = Contribs[i];
101 292 : for (unsigned i = 0; i != Header.NumColumns; ++i)
102 232 : Contrib[i].Length = IndexData.getU32(&Offset);
103 : }
104 :
105 : return true;
106 : }
107 :
108 60 : StringRef DWARFUnitIndex::getColumnHeader(DWARFSectionKind DS) {
109 : #define CASE(DS) \
110 : case DW_SECT_##DS: \
111 : return #DS;
112 60 : switch (DS) {
113 10 : CASE(INFO);
114 6 : CASE(TYPES);
115 16 : CASE(ABBREV);
116 14 : CASE(LINE);
117 0 : CASE(LOC);
118 14 : CASE(STR_OFFSETS);
119 0 : CASE(MACINFO);
120 0 : CASE(MACRO);
121 : }
122 0 : llvm_unreachable("unknown DWARFSectionKind");
123 : }
124 :
125 16 : void DWARFUnitIndex::dump(raw_ostream &OS) const {
126 16 : if (!*this)
127 : return;
128 :
129 16 : Header.dump(OS);
130 16 : OS << "Index Signature ";
131 76 : for (unsigned i = 0; i != Header.NumColumns; ++i)
132 120 : OS << ' ' << left_justify(getColumnHeader(ColumnKinds[i]), 24);
133 16 : OS << "\n----- ------------------";
134 76 : for (unsigned i = 0; i != Header.NumColumns; ++i)
135 60 : OS << " ------------------------";
136 : OS << '\n';
137 113 : for (unsigned i = 0; i != Header.NumBuckets; ++i) {
138 97 : auto &Row = Rows[i];
139 97 : if (auto *Contribs = Row.Contributions.get()) {
140 74 : OS << format("%5u 0x%016" PRIx64 " ", i + 1, Row.Signature);
141 177 : for (unsigned i = 0; i != Header.NumColumns; ++i) {
142 140 : auto &Contrib = Contribs[i];
143 140 : OS << format("[0x%08x, 0x%08x) ", Contrib.Offset,
144 280 : Contrib.Offset + Contrib.Length);
145 : }
146 : OS << '\n';
147 : }
148 : }
149 : }
150 :
151 : const DWARFUnitIndex::Entry::SectionContribution *
152 168 : DWARFUnitIndex::Entry::getOffset(DWARFSectionKind Sec) const {
153 : uint32_t i = 0;
154 505 : for (; i != Index->Header.NumColumns; ++i)
155 998 : if (Index->ColumnKinds[i] == Sec)
156 162 : return &Contributions[i];
157 : return nullptr;
158 : }
159 :
160 : const DWARFUnitIndex::Entry::SectionContribution *
161 41 : DWARFUnitIndex::Entry::getOffset() const {
162 82 : return &Contributions[Index->InfoColumn];
163 : }
164 :
165 : const DWARFUnitIndex::Entry *
166 116 : DWARFUnitIndex::getFromOffset(uint32_t Offset) const {
167 116 : if (OffsetLookup.empty()) {
168 208 : for (uint32_t i = 0; i != Header.NumBuckets; ++i)
169 226 : if (Rows[i].Contributions)
170 45 : OffsetLookup.push_back(&Rows[i]);
171 : llvm::sort(OffsetLookup, [&](Entry *E1, Entry *E2) {
172 50 : return E1->Contributions[InfoColumn].Offset <
173 51 : E2->Contributions[InfoColumn].Offset;
174 : });
175 : }
176 : auto I =
177 : llvm::upper_bound(OffsetLookup, Offset, [&](uint32_t Offset, Entry *E2) {
178 146 : return Offset < E2->Contributions[InfoColumn].Offset;
179 116 : });
180 116 : if (I == OffsetLookup.begin())
181 : return nullptr;
182 : --I;
183 41 : const auto *E = *I;
184 41 : const auto &InfoContrib = E->Contributions[InfoColumn];
185 41 : if ((InfoContrib.Offset + InfoContrib.Length) <= Offset)
186 0 : return nullptr;
187 : return E;
188 : }
189 :
190 4 : const DWARFUnitIndex::Entry *DWARFUnitIndex::getFromHash(uint64_t S) const {
191 4 : uint64_t Mask = Header.NumBuckets - 1;
192 :
193 4 : auto H = S & Mask;
194 4 : auto HP = ((S >> 32) & Mask) | 1;
195 4 : while (Rows[H].getSignature() != S && Rows[H].getSignature() != 0)
196 0 : H = (H + HP) & Mask;
197 :
198 4 : if (Rows[H].getSignature() != S)
199 0 : return nullptr;
200 :
201 : return &Rows[H];
202 : }
|