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/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/DWARFUnit.h"
17 #include "llvm/Object/ObjectFile.h"
18 #include "llvm/Support/Casting.h"
19 #include "llvm/Support/DataExtractor.h"
20 #include "llvm/Support/Path.h"
29 using namespace dwarf;
31 void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) {
32 parseImpl(C, Section, C.getDebugAbbrev(), C.getRangeSection(),
33 C.getStringSection(), StringRef(), C.getAddrSection(),
34 C.getLineSection().Data, C.isLittleEndian(), false);
37 void DWARFUnitSectionBase::parseDWO(DWARFContext &C,
38 const DWARFSection &DWOSection,
39 DWARFUnitIndex *Index) {
40 parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), C.getRangeDWOSection(),
41 C.getStringDWOSection(), C.getStringOffsetDWOSection(),
42 C.getAddrSection(), C.getLineDWOSection().Data, C.isLittleEndian(),
46 DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,
47 const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
48 StringRef SOS, StringRef AOS, StringRef LS, bool LE,
49 bool IsDWO, const DWARFUnitSectionBase &UnitSection,
50 const DWARFUnitIndex::Entry *IndexEntry)
51 : Context(DC), InfoSection(Section), Abbrev(DA), RangeSection(RS),
52 LineSection(LS), StringSection(SS), StringOffsetSection([&]() {
54 if (const auto *C = IndexEntry->getOffset(DW_SECT_STR_OFFSETS))
55 return SOS.slice(C->Offset, C->Offset + C->Length);
58 AddrOffsetSection(AOS), isLittleEndian(LE), isDWO(IsDWO),
59 UnitSection(UnitSection), IndexEntry(IndexEntry) {
63 DWARFUnit::~DWARFUnit() = default;
65 bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index,
66 uint64_t &Result) const {
67 uint32_t Offset = AddrOffsetSectionBase + Index * AddrSize;
68 if (AddrOffsetSection.size() < Offset + AddrSize)
70 DataExtractor DA(AddrOffsetSection, isLittleEndian, AddrSize);
71 Result = DA.getAddress(&Offset);
75 bool DWARFUnit::getStringOffsetSectionItem(uint32_t Index,
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)
82 DataExtractor DA(StringOffsetSection, isLittleEndian, 0);
83 Result = DA.getU32(&Offset);
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);
94 auto *UnitContrib = IndexEntry->getOffset();
95 if (!UnitContrib || UnitContrib->Length != (Length + 4))
97 auto *AbbrEntry = IndexEntry->getOffset(DW_SECT_ABBREV);
100 AbbrOffset = AbbrEntry->Offset;
102 AddrSize = debug_info.getU8(offset_ptr);
104 bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
105 bool VersionOK = DWARFContext::isSupportedVersion(Version);
106 bool AddrSizeOK = AddrSize == 4 || AddrSize == 8;
108 if (!LengthOK || !VersionOK || !AddrSizeOK)
111 Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset);
112 return Abbrevs != nullptr;
115 bool DWARFUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) {
118 Offset = *offset_ptr;
120 if (debug_info.isValidOffset(*offset_ptr)) {
121 if (extractImpl(debug_info, offset_ptr))
124 // reset the offset to where we tried to parse from if anything went wrong
125 *offset_ptr = Offset;
131 bool DWARFUnit::extractRangeList(uint32_t RangeListOffset,
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);
140 void DWARFUnit::clear() {
147 RangeSectionBase = 0;
148 AddrOffsetSectionBase = 0;
153 const char *DWARFUnit::getCompilationDir() {
154 return getUnitDIE().getAttributeValueAsString(DW_AT_comp_dir, nullptr);
157 Optional<uint64_t> DWARFUnit::getDWOId() {
158 return getUnitDIE().getAttributeValueAsUnsignedConstant(DW_AT_GNU_dwo_id);
161 void DWARFUnit::extractDIEsToVector(
162 bool AppendCUDie, bool AppendNonCUDies,
163 std::vector<DWARFDebugInfoEntry> &Dies) const {
164 if (!AppendCUDie && !AppendNonCUDies)
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();
171 DWARFDebugInfoEntry DIE;
172 DataExtractor DebugInfoData = getDebugInfoExtractor();
176 while (DIE.extractFast(*this, &DIEOffset, DebugInfoData, NextCUOffset,
181 if (!AppendNonCUDies)
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);
192 if (const DWARFAbbreviationDeclaration *AbbrDecl =
193 DIE.getAbbreviationDeclarationPtr()) {
195 if (AbbrDecl->hasChildren())
202 break; // We are done with this compile unit!
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
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);
214 size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
215 if ((CUDieOnly && !DieArray.empty()) ||
217 return 0; // Already parsed.
219 bool HasCUDie = !DieArray.empty();
220 extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray);
222 if (DieArray.empty())
225 // If CU DIE was just parsed, copy several attribute values from it.
227 DWARFDie UnitDie = getUnitDIE();
228 auto BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_low_pc);
230 BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_entry_pc);
232 setBaseAddress(*BaseAddr);
233 AddrOffsetSectionBase =
234 UnitDie.getAttributeValueAsSectionOffset(DW_AT_GNU_addr_base)
237 UnitDie.getAttributeValueAsSectionOffset(DW_AT_rnglists_base)
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.
243 return DieArray.size();
246 DWARFUnit::DWOHolder::DWOHolder(StringRef DWOPath)
248 auto Obj = object::ObjectFile::createObjectFile(DWOPath);
250 // TODO: Actually report errors helpfully.
251 consumeError(Obj.takeError());
254 DWOFile = std::move(Obj.get());
256 cast<DWARFContext>(new DWARFContextInMemory(*DWOFile.getBinary())));
257 if (DWOContext->getNumDWOCompileUnits() > 0)
258 DWOU = DWOContext->getDWOCompileUnitAtIndex(0);
261 bool DWARFUnit::parseDWO() {
266 DWARFDie UnitDie = getUnitDIE();
269 const char *DWOFileName =
270 UnitDie.getAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr);
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);
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()) {
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);
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
303 std::vector<DWARFDebugInfoEntry> TmpArray;
304 DieArray.swap(TmpArray);
305 // Save at least the compile unit DIE
307 DieArray.push_back(TmpArray.front());
311 void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) {
312 DWARFDie UnitDie = getUnitDIE();
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());
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
328 const bool ClearDIEs = extractDIEsIfNeeded(false) > 1;
329 getUnitDIE().collectChildrenAddressRanges(CURanges);
331 // Collect address ranges from DIEs in .dwo if necessary.
332 bool DWOCreated = parseDWO();
334 DWO->getUnit()->collectAddressRanges(CURanges);
338 // Keep memory down by clearing DIEs if this generate function
339 // caused them to be parsed.
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)) {
358 DWARFUnit::getInlinedChainForAddress(uint64_t Address,
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.
366 SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address);
368 SubprogramDIE = getSubprogramForAddress(Address);
370 // Get inlined chain rooted at this subprogram DIE.
372 SubprogramDIE.getInlinedChainForAddress(Address, InlinedChain);
374 InlinedChain.clear();
377 const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
378 DWARFSectionKind Kind) {
379 if (Kind == DW_SECT_INFO)
380 return Context.getCUIndex();
381 assert(Kind == DW_SECT_TYPES);
382 return Context.getTUIndex();
385 DWARFDie DWARFUnit::getParent(const DWARFDebugInfoEntry *Die) {
388 const uint32_t Depth = Die->getDepth();
389 // Unit DIEs always have a depth of zero and never have parents.
392 // Depth of 1 always means parent is the compile/type unit.
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]);
404 DWARFDie DWARFUnit::getSibling(const DWARFDebugInfoEntry *Die) {
407 uint32_t Depth = Die->getDepth();
408 // Unit DIEs always have a depth of zero and never have siblings.
411 // NULL DIEs don't have siblings.
412 if (Die->getAbbreviationDeclarationPtr() == nullptr)
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]);
423 } // end namespace llvm