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