LLVM  15.0.0git
DWARFUnitIndex.cpp
Go to the documentation of this file.
1 //===- DWARFUnitIndex.cpp -------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/StringRef.h"
14 #include "llvm/Support/Format.h"
16 #include <cinttypes>
17 #include <cstdint>
18 
19 using namespace llvm;
20 
21 namespace {
22 
23 enum class DWARFSectionKindV2 {
24  DW_SECT_INFO = 1,
25  DW_SECT_TYPES = 2,
26  DW_SECT_ABBREV = 3,
27  DW_SECT_LINE = 4,
28  DW_SECT_LOC = 5,
29  DW_SECT_STR_OFFSETS = 6,
30  DW_SECT_MACINFO = 7,
31  DW_SECT_MACRO = 8,
32 };
33 
34 } // namespace
35 
36 // Return true if the section identifier is defined in the DWARFv5 standard.
37 constexpr bool isKnownV5SectionID(uint32_t ID) {
38  return ID >= DW_SECT_INFO && ID <= DW_SECT_RNGLISTS &&
40 }
41 
43  unsigned IndexVersion) {
44  if (IndexVersion == 5) {
46  return static_cast<uint32_t>(Kind);
47  }
48  assert(IndexVersion == 2);
49  switch (Kind) {
50 #define CASE(S,T) \
51  case DW_SECT_##S: \
52  return static_cast<uint32_t>(DWARFSectionKindV2::DW_SECT_##T)
53  CASE(INFO, INFO);
54  CASE(EXT_TYPES, TYPES);
55  CASE(ABBREV, ABBREV);
56  CASE(LINE, LINE);
57  CASE(EXT_LOC, LOC);
58  CASE(STR_OFFSETS, STR_OFFSETS);
59  CASE(EXT_MACINFO, MACINFO);
60  CASE(MACRO, MACRO);
61 #undef CASE
62  default:
63  // All other section kinds have no corresponding values in v2 indexes.
64  llvm_unreachable("Invalid DWARFSectionKind");
65  }
66 }
67 
69  unsigned IndexVersion) {
70  if (IndexVersion == 5)
72  ? static_cast<DWARFSectionKind>(Value)
74  assert(IndexVersion == 2);
75  switch (static_cast<DWARFSectionKindV2>(Value)) {
76 #define CASE(S,T) \
77  case DWARFSectionKindV2::DW_SECT_##S: \
78  return DW_SECT_##T
79  CASE(INFO, INFO);
80  CASE(TYPES, EXT_TYPES);
81  CASE(ABBREV, ABBREV);
82  CASE(LINE, LINE);
83  CASE(LOC, EXT_LOC);
84  CASE(STR_OFFSETS, STR_OFFSETS);
85  CASE(MACINFO, EXT_MACINFO);
86  CASE(MACRO, MACRO);
87 #undef CASE
88  }
89  return DW_SECT_EXT_unknown;
90 }
91 
93  uint64_t *OffsetPtr) {
94  const uint64_t BeginOffset = *OffsetPtr;
95  if (!IndexData.isValidOffsetForDataOfSize(*OffsetPtr, 16))
96  return false;
97  // GCC Debug Fission defines the version as an unsigned 32-bit field
98  // with value of 2, https://gcc.gnu.org/wiki/DebugFissionDWP.
99  // DWARFv5 defines the same space as an uhalf version field with value of 5
100  // and a 2 bytes long padding, see Section 7.3.5.3.
101  Version = IndexData.getU32(OffsetPtr);
102  if (Version != 2) {
103  *OffsetPtr = BeginOffset;
104  Version = IndexData.getU16(OffsetPtr);
105  if (Version != 5)
106  return false;
107  *OffsetPtr += 2; // Skip padding.
108  }
109  NumColumns = IndexData.getU32(OffsetPtr);
110  NumUnits = IndexData.getU32(OffsetPtr);
111  NumBuckets = IndexData.getU32(OffsetPtr);
112  return true;
113 }
114 
116  OS << format("version = %u, units = %u, slots = %u\n\n", Version, NumUnits, NumBuckets);
117 }
118 
120  bool b = parseImpl(IndexData);
121  if (!b) {
122  // Make sure we don't try to dump anything
123  Header.NumBuckets = 0;
124  // Release any partially initialized data.
125  ColumnKinds.reset();
126  Rows.reset();
127  }
128  return b;
129 }
130 
131 bool DWARFUnitIndex::parseImpl(DataExtractor IndexData) {
132  uint64_t Offset = 0;
133  if (!Header.parse(IndexData, &Offset))
134  return false;
135 
136  // Fix InfoColumnKind: in DWARFv5, type units are in .debug_info.dwo.
137  if (Header.Version == 5)
138  InfoColumnKind = DW_SECT_INFO;
139 
140  if (!IndexData.isValidOffsetForDataOfSize(
141  Offset, Header.NumBuckets * (8 + 4) +
142  (2 * Header.NumUnits + 1) * 4 * Header.NumColumns))
143  return false;
144 
145  Rows = std::make_unique<Entry[]>(Header.NumBuckets);
146  auto Contribs =
147  std::make_unique<Entry::SectionContribution *[]>(Header.NumUnits);
148  ColumnKinds = std::make_unique<DWARFSectionKind[]>(Header.NumColumns);
149  RawSectionIds = std::make_unique<uint32_t[]>(Header.NumColumns);
150 
151  // Read Hash Table of Signatures
152  for (unsigned i = 0; i != Header.NumBuckets; ++i)
153  Rows[i].Signature = IndexData.getU64(&Offset);
154 
155  // Read Parallel Table of Indexes
156  for (unsigned i = 0; i != Header.NumBuckets; ++i) {
157  auto Index = IndexData.getU32(&Offset);
158  if (!Index)
159  continue;
160  Rows[i].Index = this;
161  Rows[i].Contributions =
162  std::make_unique<Entry::SectionContribution[]>(Header.NumColumns);
163  Contribs[Index - 1] = Rows[i].Contributions.get();
164  }
165 
166  // Read the Column Headers
167  for (unsigned i = 0; i != Header.NumColumns; ++i) {
168  RawSectionIds[i] = IndexData.getU32(&Offset);
169  ColumnKinds[i] = deserializeSectionKind(RawSectionIds[i], Header.Version);
170  if (ColumnKinds[i] == InfoColumnKind) {
171  if (InfoColumn != -1)
172  return false;
173  InfoColumn = i;
174  }
175  }
176 
177  if (InfoColumn == -1)
178  return false;
179 
180  // Read Table of Section Offsets
181  for (unsigned i = 0; i != Header.NumUnits; ++i) {
182  auto *Contrib = Contribs[i];
183  for (unsigned i = 0; i != Header.NumColumns; ++i)
184  Contrib[i].Offset = IndexData.getU32(&Offset);
185  }
186 
187  // Read Table of Section Sizes
188  for (unsigned i = 0; i != Header.NumUnits; ++i) {
189  auto *Contrib = Contribs[i];
190  for (unsigned i = 0; i != Header.NumColumns; ++i)
191  Contrib[i].Length = IndexData.getU32(&Offset);
192  }
193 
194  return true;
195 }
196 
197 StringRef DWARFUnitIndex::getColumnHeader(DWARFSectionKind DS) {
198  switch (DS) {
199 #define HANDLE_DW_SECT(ID, NAME) \
200  case DW_SECT_##NAME: \
201  return #NAME;
202 #include "llvm/BinaryFormat/Dwarf.def"
203  case DW_SECT_EXT_TYPES:
204  return "TYPES";
205  case DW_SECT_EXT_LOC:
206  return "LOC";
207  case DW_SECT_EXT_MACINFO:
208  return "MACINFO";
209  case DW_SECT_EXT_unknown:
210  return StringRef();
211  }
212  llvm_unreachable("Unknown DWARFSectionKind");
213 }
214 
216  if (!*this)
217  return;
218 
219  Header.dump(OS);
220  OS << "Index Signature ";
221  for (unsigned i = 0; i != Header.NumColumns; ++i) {
222  DWARFSectionKind Kind = ColumnKinds[i];
223  StringRef Name = getColumnHeader(Kind);
224  if (!Name.empty())
225  OS << ' ' << left_justify(Name, 24);
226  else
227  OS << format(" Unknown: %-15" PRIu32, RawSectionIds[i]);
228  }
229  OS << "\n----- ------------------";
230  for (unsigned i = 0; i != Header.NumColumns; ++i)
231  OS << " ------------------------";
232  OS << '\n';
233  for (unsigned i = 0; i != Header.NumBuckets; ++i) {
234  auto &Row = Rows[i];
235  if (auto *Contribs = Row.Contributions.get()) {
236  OS << format("%5u 0x%016" PRIx64 " ", i + 1, Row.Signature);
237  for (unsigned i = 0; i != Header.NumColumns; ++i) {
238  auto &Contrib = Contribs[i];
239  OS << format("[0x%08x, 0x%08x) ", Contrib.Offset,
240  Contrib.Offset + Contrib.Length);
241  }
242  OS << '\n';
243  }
244  }
245 }
246 
249  uint32_t i = 0;
250  for (; i != Index->Header.NumColumns; ++i)
251  if (Index->ColumnKinds[i] == Sec)
252  return &Contributions[i];
253  return nullptr;
254 }
255 
258  return &Contributions[Index->InfoColumn];
259 }
260 
261 const DWARFUnitIndex::Entry *
263  if (OffsetLookup.empty()) {
264  for (uint32_t i = 0; i != Header.NumBuckets; ++i)
265  if (Rows[i].Contributions)
266  OffsetLookup.push_back(&Rows[i]);
267  llvm::sort(OffsetLookup, [&](Entry *E1, Entry *E2) {
268  return E1->Contributions[InfoColumn].Offset <
269  E2->Contributions[InfoColumn].Offset;
270  });
271  }
272  auto I = partition_point(OffsetLookup, [&](Entry *E2) {
273  return E2->Contributions[InfoColumn].Offset <= Offset;
274  });
275  if (I == OffsetLookup.begin())
276  return nullptr;
277  --I;
278  const auto *E = *I;
279  const auto &InfoContrib = E->Contributions[InfoColumn];
280  if ((InfoContrib.Offset + InfoContrib.Length) <= Offset)
281  return nullptr;
282  return E;
283 }
284 
286  uint64_t Mask = Header.NumBuckets - 1;
287 
288  auto H = S & Mask;
289  auto HP = ((S >> 32) & Mask) | 1;
290  // The spec says "while 0 is a valid hash value, the row index in a used slot
291  // will always be non-zero". Loop until we find a match or an empty slot.
292  while (Rows[H].getSignature() != S && Rows[H].Index != nullptr)
293  H = (H + HP) & Mask;
294 
295  // If the slot is empty, we don't care whether the signature matches (it could
296  // be zero and still match the zeros in the empty slot).
297  if (Rows[H].Index == nullptr)
298  return nullptr;
299 
300  return &Rows[H];
301 }
i
i
Definition: README.txt:29
isKnownV5SectionID
constexpr bool isKnownV5SectionID(uint32_t ID)
Definition: DWARFUnitIndex.cpp:37
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
StringRef.h
llvm::DWARFUnitIndex::Entry::SectionContribution
Definition: DWARFUnitIndex.h:113
getSignature
static std::string getSignature(FunctionType *FTy)
Definition: WebAssemblyLowerEmscriptenEHSjLj.cpp:432
ErrorHandling.h
llvm::DW_SECT_EXT_unknown
@ DW_SECT_EXT_unknown
Denotes a value read from an index section that does not correspond to any of the supported standards...
Definition: DWARFUnitIndex.h:59
TYPES
#define TYPES
Definition: X86DisassemblerDecoderCommon.h:411
llvm::DWARFUnitIndex::Entry
Definition: DWARFUnitIndex.h:111
llvm::DWARFUnitIndex::dump
void dump(raw_ostream &OS) const
Definition: DWARFUnitIndex.cpp:215
llvm::dump
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
Definition: SparseBitVector.h:877
STLExtras.h
llvm::DataExtractor::getU64
uint64_t getU64(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint64_t value from *offset_ptr.
Definition: DataExtractor.cpp:116
Format.h
llvm::BitmaskEnumDetail::Mask
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Definition: BitmaskEnum.h:80
llvm::serializeSectionKind
uint32_t serializeSectionKind(DWARFSectionKind Kind, unsigned IndexVersion)
Convert the internal value for a section kind to an on-disk value.
Definition: DWARFUnitIndex.cpp:42
llvm::DWARFUnitIndex::getFromHash
const Entry * getFromHash(uint64_t Offset) const
Definition: DWARFUnitIndex.cpp:285
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
CASE
#define CASE(S, T)
llvm::DWARFSectionKind
DWARFSectionKind
The enum of section identifiers to be used in internal interfaces.
Definition: DWARFUnitIndex.h:56
b
the resulting code requires compare and branches when and if the revised code is with conditional branches instead of More there is a byte word extend before each where there should be only and the condition codes are not remembered when the same two values are compared twice More LSR enhancements i8 and i32 load store addressing modes are identical int b
Definition: README.txt:418
llvm::DWARFUnitIndex::parse
bool parse(DataExtractor IndexData)
Definition: DWARFUnitIndex.cpp:119
llvm::DW_SECT_EXT_TYPES
@ DW_SECT_EXT_TYPES
Definition: DWARFUnitIndex.h:62
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:54
llvm::DWARFUnitIndex::getFromOffset
const Entry * getFromOffset(uint32_t Offset) const
Definition: DWARFUnitIndex.cpp:262
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
llvm::CallingConv::ID
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
uint64_t
llvm::DataExtractor::isValidOffsetForDataOfSize
bool isValidOffsetForDataOfSize(uint64_t offset, uint64_t length) const
Test the availability of length bytes of data from offset.
Definition: DataExtractor.h:672
llvm::DW_SECT_EXT_LOC
@ DW_SECT_EXT_LOC
Definition: DWARFUnitIndex.h:63
llvm::SIInstrFlags::DS
@ DS
Definition: SIDefines.h:60
I
#define I(x, y, z)
Definition: MD5.cpp:58
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::DataExtractor::getU32
uint32_t getU32(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint32_t value from *offset_ptr.
Definition: DataExtractor.cpp:107
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
uint32_t
parse
static llvm::Error parse(DataExtractor &Data, uint64_t BaseAddr, LineEntryCallback const &Callback)
Definition: LineTable.cpp:54
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::DW_SECT_EXT_MACINFO
@ DW_SECT_EXT_MACINFO
Definition: DWARFUnitIndex.h:64
llvm::deserializeSectionKind
DWARFSectionKind deserializeSectionKind(uint32_t Value, unsigned IndexVersion)
Convert a value read from an index section to the internal representation.
Definition: DWARFUnitIndex.cpp:68
llvm::left_justify
FormattedString left_justify(StringRef Str, unsigned Width)
left_justify - append spaces after string so total output is Width characters.
Definition: Format.h:145
llvm::format
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
llvm::partition_point
auto partition_point(R &&Range, Predicate P)
Binary search for the first iterator in a range where a predicate is false.
Definition: STLExtras.h:1764
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
H
#define H(x, y, z)
Definition: MD5.cpp:57
DataExtractor.h
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1552
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
DWARFUnitIndex.h
llvm::DataExtractor
Definition: DataExtractor.h:41
Version
uint64_t Version
Definition: RawMemProfReader.cpp:40
raw_ostream.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::DWARFUnitIndex::Entry::getContribution
const SectionContribution * getContribution() const
Definition: DWARFUnitIndex.cpp:257
llvm::DataExtractor::getU16
uint16_t getU16(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint16_t value from *offset_ptr.
Definition: DataExtractor.cpp:92