LLVM  4.0.0
DWARFUnitIndex.cpp
Go to the documentation of this file.
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 
11 
12 #include "llvm/ADT/StringRef.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 
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 
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 
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 }
157  return &Contributions[Index->InfoColumn];
158 }
159 
160 const DWARFUnitIndex::Entry *
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 }
FormattedString left_justify(StringRef Str, unsigned Width)
left_justify - append spaces after string so total output is Width characters.
Definition: Format.h:143
size_t i
static void dump(StringRef Title, SpillInfo const &Spills)
Definition: CoroFrame.cpp:283
const Entry * getFromOffset(uint32_t Offset) const
uint32_t getU32(uint32_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
bool isValidOffsetForDataOfSize(uint32_t offset, uint32_t length) const
Test the availability of length bytes of data from offset.
bool parse(DataExtractor IndexData)
format_object< Ts...> format(const char *Fmt, const Ts &...Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
DWARFSectionKind
uint32_t Offset
uint64_t getU64(uint32_t *offset_ptr) const
Extract a uint64_t value from *offset_ptr.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const SectionContribution * getOffset() const
void dump(raw_ostream &OS) const
#define CASE(DS)
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:44
const uint64_t Version
Definition: InstrProf.h:799