LLVM  8.0.1
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 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/StringRef.h"
14 #include "llvm/Support/Format.h"
16 #include <cinttypes>
17 #include <cstdint>
18 
19 using namespace llvm;
20 
22  uint32_t *OffsetPtr) {
23  if (!IndexData.isValidOffsetForDataOfSize(*OffsetPtr, 16))
24  return false;
25  Version = IndexData.getU32(OffsetPtr);
26  NumColumns = IndexData.getU32(OffsetPtr);
27  NumUnits = IndexData.getU32(OffsetPtr);
28  NumBuckets = IndexData.getU32(OffsetPtr);
29  return Version <= 2;
30 }
31 
33  OS << format("version = %u slots = %u\n\n", Version, NumBuckets);
34 }
35 
37  bool b = parseImpl(IndexData);
38  if (!b) {
39  // Make sure we don't try to dump anything
40  Header.NumBuckets = 0;
41  // Release any partially initialized data.
42  ColumnKinds.reset();
43  Rows.reset();
44  }
45  return b;
46 }
47 
48 bool DWARFUnitIndex::parseImpl(DataExtractor IndexData) {
49  uint32_t Offset = 0;
50  if (!Header.parse(IndexData, &Offset))
51  return false;
52 
53  if (!IndexData.isValidOffsetForDataOfSize(
54  Offset, Header.NumBuckets * (8 + 4) +
55  (2 * Header.NumUnits + 1) * 4 * Header.NumColumns))
56  return false;
57 
58  Rows = llvm::make_unique<Entry[]>(Header.NumBuckets);
59  auto Contribs =
60  llvm::make_unique<Entry::SectionContribution *[]>(Header.NumUnits);
61  ColumnKinds = llvm::make_unique<DWARFSectionKind[]>(Header.NumColumns);
62 
63  // Read Hash Table of Signatures
64  for (unsigned i = 0; i != Header.NumBuckets; ++i)
65  Rows[i].Signature = IndexData.getU64(&Offset);
66 
67  // Read Parallel Table of Indexes
68  for (unsigned i = 0; i != Header.NumBuckets; ++i) {
69  auto Index = IndexData.getU32(&Offset);
70  if (!Index)
71  continue;
72  Rows[i].Index = this;
73  Rows[i].Contributions =
74  llvm::make_unique<Entry::SectionContribution[]>(Header.NumColumns);
75  Contribs[Index - 1] = Rows[i].Contributions.get();
76  }
77 
78  // Read the Column Headers
79  for (unsigned i = 0; i != Header.NumColumns; ++i) {
80  ColumnKinds[i] = static_cast<DWARFSectionKind>(IndexData.getU32(&Offset));
81  if (ColumnKinds[i] == InfoColumnKind) {
82  if (InfoColumn != -1)
83  return false;
84  InfoColumn = i;
85  }
86  }
87 
88  if (InfoColumn == -1)
89  return false;
90 
91  // Read Table of Section Offsets
92  for (unsigned i = 0; i != Header.NumUnits; ++i) {
93  auto *Contrib = Contribs[i];
94  for (unsigned i = 0; i != Header.NumColumns; ++i)
95  Contrib[i].Offset = IndexData.getU32(&Offset);
96  }
97 
98  // Read Table of Section Sizes
99  for (unsigned i = 0; i != Header.NumUnits; ++i) {
100  auto *Contrib = Contribs[i];
101  for (unsigned i = 0; i != Header.NumColumns; ++i)
102  Contrib[i].Length = IndexData.getU32(&Offset);
103  }
104 
105  return true;
106 }
107 
108 StringRef DWARFUnitIndex::getColumnHeader(DWARFSectionKind DS) {
109 #define CASE(DS) \
110  case DW_SECT_##DS: \
111  return #DS;
112  switch (DS) {
113  CASE(INFO);
114  CASE(TYPES);
115  CASE(ABBREV);
116  CASE(LINE);
117  CASE(LOC);
118  CASE(STR_OFFSETS);
119  CASE(MACINFO);
120  CASE(MACRO);
121  }
122  llvm_unreachable("unknown DWARFSectionKind");
123 }
124 
126  if (!*this)
127  return;
128 
129  Header.dump(OS);
130  OS << "Index Signature ";
131  for (unsigned i = 0; i != Header.NumColumns; ++i)
132  OS << ' ' << left_justify(getColumnHeader(ColumnKinds[i]), 24);
133  OS << "\n----- ------------------";
134  for (unsigned i = 0; i != Header.NumColumns; ++i)
135  OS << " ------------------------";
136  OS << '\n';
137  for (unsigned i = 0; i != Header.NumBuckets; ++i) {
138  auto &Row = Rows[i];
139  if (auto *Contribs = Row.Contributions.get()) {
140  OS << format("%5u 0x%016" PRIx64 " ", i + 1, Row.Signature);
141  for (unsigned i = 0; i != Header.NumColumns; ++i) {
142  auto &Contrib = Contribs[i];
143  OS << format("[0x%08x, 0x%08x) ", Contrib.Offset,
144  Contrib.Offset + Contrib.Length);
145  }
146  OS << '\n';
147  }
148  }
149 }
150 
153  uint32_t i = 0;
154  for (; i != Index->Header.NumColumns; ++i)
155  if (Index->ColumnKinds[i] == Sec)
156  return &Contributions[i];
157  return nullptr;
158 }
159 
162  return &Contributions[Index->InfoColumn];
163 }
164 
165 const DWARFUnitIndex::Entry *
167  if (OffsetLookup.empty()) {
168  for (uint32_t i = 0; i != Header.NumBuckets; ++i)
169  if (Rows[i].Contributions)
170  OffsetLookup.push_back(&Rows[i]);
171  llvm::sort(OffsetLookup, [&](Entry *E1, Entry *E2) {
172  return E1->Contributions[InfoColumn].Offset <
173  E2->Contributions[InfoColumn].Offset;
174  });
175  }
176  auto I =
177  llvm::upper_bound(OffsetLookup, Offset, [&](uint32_t Offset, Entry *E2) {
178  return Offset < E2->Contributions[InfoColumn].Offset;
179  });
180  if (I == OffsetLookup.begin())
181  return nullptr;
182  --I;
183  const auto *E = *I;
184  const auto &InfoContrib = E->Contributions[InfoColumn];
185  if ((InfoContrib.Offset + InfoContrib.Length) <= Offset)
186  return nullptr;
187  return E;
188 }
189 
191  uint64_t Mask = Header.NumBuckets - 1;
192 
193  auto H = S & Mask;
194  auto HP = ((S >> 32) & Mask) | 1;
195  while (Rows[H].getSignature() != S && Rows[H].getSignature() != 0)
196  H = (H + HP) & Mask;
197 
198  if (Rows[H].getSignature() != S)
199  return nullptr;
200 
201  return &Rows[H];
202 }
FormattedString left_justify(StringRef Str, unsigned Width)
left_justify - append spaces after string so total output is Width characters.
Definition: Format.h:145
This class represents lattice values for constants.
Definition: AllocatorList.h:24
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
static void dump(StringRef Title, SpillInfo const &Spills)
Definition: CoroFrame.cpp:299
const SectionContribution * getOffset() 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.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
DWARFSectionKind
#define H(x, y, z)
Definition: MD5.cpp:57
llvm::Expected< Value > parse(llvm::StringRef JSON)
Parses the provided JSON source, or returns a ParseError.
Definition: JSON.cpp:511
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.
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1116
void dump(raw_ostream &OS) const
#define I(x, y, z)
Definition: MD5.cpp:58
const Entry * getFromHash(uint64_t Offset) const
#define CASE(DS)
auto upper_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range))
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1295
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E&#39;s largest value.
Definition: BitmaskEnum.h:81
const Entry * getFromOffset(uint32_t Offset) const
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
bool parse(DataExtractor IndexData)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
static std::string getSignature(FunctionType *FTy)
const uint64_t Version
Definition: InstrProf.h:895