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