1 //===-- DWARFUnit.cpp -----------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
18 using namespace dwarf
;
20 void DWARFUnitSectionBase::parse(DWARFContext
&C
, const DWARFSection
&Section
) {
21 parseImpl(C
, Section
, C
.getDebugAbbrev(), C
.getRangeSection(),
22 C
.getStringSection(), StringRef(), C
.getAddrSection(),
26 void DWARFUnitSectionBase::parseDWO(DWARFContext
&C
,
27 const DWARFSection
&DWOSection
) {
28 parseImpl(C
, DWOSection
, C
.getDebugAbbrevDWO(), C
.getRangeDWOSection(),
29 C
.getStringDWOSection(), C
.getStringOffsetDWOSection(),
30 C
.getAddrSection(), C
.isLittleEndian());
33 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 isLittleEndian(LE
), UnitSection(UnitSection
) {
43 DWARFUnit::~DWARFUnit() {
46 bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index
,
47 uint64_t &Result
) const {
48 uint32_t Offset
= AddrOffsetSectionBase
+ Index
* AddrSize
;
49 if (AddrOffsetSection
.size() < Offset
+ AddrSize
)
51 DataExtractor
DA(AddrOffsetSection
, isLittleEndian
, AddrSize
);
52 Result
= DA
.getAddress(&Offset
);
56 bool DWARFUnit::getStringOffsetSectionItem(uint32_t Index
,
57 uint32_t &Result
) const {
58 // FIXME: string offset section entries are 8-byte for DWARF64.
59 const uint32_t ItemSize
= 4;
60 uint32_t Offset
= Index
* ItemSize
;
61 if (StringOffsetSection
.size() < Offset
+ ItemSize
)
63 DataExtractor
DA(StringOffsetSection
, isLittleEndian
, 0);
64 Result
= DA
.getU32(&Offset
);
68 bool DWARFUnit::extractImpl(DataExtractor debug_info
, uint32_t *offset_ptr
) {
69 Length
= debug_info
.getU32(offset_ptr
);
70 Version
= debug_info
.getU16(offset_ptr
);
71 uint64_t AbbrOffset
= debug_info
.getU32(offset_ptr
);
72 AddrSize
= debug_info
.getU8(offset_ptr
);
74 bool LengthOK
= debug_info
.isValidOffset(getNextUnitOffset() - 1);
75 bool VersionOK
= DWARFContext::isSupportedVersion(Version
);
76 bool AddrSizeOK
= AddrSize
== 4 || AddrSize
== 8;
78 if (!LengthOK
|| !VersionOK
|| !AddrSizeOK
)
81 Abbrevs
= Abbrev
->getAbbreviationDeclarationSet(AbbrOffset
);
82 if (Abbrevs
== nullptr)
88 bool DWARFUnit::extract(DataExtractor debug_info
, uint32_t *offset_ptr
) {
93 if (debug_info
.isValidOffset(*offset_ptr
)) {
94 if (extractImpl(debug_info
, offset_ptr
))
97 // reset the offset to where we tried to parse from if anything went wrong
104 bool DWARFUnit::extractRangeList(uint32_t RangeListOffset
,
105 DWARFDebugRangeList
&RangeList
) const {
106 // Require that compile unit is extracted.
107 assert(DieArray
.size() > 0);
108 DataExtractor
RangesData(RangeSection
, isLittleEndian
, AddrSize
);
109 uint32_t ActualRangeListOffset
= RangeSectionBase
+ RangeListOffset
;
110 return RangeList
.extract(RangesData
, &ActualRangeListOffset
);
113 void DWARFUnit::clear() {
120 RangeSectionBase
= 0;
121 AddrOffsetSectionBase
= 0;
126 const char *DWARFUnit::getCompilationDir() {
127 extractDIEsIfNeeded(true);
128 if (DieArray
.empty())
130 return DieArray
[0].getAttributeValueAsString(this, DW_AT_comp_dir
, nullptr);
133 uint64_t DWARFUnit::getDWOId() {
134 extractDIEsIfNeeded(true);
135 const uint64_t FailValue
= -1ULL;
136 if (DieArray
.empty())
139 .getAttributeValueAsUnsignedConstant(this, DW_AT_GNU_dwo_id
, FailValue
);
142 void DWARFUnit::setDIERelations() {
143 if (DieArray
.size() <= 1)
146 std::vector
<DWARFDebugInfoEntryMinimal
*> ParentChain
;
147 DWARFDebugInfoEntryMinimal
*SiblingChain
= nullptr;
148 for (auto &DIE
: DieArray
) {
150 SiblingChain
->setSibling(&DIE
);
152 if (const DWARFAbbreviationDeclaration
*AbbrDecl
=
153 DIE
.getAbbreviationDeclarationPtr()) {
155 if (AbbrDecl
->hasChildren()) {
156 ParentChain
.push_back(&DIE
);
157 SiblingChain
= nullptr;
162 // NULL entry terminates the sibling chain.
163 SiblingChain
= ParentChain
.back();
164 ParentChain
.pop_back();
167 assert(SiblingChain
== nullptr || SiblingChain
== &DieArray
[0]);
168 assert(ParentChain
.empty());
171 void DWARFUnit::extractDIEsToVector(
172 bool AppendCUDie
, bool AppendNonCUDies
,
173 std::vector
<DWARFDebugInfoEntryMinimal
> &Dies
) const {
174 if (!AppendCUDie
&& !AppendNonCUDies
)
177 // Set the offset to that of the first DIE and calculate the start of the
178 // next compilation unit header.
179 uint32_t DIEOffset
= Offset
+ getHeaderSize();
180 uint32_t NextCUOffset
= getNextUnitOffset();
181 DWARFDebugInfoEntryMinimal DIE
;
185 while (DIEOffset
< NextCUOffset
&& DIE
.extractFast(this, &DIEOffset
)) {
189 if (!AppendNonCUDies
)
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 Dies
.reserve(Dies
.size() + getDebugInfoSize() / 14);
200 if (const DWARFAbbreviationDeclaration
*AbbrDecl
=
201 DIE
.getAbbreviationDeclarationPtr()) {
203 if (AbbrDecl
->hasChildren())
210 break; // We are done with this compile unit!
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
217 if (DIEOffset
> NextCUOffset
)
218 fprintf(stderr
, "warning: DWARF compile unit extends beyond its "
219 "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), DIEOffset
);
222 size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly
) {
223 if ((CUDieOnly
&& DieArray
.size() > 0) ||
225 return 0; // Already parsed.
227 bool HasCUDie
= DieArray
.size() > 0;
228 extractDIEsToVector(!HasCUDie
, !CUDieOnly
, DieArray
);
230 if (DieArray
.empty())
233 // If CU DIE was just parsed, copy several attribute values from it.
236 DieArray
[0].getAttributeValueAsAddress(this, DW_AT_low_pc
, -1ULL);
237 if (BaseAddr
== -1ULL)
238 BaseAddr
= DieArray
[0].getAttributeValueAsAddress(this, DW_AT_entry_pc
, 0);
239 setBaseAddress(BaseAddr
);
240 AddrOffsetSectionBase
= DieArray
[0].getAttributeValueAsSectionOffset(
241 this, DW_AT_GNU_addr_base
, 0);
242 RangeSectionBase
= DieArray
[0].getAttributeValueAsSectionOffset(
243 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.
249 return DieArray
.size();
252 DWARFUnit::DWOHolder::DWOHolder(StringRef DWOPath
)
253 : DWOFile(), DWOContext(), DWOU(nullptr) {
254 auto Obj
= object::ObjectFile::createObjectFile(DWOPath
);
257 DWOFile
= std::move(Obj
.get());
259 cast
<DWARFContext
>(DIContext::getDWARFContext(*DWOFile
.getBinary())));
260 if (DWOContext
->getNumDWOCompileUnits() > 0)
261 DWOU
= DWOContext
->getDWOCompileUnitAtIndex(0);
264 bool DWARFUnit::parseDWO() {
267 extractDIEsIfNeeded(true);
268 if (DieArray
.empty())
270 const char *DWOFileName
=
271 DieArray
[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name
, nullptr);
274 const char *CompilationDir
=
275 DieArray
[0].getAttributeValueAsString(this, DW_AT_comp_dir
, nullptr);
276 SmallString
<16> AbsolutePath
;
277 if (sys::path::is_relative(DWOFileName
) && CompilationDir
!= nullptr) {
278 sys::path::append(AbsolutePath
, CompilationDir
);
280 sys::path::append(AbsolutePath
, DWOFileName
);
281 DWO
= llvm::make_unique
<DWOHolder
>(AbsolutePath
);
282 DWARFUnit
*DWOCU
= DWO
->getUnit();
283 // Verify that compile unit in .dwo file is valid.
284 if (!DWOCU
|| DWOCU
->getDWOId() != getDWOId()) {
288 // Share .debug_addr and .debug_ranges section with compile unit in .dwo
289 DWOCU
->setAddrOffsetSection(AddrOffsetSection
, AddrOffsetSectionBase
);
290 uint32_t DWORangesBase
= DieArray
[0].getRangesBaseAttribute(this, 0);
291 DWOCU
->setRangesSection(RangeSection
, DWORangesBase
);
295 void DWARFUnit::clearDIEs(bool KeepCUDie
) {
296 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
304 std::vector
<DWARFDebugInfoEntryMinimal
> TmpArray
;
305 DieArray
.swap(TmpArray
);
306 // Save at least the compile unit DIE
308 DieArray
.push_back(TmpArray
.front());
312 void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector
&CURanges
) {
313 // First, check if CU DIE describes address ranges for the unit.
314 const auto &CUDIERanges
= getCompileUnitDIE()->getAddressRanges(this);
315 if (!CUDIERanges
.empty()) {
316 CURanges
.insert(CURanges
.end(), CUDIERanges
.begin(), CUDIERanges
.end());
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
326 const bool ClearDIEs
= extractDIEsIfNeeded(false) > 1;
327 DieArray
[0].collectChildrenAddressRanges(this, CURanges
);
329 // Collect address ranges from DIEs in .dwo if necessary.
330 bool DWOCreated
= parseDWO();
332 DWO
->getUnit()->collectAddressRanges(CURanges
);
336 // Keep memory down by clearing DIEs if this generate function
337 // caused them to be parsed.
342 const DWARFDebugInfoEntryMinimal
*
343 DWARFUnit::getSubprogramForAddress(uint64_t Address
) {
344 extractDIEsIfNeeded(false);
345 for (const DWARFDebugInfoEntryMinimal
&DIE
: DieArray
) {
346 if (DIE
.isSubprogramDIE() &&
347 DIE
.addressRangeContainsAddress(this, Address
)) {
354 DWARFDebugInfoEntryInlinedChain
355 DWARFUnit::getInlinedChainForAddress(uint64_t Address
) {
356 // First, find a subprogram that contains the given address (the root
357 // of inlined chain).
358 const DWARFUnit
*ChainCU
= nullptr;
359 const DWARFDebugInfoEntryMinimal
*SubprogramDIE
=
360 getSubprogramForAddress(Address
);
364 // Try to look for subprogram DIEs in the DWO file.
367 SubprogramDIE
= DWO
->getUnit()->getSubprogramForAddress(Address
);
369 ChainCU
= DWO
->getUnit();
373 // Get inlined chain rooted at this subprogram DIE.
375 return DWARFDebugInfoEntryInlinedChain();
376 return SubprogramDIE
->getInlinedChainForAddress(ChainCU
, Address
);