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