LLVM  4.0.0
DWARFUnit.cpp
Go to the documentation of this file.
1 //===-- DWARFUnit.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/ADT/SmallString.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/StringRef.h"
17 #include "llvm/Object/ObjectFile.h"
18 #include "llvm/Support/Casting.h"
20 #include "llvm/Support/Path.h"
21 #include <algorithm>
22 #include <cassert>
23 #include <cstdint>
24 #include <cstdio>
25 #include <vector>
26 
27 namespace llvm {
28 
29 using namespace dwarf;
30 
32  parseImpl(C, Section, C.getDebugAbbrev(), C.getRangeSection(),
34  C.getLineSection().Data, C.isLittleEndian(), false);
35 }
36 
38  const DWARFSection &DWOSection,
39  DWARFUnitIndex *Index) {
40  parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), C.getRangeDWOSection(),
43  true);
44 }
45 
47  const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
48  StringRef SOS, StringRef AOS, StringRef LS, bool LE,
49  bool IsDWO, const DWARFUnitSectionBase &UnitSection,
51  : Context(DC), InfoSection(Section), Abbrev(DA), RangeSection(RS),
52  LineSection(LS), StringSection(SS), StringOffsetSection([&]() {
53  if (IndexEntry)
54  if (const auto *C = IndexEntry->getOffset(DW_SECT_STR_OFFSETS))
55  return SOS.slice(C->Offset, C->Offset + C->Length);
56  return SOS;
57  }()),
60  clear();
61 }
62 
63 DWARFUnit::~DWARFUnit() = default;
64 
66  uint64_t &Result) const {
67  uint32_t Offset = AddrOffsetSectionBase + Index * AddrSize;
68  if (AddrOffsetSection.size() < Offset + AddrSize)
69  return false;
70  DataExtractor DA(AddrOffsetSection, isLittleEndian, AddrSize);
71  Result = DA.getAddress(&Offset);
72  return true;
73 }
74 
76  uint32_t &Result) const {
77  // FIXME: string offset section entries are 8-byte for DWARF64.
78  const uint32_t ItemSize = 4;
79  uint32_t Offset = Index * ItemSize;
80  if (StringOffsetSection.size() < Offset + ItemSize)
81  return false;
82  DataExtractor DA(StringOffsetSection, isLittleEndian, 0);
83  Result = DA.getU32(&Offset);
84  return true;
85 }
86 
87 bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) {
88  Length = debug_info.getU32(offset_ptr);
89  Version = debug_info.getU16(offset_ptr);
90  uint64_t AbbrOffset = debug_info.getU32(offset_ptr);
91  if (IndexEntry) {
92  if (AbbrOffset)
93  return false;
94  auto *UnitContrib = IndexEntry->getOffset();
95  if (!UnitContrib || UnitContrib->Length != (Length + 4))
96  return false;
97  auto *AbbrEntry = IndexEntry->getOffset(DW_SECT_ABBREV);
98  if (!AbbrEntry)
99  return false;
100  AbbrOffset = AbbrEntry->Offset;
101  }
102  AddrSize = debug_info.getU8(offset_ptr);
103 
104  bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
105  bool VersionOK = DWARFContext::isSupportedVersion(Version);
106  bool AddrSizeOK = AddrSize == 4 || AddrSize == 8;
107 
108  if (!LengthOK || !VersionOK || !AddrSizeOK)
109  return false;
110 
111  Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset);
112  return Abbrevs != nullptr;
113 }
114 
115 bool DWARFUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) {
116  clear();
117 
118  Offset = *offset_ptr;
119 
120  if (debug_info.isValidOffset(*offset_ptr)) {
121  if (extractImpl(debug_info, offset_ptr))
122  return true;
123 
124  // reset the offset to where we tried to parse from if anything went wrong
125  *offset_ptr = Offset;
126  }
127 
128  return false;
129 }
130 
132  DWARFDebugRangeList &RangeList) const {
133  // Require that compile unit is extracted.
134  assert(!DieArray.empty());
135  DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize);
136  uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
137  return RangeList.extract(RangesData, &ActualRangeListOffset);
138 }
139 
141  Offset = 0;
142  Length = 0;
143  Version = 0;
144  Abbrevs = nullptr;
145  AddrSize = 0;
146  BaseAddr = 0;
147  RangeSectionBase = 0;
148  AddrOffsetSectionBase = 0;
149  clearDIEs(false);
150  DWO.reset();
151 }
152 
154  return getUnitDIE().getAttributeValueAsString(DW_AT_comp_dir, nullptr);
155 }
156 
158  return getUnitDIE().getAttributeValueAsUnsignedConstant(DW_AT_GNU_dwo_id);
159 }
160 
161 void DWARFUnit::extractDIEsToVector(
162  bool AppendCUDie, bool AppendNonCUDies,
163  std::vector<DWARFDebugInfoEntry> &Dies) const {
164  if (!AppendCUDie && !AppendNonCUDies)
165  return;
166 
167  // Set the offset to that of the first DIE and calculate the start of the
168  // next compilation unit header.
169  uint32_t DIEOffset = Offset + getHeaderSize();
170  uint32_t NextCUOffset = getNextUnitOffset();
172  DataExtractor DebugInfoData = getDebugInfoExtractor();
173  uint32_t Depth = 0;
174  bool IsCUDie = true;
175 
176  while (DIE.extractFast(*this, &DIEOffset, DebugInfoData, NextCUOffset,
177  Depth)) {
178  if (IsCUDie) {
179  if (AppendCUDie)
180  Dies.push_back(DIE);
181  if (!AppendNonCUDies)
182  break;
183  // The average bytes per DIE entry has been seen to be
184  // around 14-20 so let's pre-reserve the needed memory for
185  // our DIE entries accordingly.
186  Dies.reserve(Dies.size() + getDebugInfoSize() / 14);
187  IsCUDie = false;
188  } else {
189  Dies.push_back(DIE);
190  }
191 
192  if (const DWARFAbbreviationDeclaration *AbbrDecl =
194  // Normal DIE
195  if (AbbrDecl->hasChildren())
196  ++Depth;
197  } else {
198  // NULL DIE.
199  if (Depth > 0)
200  --Depth;
201  if (Depth == 0)
202  break; // We are done with this compile unit!
203  }
204  }
205 
206  // Give a little bit of info if we encounter corrupt DWARF (our offset
207  // should always terminate at or before the start of the next compilation
208  // unit header).
209  if (DIEOffset > NextCUOffset)
210  fprintf(stderr, "warning: DWARF compile unit extends beyond its "
211  "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), DIEOffset);
212 }
213 
214 size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
215  if ((CUDieOnly && !DieArray.empty()) ||
216  DieArray.size() > 1)
217  return 0; // Already parsed.
218 
219  bool HasCUDie = !DieArray.empty();
220  extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray);
221 
222  if (DieArray.empty())
223  return 0;
224 
225  // If CU DIE was just parsed, copy several attribute values from it.
226  if (!HasCUDie) {
227  DWARFDie UnitDie = getUnitDIE();
228  auto BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_low_pc);
229  if (!BaseAddr)
230  BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_entry_pc);
231  if (BaseAddr)
232  setBaseAddress(*BaseAddr);
233  AddrOffsetSectionBase =
234  UnitDie.getAttributeValueAsSectionOffset(DW_AT_GNU_addr_base)
235  .getValueOr(0);
236  RangeSectionBase =
237  UnitDie.getAttributeValueAsSectionOffset(DW_AT_rnglists_base)
238  .getValueOr(0);
239  // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for
240  // skeleton CU DIE, so that DWARF users not aware of it are not broken.
241  }
242 
243  return DieArray.size();
244 }
245 
246 DWARFUnit::DWOHolder::DWOHolder(StringRef DWOPath)
247  : DWOU(nullptr) {
248  auto Obj = object::ObjectFile::createObjectFile(DWOPath);
249  if (!Obj) {
250  // TODO: Actually report errors helpfully.
251  consumeError(Obj.takeError());
252  return;
253  }
254  DWOFile = std::move(Obj.get());
255  DWOContext.reset(
256  cast<DWARFContext>(new DWARFContextInMemory(*DWOFile.getBinary())));
257  if (DWOContext->getNumDWOCompileUnits() > 0)
258  DWOU = DWOContext->getDWOCompileUnitAtIndex(0);
259 }
260 
261 bool DWARFUnit::parseDWO() {
262  if (isDWO)
263  return false;
264  if (DWO.get())
265  return false;
266  DWARFDie UnitDie = getUnitDIE();
267  if (!UnitDie)
268  return false;
269  const char *DWOFileName =
270  UnitDie.getAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr);
271  if (!DWOFileName)
272  return false;
273  const char *CompilationDir =
274  UnitDie.getAttributeValueAsString(DW_AT_comp_dir, nullptr);
275  SmallString<16> AbsolutePath;
276  if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) {
277  sys::path::append(AbsolutePath, CompilationDir);
278  }
279  sys::path::append(AbsolutePath, DWOFileName);
280  DWO = llvm::make_unique<DWOHolder>(AbsolutePath);
281  DWARFUnit *DWOCU = DWO->getUnit();
282  // Verify that compile unit in .dwo file is valid.
283  if (!DWOCU || DWOCU->getDWOId() != getDWOId()) {
284  DWO.reset();
285  return false;
286  }
287  // Share .debug_addr and .debug_ranges section with compile unit in .dwo
288  DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase);
289  auto DWORangesBase = UnitDie.getRangesBaseAttribute();
290  DWOCU->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0);
291  return true;
292 }
293 
294 void DWARFUnit::clearDIEs(bool KeepCUDie) {
295  if (DieArray.size() > (unsigned)KeepCUDie) {
296  // std::vectors never get any smaller when resized to a smaller size,
297  // or when clear() or erase() are called, the size will report that it
298  // is smaller, but the memory allocated remains intact (call capacity()
299  // to see this). So we need to create a temporary vector and swap the
300  // contents which will cause just the internal pointers to be swapped
301  // so that when temporary vector goes out of scope, it will destroy the
302  // contents.
303  std::vector<DWARFDebugInfoEntry> TmpArray;
304  DieArray.swap(TmpArray);
305  // Save at least the compile unit DIE
306  if (KeepCUDie)
307  DieArray.push_back(TmpArray.front());
308  }
309 }
310 
312  DWARFDie UnitDie = getUnitDIE();
313  if (!UnitDie)
314  return;
315  // First, check if unit DIE describes address ranges for the whole unit.
316  const auto &CUDIERanges = UnitDie.getAddressRanges();
317  if (!CUDIERanges.empty()) {
318  CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end());
319  return;
320  }
321 
322  // This function is usually called if there in no .debug_aranges section
323  // in order to produce a compile unit level set of address ranges that
324  // is accurate. If the DIEs weren't parsed, then we don't want all dies for
325  // all compile units to stay loaded when they weren't needed. So we can end
326  // up parsing the DWARF and then throwing them all away to keep memory usage
327  // down.
328  const bool ClearDIEs = extractDIEsIfNeeded(false) > 1;
330 
331  // Collect address ranges from DIEs in .dwo if necessary.
332  bool DWOCreated = parseDWO();
333  if (DWO.get())
334  DWO->getUnit()->collectAddressRanges(CURanges);
335  if (DWOCreated)
336  DWO.reset();
337 
338  // Keep memory down by clearing DIEs if this generate function
339  // caused them to be parsed.
340  if (ClearDIEs)
341  clearDIEs(true);
342 }
343 
344 DWARFDie
345 DWARFUnit::getSubprogramForAddress(uint64_t Address) {
346  extractDIEsIfNeeded(false);
347  for (const DWARFDebugInfoEntry &D : DieArray) {
348  DWARFDie DIE(this, &D);
349  if (DIE.isSubprogramDIE() &&
350  DIE.addressRangeContainsAddress(Address)) {
351  return DIE;
352  }
353  }
354  return DWARFDie();
355 }
356 
357 void
359  SmallVectorImpl<DWARFDie> &InlinedChain) {
360  // First, find a subprogram that contains the given address (the root
361  // of inlined chain).
362  DWARFDie SubprogramDIE;
363  // Try to look for subprogram DIEs in the DWO file.
364  parseDWO();
365  if (DWO)
366  SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address);
367  else
368  SubprogramDIE = getSubprogramForAddress(Address);
369 
370  // Get inlined chain rooted at this subprogram DIE.
371  if (SubprogramDIE)
372  SubprogramDIE.getInlinedChainForAddress(Address, InlinedChain);
373  else
374  InlinedChain.clear();
375 }
376 
379  if (Kind == DW_SECT_INFO)
380  return Context.getCUIndex();
381  assert(Kind == DW_SECT_TYPES);
382  return Context.getTUIndex();
383 }
384 
386  if (!Die)
387  return DWARFDie();
388  const uint32_t Depth = Die->getDepth();
389  // Unit DIEs always have a depth of zero and never have parents.
390  if (Depth == 0)
391  return DWARFDie();
392  // Depth of 1 always means parent is the compile/type unit.
393  if (Depth == 1)
394  return getUnitDIE();
395  // Look for previous DIE with a depth that is one less than the Die's depth.
396  const uint32_t ParentDepth = Depth - 1;
397  for (uint32_t I = getDIEIndex(Die) - 1; I > 0; --I) {
398  if (DieArray[I].getDepth() == ParentDepth)
399  return DWARFDie(this, &DieArray[I]);
400  }
401  return DWARFDie();
402 }
403 
405  if (!Die)
406  return DWARFDie();
407  uint32_t Depth = Die->getDepth();
408  // Unit DIEs always have a depth of zero and never have siblings.
409  if (Depth == 0)
410  return DWARFDie();
411  // NULL DIEs don't have siblings.
412  if (Die->getAbbreviationDeclarationPtr() == nullptr)
413  return DWARFDie();
414 
415  // Find the next DIE whose depth is the same as the Die's depth.
416  for (size_t I=getDIEIndex(Die)+1, EndIdx = DieArray.size(); I<EndIdx; ++I) {
417  if (DieArray[I].getDepth() == Depth)
418  return DWARFDie(this, &DieArray[I]);
419  }
420  return DWARFDie();
421 }
422 
423 } // end namespace llvm
const DWARFUnitIndex & getTUIndex()
virtual StringRef getAddrSection()=0
static Expected< OwningBinary< ObjectFile > > createObjectFile(StringRef ObjectPath)
Create ObjectFile from path.
Definition: ObjectFile.cpp:116
LLVMContext & Context
bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const
Definition: DWARFUnit.cpp:65
DWARFAddressRangesVector getAddressRanges() const
Get the address ranges for this DIE.
Definition: DWARFDie.cpp:237
void setBaseAddress(uint64_t base_addr)
Definition: DWARFUnit.h:224
virtual ~DWARFUnit()
virtual StringRef getStringOffsetDWOSection()=0
virtual StringRef getRangeDWOSection()=0
bool is_relative(const Twine &path)
Is path relative?
Definition: Path.cpp:700
std::vector< std::pair< uint64_t, uint64_t > > DWARFAddressRangesVector
DWARFAddressRangesVector - represents a set of absolute address ranges.
virtual const DWARFSection & getLineSection()=0
virtual uint32_t getHeaderSize() const
Size in bytes of the unit header.
Definition: DWARFUnit.h:155
void collectChildrenAddressRanges(DWARFAddressRangesVector &Ranges) const
Get all address ranges for any DW_TAG_subprogram DIEs in this DIE or any of its children.
Definition: DWARFDie.cpp:256
uint32_t getNextUnitOffset() const
Definition: DWARFUnit.h:202
const DWARFDebugAbbrev * getDebugAbbrevDWO()
Get a pointer to the parsed dwo abbreviations object.
virtual StringRef getStringDWOSection()=0
bool isValidOffset(uint32_t offset) const
Test the validity of offset.
virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr)
Definition: DWARFUnit.cpp:87
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:448
uint32_t getU32(uint32_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:32
static GCRegistry::Add< StatepointGC > D("statepoint-example","an example strategy for statepoint")
DWARFDie getSibling(const DWARFDebugInfoEntry *Die)
Definition: DWARFUnit.cpp:404
const char * getAttributeValueAsString(dwarf::Attribute Attr, const char *FailValue) const
Extract the specified attribute from this DIE as a C string.
Definition: DWARFDie.cpp:146
UnitSection(UnitSection)
DWARFDie getParent(const DWARFDebugInfoEntry *Die)
Definition: DWARFUnit.cpp:385
AddrOffsetSection(AOS)
virtual StringRef getRangeSection()=0
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
Definition: StringRef.h:699
const DWARFDebugAbbrev * getDebugAbbrev()
Get a pointer to the parsed DebugAbbrev object.
bool extract(DataExtractor data, uint32_t *offset_ptr)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:135
const DWARFAbbreviationDeclarationSet * getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const
void collectAddressRanges(DWARFAddressRangesVector &CURanges)
Definition: DWARFUnit.cpp:311
DWARFUnit(DWARFContext &Context, const DWARFSection &Section, const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, StringRef LS, bool LE, bool IsDWO, const DWARFUnitSectionBase &UnitSection, const DWARFUnitIndex::Entry *IndexEntry=nullptr)
Definition: DWARFUnit.cpp:46
void parseDWO(DWARFContext &C, const DWARFSection &DWOSection, DWARFUnitIndex *Index=nullptr)
Definition: DWARFUnit.cpp:37
Utility class that carries the DWARF compile/type unit and the debug info entry in an object...
Definition: DWARFDie.h:36
uint8_t getU8(uint32_t *offset_ptr) const
Extract a uint8_t value from *offset_ptr.
DWARFSectionKind
A structured debug information entry.
Definition: DIE.h:655
void getInlinedChainForAddress(const uint64_t Address, SmallVectorImpl< DWARFDie > &InlinedChain) const
Get inlined chain for a given address, rooted at the current DIE.
Definition: DWARFDie.cpp:365
bool extractFast(const DWARFUnit &U, uint32_t *OffsetPtr)
Extracts a debug info entry, which is a child of a given unit, starting at a given offset...
Optional< uint64_t > getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE as an unsigned integer.
Definition: DWARFDie.cpp:170
const char * getCompilationDir()
Definition: DWARFUnit.cpp:153
IndexEntry(IndexEntry)
Definition: DWARFUnit.cpp:59
void consumeError(Error Err)
Consume a Error without doing anything.
const DWARFUnitIndex & getDWARFUnitIndex(DWARFContext &Context, DWARFSectionKind Kind)
Definition: DWARFUnit.cpp:377
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly=true)
Definition: DWARFUnit.h:228
DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...
Definition: DWARFContext.h:52
bool extractRangeList(uint32_t RangeListOffset, DWARFDebugRangeList &RangeList) const
extractRangeList - extracts the range list referenced by this compile unit from .debug_ranges section...
Definition: DWARFUnit.cpp:131
uint16_t getU16(uint32_t *offset_ptr) const
Extract a uint16_t value from *offset_ptr.
uint64_t getAddress(uint32_t *offset_ptr) const
Extract an pointer from *offset_ptr.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
isDWO(IsDWO)
bool extract(DataExtractor debug_info, uint32_t *offset_ptr)
Definition: DWARFUnit.cpp:115
static void clear(coro::Shape &Shape)
Definition: Coroutines.cpp:191
DataExtractor getDebugInfoExtractor() const
Definition: DWARFUnit.h:184
static bool isSupportedVersion(unsigned version)
Definition: DWARFContext.h:239
const SectionContribution * getOffset(DWARFSectionKind Sec) const
void getInlinedChainForAddress(uint64_t Address, SmallVectorImpl< DWARFDie > &InlinedChain)
getInlinedChainForAddress - fetches inlined chain for a given address.
Definition: DWARFUnit.cpp:358
Optional< uint64_t > getDWOId()
Definition: DWARFUnit.cpp:157
#define I(x, y, z)
Definition: MD5.cpp:54
const DWARFAbbreviationDeclaration * getAbbreviationDeclarationPtr() const
bool getStringOffsetSectionItem(uint32_t Index, uint32_t &Result) const
Definition: DWARFUnit.cpp:75
uint32_t getOffset() const
Definition: DWARFUnit.h:201
const DWARFUnitIndex & getCUIndex()
const unsigned Kind
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Base class for all DWARFUnitSection classes.
Definition: DWARFUnit.h:39
virtual const DWARFSection & getLineDWOSection()=0
DWARFDebugInfoEntry - A DIE with only the minimum required data.
void parse(DWARFContext &C, const DWARFSection &Section)
Definition: DWARFUnit.cpp:31
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
virtual StringRef getStringSection()=0
isLittleEndian(LE)
virtual bool isLittleEndian() const =0