dwarfdump: Use the index to find the right abbrev offset in DWP files
[oota-llvm.git] / lib / DebugInfo / DWARF / DWARFUnitIndex.cpp
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 }