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