10b57cec5SDimitry Andric //===- DWARFUnit.cpp ------------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 100b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 110b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 1281ad6265SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h" 130b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" 140b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" 150b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h" 160b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" 170b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" 1881ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" 1981ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" 200b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" 210b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDie.h" 2281ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFExpression.h" 230b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 2481ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFListTable.h" 2581ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFObject.h" 2681ad6265SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFSection.h" 270b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" 2881ad6265SDimitry Andric #include "llvm/Object/ObjectFile.h" 290b57cec5SDimitry Andric #include "llvm/Support/DataExtractor.h" 300b57cec5SDimitry Andric #include "llvm/Support/Errc.h" 310b57cec5SDimitry Andric #include "llvm/Support/Path.h" 320b57cec5SDimitry Andric #include <algorithm> 330b57cec5SDimitry Andric #include <cassert> 340b57cec5SDimitry Andric #include <cstddef> 350b57cec5SDimitry Andric #include <cstdint> 360b57cec5SDimitry Andric #include <utility> 370b57cec5SDimitry Andric #include <vector> 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric using namespace llvm; 400b57cec5SDimitry Andric using namespace dwarf; 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric void DWARFUnitVector::addUnitsForSection(DWARFContext &C, 430b57cec5SDimitry Andric const DWARFSection &Section, 440b57cec5SDimitry Andric DWARFSectionKind SectionKind) { 450b57cec5SDimitry Andric const DWARFObject &D = C.getDWARFObj(); 468bcb0991SDimitry Andric addUnitsImpl(C, D, Section, C.getDebugAbbrev(), &D.getRangesSection(), 478bcb0991SDimitry Andric &D.getLocSection(), D.getStrSection(), 488bcb0991SDimitry Andric D.getStrOffsetsSection(), &D.getAddrSection(), 490b57cec5SDimitry Andric D.getLineSection(), D.isLittleEndian(), false, false, 500b57cec5SDimitry Andric SectionKind); 510b57cec5SDimitry Andric } 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric void DWARFUnitVector::addUnitsForDWOSection(DWARFContext &C, 540b57cec5SDimitry Andric const DWARFSection &DWOSection, 550b57cec5SDimitry Andric DWARFSectionKind SectionKind, 560b57cec5SDimitry Andric bool Lazy) { 570b57cec5SDimitry Andric const DWARFObject &D = C.getDWARFObj(); 588bcb0991SDimitry Andric addUnitsImpl(C, D, DWOSection, C.getDebugAbbrevDWO(), &D.getRangesDWOSection(), 598bcb0991SDimitry Andric &D.getLocDWOSection(), D.getStrDWOSection(), 608bcb0991SDimitry Andric D.getStrOffsetsDWOSection(), &D.getAddrSection(), 610b57cec5SDimitry Andric D.getLineDWOSection(), C.isLittleEndian(), true, Lazy, 620b57cec5SDimitry Andric SectionKind); 630b57cec5SDimitry Andric } 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric void DWARFUnitVector::addUnitsImpl( 660b57cec5SDimitry Andric DWARFContext &Context, const DWARFObject &Obj, const DWARFSection &Section, 670b57cec5SDimitry Andric const DWARFDebugAbbrev *DA, const DWARFSection *RS, 680b57cec5SDimitry Andric const DWARFSection *LocSection, StringRef SS, const DWARFSection &SOS, 690b57cec5SDimitry Andric const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO, 700b57cec5SDimitry Andric bool Lazy, DWARFSectionKind SectionKind) { 710b57cec5SDimitry Andric DWARFDataExtractor Data(Obj, Section, LE, 0); 720b57cec5SDimitry Andric // Lazy initialization of Parser, now that we have all section info. 730b57cec5SDimitry Andric if (!Parser) { 740b57cec5SDimitry Andric Parser = [=, &Context, &Obj, &Section, &SOS, 758bcb0991SDimitry Andric &LS](uint64_t Offset, DWARFSectionKind SectionKind, 760b57cec5SDimitry Andric const DWARFSection *CurSection, 770b57cec5SDimitry Andric const DWARFUnitIndex::Entry *IndexEntry) 780b57cec5SDimitry Andric -> std::unique_ptr<DWARFUnit> { 790b57cec5SDimitry Andric const DWARFSection &InfoSection = CurSection ? *CurSection : Section; 800b57cec5SDimitry Andric DWARFDataExtractor Data(Obj, InfoSection, LE, 0); 810b57cec5SDimitry Andric if (!Data.isValidOffset(Offset)) 820b57cec5SDimitry Andric return nullptr; 830b57cec5SDimitry Andric DWARFUnitHeader Header; 845f757f3fSDimitry Andric if (Error ExtractErr = 855f757f3fSDimitry Andric Header.extract(Context, Data, &Offset, SectionKind)) { 865f757f3fSDimitry Andric Context.getWarningHandler()(std::move(ExtractErr)); 875ffd83dbSDimitry Andric return nullptr; 885f757f3fSDimitry Andric } 895ffd83dbSDimitry Andric if (!IndexEntry && IsDWO) { 905ffd83dbSDimitry Andric const DWARFUnitIndex &Index = getDWARFUnitIndex( 915ffd83dbSDimitry Andric Context, Header.isTypeUnit() ? DW_SECT_EXT_TYPES : DW_SECT_INFO); 9281ad6265SDimitry Andric if (Index) { 9381ad6265SDimitry Andric if (Header.isTypeUnit()) 9481ad6265SDimitry Andric IndexEntry = Index.getFromHash(Header.getTypeHash()); 9581ad6265SDimitry Andric else if (auto DWOId = Header.getDWOId()) 9681ad6265SDimitry Andric IndexEntry = Index.getFromHash(*DWOId); 9781ad6265SDimitry Andric } 9881ad6265SDimitry Andric if (!IndexEntry) 995ffd83dbSDimitry Andric IndexEntry = Index.getFromOffset(Header.getOffset()); 1005ffd83dbSDimitry Andric } 101*0fca6ea1SDimitry Andric if (IndexEntry) { 102*0fca6ea1SDimitry Andric if (Error ApplicationErr = Header.applyIndexEntry(IndexEntry)) { 103*0fca6ea1SDimitry Andric Context.getWarningHandler()(std::move(ApplicationErr)); 1040b57cec5SDimitry Andric return nullptr; 105*0fca6ea1SDimitry Andric } 106*0fca6ea1SDimitry Andric } 1070b57cec5SDimitry Andric std::unique_ptr<DWARFUnit> U; 1080b57cec5SDimitry Andric if (Header.isTypeUnit()) 1098bcb0991SDimitry Andric U = std::make_unique<DWARFTypeUnit>(Context, InfoSection, Header, DA, 1100b57cec5SDimitry Andric RS, LocSection, SS, SOS, AOS, LS, 1110b57cec5SDimitry Andric LE, IsDWO, *this); 1120b57cec5SDimitry Andric else 1138bcb0991SDimitry Andric U = std::make_unique<DWARFCompileUnit>(Context, InfoSection, Header, 1140b57cec5SDimitry Andric DA, RS, LocSection, SS, SOS, 1150b57cec5SDimitry Andric AOS, LS, LE, IsDWO, *this); 1160b57cec5SDimitry Andric return U; 1170b57cec5SDimitry Andric }; 1180b57cec5SDimitry Andric } 1190b57cec5SDimitry Andric if (Lazy) 1200b57cec5SDimitry Andric return; 1210b57cec5SDimitry Andric // Find a reasonable insertion point within the vector. We skip over 1220b57cec5SDimitry Andric // (a) units from a different section, (b) units from the same section 1230b57cec5SDimitry Andric // but with lower offset-within-section. This keeps units in order 1240b57cec5SDimitry Andric // within a section, although not necessarily within the object file, 1250b57cec5SDimitry Andric // even if we do lazy parsing. 1260b57cec5SDimitry Andric auto I = this->begin(); 1278bcb0991SDimitry Andric uint64_t Offset = 0; 1280b57cec5SDimitry Andric while (Data.isValidOffset(Offset)) { 1290b57cec5SDimitry Andric if (I != this->end() && 1300b57cec5SDimitry Andric (&(*I)->getInfoSection() != &Section || (*I)->getOffset() == Offset)) { 1310b57cec5SDimitry Andric ++I; 1320b57cec5SDimitry Andric continue; 1330b57cec5SDimitry Andric } 1340b57cec5SDimitry Andric auto U = Parser(Offset, SectionKind, &Section, nullptr); 1350b57cec5SDimitry Andric // If parsing failed, we're done with this section. 1360b57cec5SDimitry Andric if (!U) 1370b57cec5SDimitry Andric break; 1380b57cec5SDimitry Andric Offset = U->getNextUnitOffset(); 1390b57cec5SDimitry Andric I = std::next(this->insert(I, std::move(U))); 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric DWARFUnit *DWARFUnitVector::addUnit(std::unique_ptr<DWARFUnit> Unit) { 144bdd1243dSDimitry Andric auto I = llvm::upper_bound(*this, Unit, 1450b57cec5SDimitry Andric [](const std::unique_ptr<DWARFUnit> &LHS, 1460b57cec5SDimitry Andric const std::unique_ptr<DWARFUnit> &RHS) { 1470b57cec5SDimitry Andric return LHS->getOffset() < RHS->getOffset(); 1480b57cec5SDimitry Andric }); 1490b57cec5SDimitry Andric return this->insert(I, std::move(Unit))->get(); 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric 1528bcb0991SDimitry Andric DWARFUnit *DWARFUnitVector::getUnitForOffset(uint64_t Offset) const { 1530b57cec5SDimitry Andric auto end = begin() + getNumInfoUnits(); 1540b57cec5SDimitry Andric auto *CU = 1550b57cec5SDimitry Andric std::upper_bound(begin(), end, Offset, 1568bcb0991SDimitry Andric [](uint64_t LHS, const std::unique_ptr<DWARFUnit> &RHS) { 1570b57cec5SDimitry Andric return LHS < RHS->getNextUnitOffset(); 1580b57cec5SDimitry Andric }); 1590b57cec5SDimitry Andric if (CU != end && (*CU)->getOffset() <= Offset) 1600b57cec5SDimitry Andric return CU->get(); 1610b57cec5SDimitry Andric return nullptr; 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric DWARFUnit * 1650b57cec5SDimitry Andric DWARFUnitVector::getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) { 1665ffd83dbSDimitry Andric const auto *CUOff = E.getContribution(DW_SECT_INFO); 1670b57cec5SDimitry Andric if (!CUOff) 1680b57cec5SDimitry Andric return nullptr; 1690b57cec5SDimitry Andric 170bdd1243dSDimitry Andric uint64_t Offset = CUOff->getOffset(); 1710b57cec5SDimitry Andric auto end = begin() + getNumInfoUnits(); 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric auto *CU = 174bdd1243dSDimitry Andric std::upper_bound(begin(), end, CUOff->getOffset(), 1758bcb0991SDimitry Andric [](uint64_t LHS, const std::unique_ptr<DWARFUnit> &RHS) { 1760b57cec5SDimitry Andric return LHS < RHS->getNextUnitOffset(); 1770b57cec5SDimitry Andric }); 1780b57cec5SDimitry Andric if (CU != end && (*CU)->getOffset() <= Offset) 1790b57cec5SDimitry Andric return CU->get(); 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric if (!Parser) 1820b57cec5SDimitry Andric return nullptr; 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric auto U = Parser(Offset, DW_SECT_INFO, nullptr, &E); 1850b57cec5SDimitry Andric if (!U) 18606c3fb27SDimitry Andric return nullptr; 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric auto *NewCU = U.get(); 1890b57cec5SDimitry Andric this->insert(CU, std::move(U)); 1900b57cec5SDimitry Andric ++NumInfoUnits; 1910b57cec5SDimitry Andric return NewCU; 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section, 1950b57cec5SDimitry Andric const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA, 1960b57cec5SDimitry Andric const DWARFSection *RS, const DWARFSection *LocSection, 1970b57cec5SDimitry Andric StringRef SS, const DWARFSection &SOS, 1980b57cec5SDimitry Andric const DWARFSection *AOS, const DWARFSection &LS, bool LE, 1990b57cec5SDimitry Andric bool IsDWO, const DWARFUnitVector &UnitVector) 2000b57cec5SDimitry Andric : Context(DC), InfoSection(Section), Header(Header), Abbrev(DA), 201480093f4SDimitry Andric RangeSection(RS), LineSection(LS), StringSection(SS), 202bdd1243dSDimitry Andric StringOffsetSection(SOS), AddrOffsetSection(AOS), IsLittleEndian(LE), 203480093f4SDimitry Andric IsDWO(IsDWO), UnitVector(UnitVector) { 2040b57cec5SDimitry Andric clear(); 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric DWARFUnit::~DWARFUnit() = default; 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const { 210bdd1243dSDimitry Andric return DWARFDataExtractor(Context.getDWARFObj(), InfoSection, IsLittleEndian, 2110b57cec5SDimitry Andric getAddressByteSize()); 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric 214bdd1243dSDimitry Andric std::optional<object::SectionedAddress> 2150b57cec5SDimitry Andric DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const { 216fe6060f1SDimitry Andric if (!AddrOffsetSectionBase) { 2170b57cec5SDimitry Andric auto R = Context.info_section_units(); 2180b57cec5SDimitry Andric // Surprising if a DWO file has more than one skeleton unit in it - this 2190b57cec5SDimitry Andric // probably shouldn't be valid, but if a use case is found, here's where to 2200b57cec5SDimitry Andric // support it (probably have to linearly search for the matching skeleton CU 2210b57cec5SDimitry Andric // here) 222fe6060f1SDimitry Andric if (IsDWO && hasSingleElement(R)) 223e8d8bef9SDimitry Andric return (*R.begin())->getAddrOffsetSectionItem(Index); 224fe6060f1SDimitry Andric 225bdd1243dSDimitry Andric return std::nullopt; 226fe6060f1SDimitry Andric } 227fe6060f1SDimitry Andric 228480093f4SDimitry Andric uint64_t Offset = *AddrOffsetSectionBase + Index * getAddressByteSize(); 2290b57cec5SDimitry Andric if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize()) 230bdd1243dSDimitry Andric return std::nullopt; 2310b57cec5SDimitry Andric DWARFDataExtractor DA(Context.getDWARFObj(), *AddrOffsetSection, 232bdd1243dSDimitry Andric IsLittleEndian, getAddressByteSize()); 2330b57cec5SDimitry Andric uint64_t Section; 2340b57cec5SDimitry Andric uint64_t Address = DA.getRelocatedAddress(&Offset, &Section); 2350b57cec5SDimitry Andric return {{Address, Section}}; 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric 2380eae32dcSDimitry Andric Expected<uint64_t> DWARFUnit::getStringOffsetSectionItem(uint32_t Index) const { 2390b57cec5SDimitry Andric if (!StringOffsetsTableContribution) 2400eae32dcSDimitry Andric return make_error<StringError>( 2410eae32dcSDimitry Andric "DW_FORM_strx used without a valid string offsets table", 2420eae32dcSDimitry Andric inconvertibleErrorCode()); 2430b57cec5SDimitry Andric unsigned ItemSize = getDwarfStringOffsetsByteSize(); 2448bcb0991SDimitry Andric uint64_t Offset = getStringOffsetsBase() + Index * ItemSize; 2450b57cec5SDimitry Andric if (StringOffsetSection.Data.size() < Offset + ItemSize) 2460eae32dcSDimitry Andric return make_error<StringError>("DW_FORM_strx uses index " + Twine(Index) + 2470eae32dcSDimitry Andric ", which is too large", 2480eae32dcSDimitry Andric inconvertibleErrorCode()); 2490b57cec5SDimitry Andric DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, 250bdd1243dSDimitry Andric IsLittleEndian, 0); 2510b57cec5SDimitry Andric return DA.getRelocatedValue(ItemSize, &Offset); 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric 2545f757f3fSDimitry Andric Error DWARFUnitHeader::extract(DWARFContext &Context, 2550b57cec5SDimitry Andric const DWARFDataExtractor &debug_info, 2568bcb0991SDimitry Andric uint64_t *offset_ptr, 2575ffd83dbSDimitry Andric DWARFSectionKind SectionKind) { 2580b57cec5SDimitry Andric Offset = *offset_ptr; 259480093f4SDimitry Andric Error Err = Error::success(); 2605ffd83dbSDimitry Andric IndexEntry = nullptr; 2615ffd83dbSDimitry Andric std::tie(Length, FormParams.Format) = 2625ffd83dbSDimitry Andric debug_info.getInitialLength(offset_ptr, &Err); 263480093f4SDimitry Andric FormParams.Version = debug_info.getU16(offset_ptr, &Err); 2640b57cec5SDimitry Andric if (FormParams.Version >= 5) { 265480093f4SDimitry Andric UnitType = debug_info.getU8(offset_ptr, &Err); 266480093f4SDimitry Andric FormParams.AddrSize = debug_info.getU8(offset_ptr, &Err); 267480093f4SDimitry Andric AbbrOffset = debug_info.getRelocatedValue( 268480093f4SDimitry Andric FormParams.getDwarfOffsetByteSize(), offset_ptr, nullptr, &Err); 2690b57cec5SDimitry Andric } else { 270480093f4SDimitry Andric AbbrOffset = debug_info.getRelocatedValue( 271480093f4SDimitry Andric FormParams.getDwarfOffsetByteSize(), offset_ptr, nullptr, &Err); 272480093f4SDimitry Andric FormParams.AddrSize = debug_info.getU8(offset_ptr, &Err); 2730b57cec5SDimitry Andric // Fake a unit type based on the section type. This isn't perfect, 2740b57cec5SDimitry Andric // but distinguishing compile and type units is generally enough. 2755ffd83dbSDimitry Andric if (SectionKind == DW_SECT_EXT_TYPES) 2760b57cec5SDimitry Andric UnitType = DW_UT_type; 2770b57cec5SDimitry Andric else 2780b57cec5SDimitry Andric UnitType = DW_UT_compile; 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric if (isTypeUnit()) { 281480093f4SDimitry Andric TypeHash = debug_info.getU64(offset_ptr, &Err); 282480093f4SDimitry Andric TypeOffset = debug_info.getUnsigned( 283480093f4SDimitry Andric offset_ptr, FormParams.getDwarfOffsetByteSize(), &Err); 2840b57cec5SDimitry Andric } else if (UnitType == DW_UT_split_compile || UnitType == DW_UT_skeleton) 285480093f4SDimitry Andric DWOId = debug_info.getU64(offset_ptr, &Err); 286480093f4SDimitry Andric 2875f757f3fSDimitry Andric if (Err) 2885f757f3fSDimitry Andric return joinErrors( 289fe6060f1SDimitry Andric createStringError( 290fe6060f1SDimitry Andric errc::invalid_argument, 291fe6060f1SDimitry Andric "DWARF unit at 0x%8.8" PRIx64 " cannot be parsed:", Offset), 2925f757f3fSDimitry Andric std::move(Err)); 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric // Header fields all parsed, capture the size of this unit header. 2950b57cec5SDimitry Andric assert(*offset_ptr - Offset <= 255 && "unexpected header size"); 2960b57cec5SDimitry Andric Size = uint8_t(*offset_ptr - Offset); 297fe6060f1SDimitry Andric uint64_t NextCUOffset = Offset + getUnitLengthFieldByteSize() + getLength(); 298fe6060f1SDimitry Andric 2995f757f3fSDimitry Andric if (!debug_info.isValidOffset(getNextUnitOffset() - 1)) 3005f757f3fSDimitry Andric return createStringError(errc::invalid_argument, 301fe6060f1SDimitry Andric "DWARF unit from offset 0x%8.8" PRIx64 " incl. " 302fe6060f1SDimitry Andric "to offset 0x%8.8" PRIx64 " excl. " 303fe6060f1SDimitry Andric "extends past section size 0x%8.8zx", 3045f757f3fSDimitry Andric Offset, NextCUOffset, debug_info.size()); 305fe6060f1SDimitry Andric 3065f757f3fSDimitry Andric if (!DWARFContext::isSupportedVersion(getVersion())) 3075f757f3fSDimitry Andric return createStringError( 308fe6060f1SDimitry Andric errc::invalid_argument, 309fe6060f1SDimitry Andric "DWARF unit at offset 0x%8.8" PRIx64 " " 310fe6060f1SDimitry Andric "has unsupported version %" PRIu16 ", supported are 2-%u", 3115f757f3fSDimitry Andric Offset, getVersion(), DWARFContext::getMaxSupportedVersion()); 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric // Type offset is unit-relative; should be after the header and before 3140b57cec5SDimitry Andric // the end of the current unit. 3155f757f3fSDimitry Andric if (isTypeUnit() && TypeOffset < Size) 3165f757f3fSDimitry Andric return createStringError(errc::invalid_argument, 317fe6060f1SDimitry Andric "DWARF type unit at offset " 318fe6060f1SDimitry Andric "0x%8.8" PRIx64 " " 319fe6060f1SDimitry Andric "has its relocated type_offset 0x%8.8" PRIx64 " " 320fe6060f1SDimitry Andric "pointing inside the header", 3215f757f3fSDimitry Andric Offset, Offset + TypeOffset); 3225f757f3fSDimitry Andric 3235f757f3fSDimitry Andric if (isTypeUnit() && TypeOffset >= getUnitLengthFieldByteSize() + getLength()) 3245f757f3fSDimitry Andric return createStringError( 325fe6060f1SDimitry Andric errc::invalid_argument, 326fe6060f1SDimitry Andric "DWARF type unit from offset 0x%8.8" PRIx64 " incl. " 327fe6060f1SDimitry Andric "to offset 0x%8.8" PRIx64 " excl. has its " 328fe6060f1SDimitry Andric "relocated type_offset 0x%8.8" PRIx64 " pointing past the unit end", 3295f757f3fSDimitry Andric Offset, NextCUOffset, Offset + TypeOffset); 330fe6060f1SDimitry Andric 331349cc55cSDimitry Andric if (Error SizeErr = DWARFContext::checkAddressSizeSupported( 332349cc55cSDimitry Andric getAddressByteSize(), errc::invalid_argument, 3335f757f3fSDimitry Andric "DWARF unit at offset 0x%8.8" PRIx64, Offset)) 3345f757f3fSDimitry Andric return SizeErr; 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric // Keep track of the highest DWARF version we encounter across all units. 3370b57cec5SDimitry Andric Context.setMaxVersionIfGreater(getVersion()); 3385f757f3fSDimitry Andric return Error::success(); 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric 341*0fca6ea1SDimitry Andric Error DWARFUnitHeader::applyIndexEntry(const DWARFUnitIndex::Entry *Entry) { 3425ffd83dbSDimitry Andric assert(Entry); 3435ffd83dbSDimitry Andric assert(!IndexEntry); 3445ffd83dbSDimitry Andric IndexEntry = Entry; 3455ffd83dbSDimitry Andric if (AbbrOffset) 346*0fca6ea1SDimitry Andric return createStringError(errc::invalid_argument, 347*0fca6ea1SDimitry Andric "DWARF package unit at offset 0x%8.8" PRIx64 348*0fca6ea1SDimitry Andric " has a non-zero abbreviation offset", 349*0fca6ea1SDimitry Andric Offset); 350*0fca6ea1SDimitry Andric 3515ffd83dbSDimitry Andric auto *UnitContrib = IndexEntry->getContribution(); 352*0fca6ea1SDimitry Andric if (!UnitContrib) 353*0fca6ea1SDimitry Andric return createStringError(errc::invalid_argument, 354*0fca6ea1SDimitry Andric "DWARF package unit at offset 0x%8.8" PRIx64 355*0fca6ea1SDimitry Andric " has no contribution index", 356*0fca6ea1SDimitry Andric Offset); 357*0fca6ea1SDimitry Andric 358*0fca6ea1SDimitry Andric uint64_t IndexLength = getLength() + getUnitLengthFieldByteSize(); 359*0fca6ea1SDimitry Andric if (UnitContrib->getLength() != IndexLength) 360*0fca6ea1SDimitry Andric return createStringError(errc::invalid_argument, 361*0fca6ea1SDimitry Andric "DWARF package unit at offset 0x%8.8" PRIx64 362*0fca6ea1SDimitry Andric " has an inconsistent index (expected: %" PRIu64 363*0fca6ea1SDimitry Andric ", actual: %" PRIu64 ")", 364*0fca6ea1SDimitry Andric Offset, UnitContrib->getLength(), IndexLength); 365*0fca6ea1SDimitry Andric 3665ffd83dbSDimitry Andric auto *AbbrEntry = IndexEntry->getContribution(DW_SECT_ABBREV); 3675ffd83dbSDimitry Andric if (!AbbrEntry) 368*0fca6ea1SDimitry Andric return createStringError(errc::invalid_argument, 369*0fca6ea1SDimitry Andric "DWARF package unit at offset 0x%8.8" PRIx64 370*0fca6ea1SDimitry Andric " missing abbreviation column", 371*0fca6ea1SDimitry Andric Offset); 372*0fca6ea1SDimitry Andric 373bdd1243dSDimitry Andric AbbrOffset = AbbrEntry->getOffset(); 374*0fca6ea1SDimitry Andric return Error::success(); 3755ffd83dbSDimitry Andric } 3765ffd83dbSDimitry Andric 3778bcb0991SDimitry Andric Error DWARFUnit::extractRangeList(uint64_t RangeListOffset, 3780b57cec5SDimitry Andric DWARFDebugRangeList &RangeList) const { 3790b57cec5SDimitry Andric // Require that compile unit is extracted. 3800b57cec5SDimitry Andric assert(!DieArray.empty()); 3810b57cec5SDimitry Andric DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, 382bdd1243dSDimitry Andric IsLittleEndian, getAddressByteSize()); 3838bcb0991SDimitry Andric uint64_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; 3840b57cec5SDimitry Andric return RangeList.extract(RangesData, &ActualRangeListOffset); 3850b57cec5SDimitry Andric } 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric void DWARFUnit::clear() { 3880b57cec5SDimitry Andric Abbrevs = nullptr; 3890b57cec5SDimitry Andric BaseAddr.reset(); 3900b57cec5SDimitry Andric RangeSectionBase = 0; 391480093f4SDimitry Andric LocSectionBase = 0; 392bdd1243dSDimitry Andric AddrOffsetSectionBase = std::nullopt; 393fe6060f1SDimitry Andric SU = nullptr; 3940b57cec5SDimitry Andric clearDIEs(false); 39581ad6265SDimitry Andric AddrDieMap.clear(); 39681ad6265SDimitry Andric if (DWO) 39781ad6265SDimitry Andric DWO->clear(); 3980b57cec5SDimitry Andric DWO.reset(); 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric const char *DWARFUnit::getCompilationDir() { 4020b57cec5SDimitry Andric return dwarf::toString(getUnitDIE().find(DW_AT_comp_dir), nullptr); 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric void DWARFUnit::extractDIEsToVector( 4060b57cec5SDimitry Andric bool AppendCUDie, bool AppendNonCUDies, 4070b57cec5SDimitry Andric std::vector<DWARFDebugInfoEntry> &Dies) const { 4080b57cec5SDimitry Andric if (!AppendCUDie && !AppendNonCUDies) 4090b57cec5SDimitry Andric return; 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric // Set the offset to that of the first DIE and calculate the start of the 4120b57cec5SDimitry Andric // next compilation unit header. 4138bcb0991SDimitry Andric uint64_t DIEOffset = getOffset() + getHeaderSize(); 4148bcb0991SDimitry Andric uint64_t NextCUOffset = getNextUnitOffset(); 4150b57cec5SDimitry Andric DWARFDebugInfoEntry DIE; 4160b57cec5SDimitry Andric DWARFDataExtractor DebugInfoData = getDebugInfoExtractor(); 417fe6060f1SDimitry Andric // The end offset has been already checked by DWARFUnitHeader::extract. 418fe6060f1SDimitry Andric assert(DebugInfoData.isValidOffset(NextCUOffset - 1)); 419349cc55cSDimitry Andric std::vector<uint32_t> Parents; 420349cc55cSDimitry Andric std::vector<uint32_t> PrevSiblings; 4210b57cec5SDimitry Andric bool IsCUDie = true; 4220b57cec5SDimitry Andric 423349cc55cSDimitry Andric assert( 424349cc55cSDimitry Andric ((AppendCUDie && Dies.empty()) || (!AppendCUDie && Dies.size() == 1)) && 425349cc55cSDimitry Andric "Dies array is not empty"); 426349cc55cSDimitry Andric 427349cc55cSDimitry Andric // Fill Parents and Siblings stacks with initial value. 428349cc55cSDimitry Andric Parents.push_back(UINT32_MAX); 429349cc55cSDimitry Andric if (!AppendCUDie) 430349cc55cSDimitry Andric Parents.push_back(0); 431349cc55cSDimitry Andric PrevSiblings.push_back(0); 432349cc55cSDimitry Andric 433349cc55cSDimitry Andric // Start to extract dies. 434349cc55cSDimitry Andric do { 435349cc55cSDimitry Andric assert(Parents.size() > 0 && "Empty parents stack"); 436349cc55cSDimitry Andric assert((Parents.back() == UINT32_MAX || Parents.back() <= Dies.size()) && 437349cc55cSDimitry Andric "Wrong parent index"); 438349cc55cSDimitry Andric 43981ad6265SDimitry Andric // Extract die. Stop if any error occurred. 440349cc55cSDimitry Andric if (!DIE.extractFast(*this, &DIEOffset, DebugInfoData, NextCUOffset, 441349cc55cSDimitry Andric Parents.back())) 442349cc55cSDimitry Andric break; 443349cc55cSDimitry Andric 444349cc55cSDimitry Andric // If previous sibling is remembered then update it`s SiblingIdx field. 445349cc55cSDimitry Andric if (PrevSiblings.back() > 0) { 446349cc55cSDimitry Andric assert(PrevSiblings.back() < Dies.size() && 447349cc55cSDimitry Andric "Previous sibling index is out of Dies boundaries"); 448349cc55cSDimitry Andric Dies[PrevSiblings.back()].setSiblingIdx(Dies.size()); 449349cc55cSDimitry Andric } 450349cc55cSDimitry Andric 451349cc55cSDimitry Andric // Store die into the Dies vector. 4520b57cec5SDimitry Andric if (IsCUDie) { 4530b57cec5SDimitry Andric if (AppendCUDie) 4540b57cec5SDimitry Andric Dies.push_back(DIE); 4550b57cec5SDimitry Andric if (!AppendNonCUDies) 4560b57cec5SDimitry Andric break; 4570b57cec5SDimitry Andric // The average bytes per DIE entry has been seen to be 4580b57cec5SDimitry Andric // around 14-20 so let's pre-reserve the needed memory for 4590b57cec5SDimitry Andric // our DIE entries accordingly. 4600b57cec5SDimitry Andric Dies.reserve(Dies.size() + getDebugInfoSize() / 14); 4610b57cec5SDimitry Andric } else { 462349cc55cSDimitry Andric // Remember last previous sibling. 463349cc55cSDimitry Andric PrevSiblings.back() = Dies.size(); 464349cc55cSDimitry Andric 4650b57cec5SDimitry Andric Dies.push_back(DIE); 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric 468349cc55cSDimitry Andric // Check for new children scope. 4690b57cec5SDimitry Andric if (const DWARFAbbreviationDeclaration *AbbrDecl = 4700b57cec5SDimitry Andric DIE.getAbbreviationDeclarationPtr()) { 471349cc55cSDimitry Andric if (AbbrDecl->hasChildren()) { 472349cc55cSDimitry Andric if (AppendCUDie || !IsCUDie) { 473349cc55cSDimitry Andric assert(Dies.size() > 0 && "Dies does not contain any die"); 474349cc55cSDimitry Andric Parents.push_back(Dies.size() - 1); 475349cc55cSDimitry Andric PrevSiblings.push_back(0); 476349cc55cSDimitry Andric } 477349cc55cSDimitry Andric } else if (IsCUDie) 478349cc55cSDimitry Andric // Stop if we have single compile unit die w/o children. 479349cc55cSDimitry Andric break; 4800b57cec5SDimitry Andric } else { 481349cc55cSDimitry Andric // NULL DIE: finishes current children scope. 482349cc55cSDimitry Andric Parents.pop_back(); 483349cc55cSDimitry Andric PrevSiblings.pop_back(); 4840b57cec5SDimitry Andric } 485349cc55cSDimitry Andric 486349cc55cSDimitry Andric if (IsCUDie) 487349cc55cSDimitry Andric IsCUDie = false; 488349cc55cSDimitry Andric 489349cc55cSDimitry Andric // Stop when compile unit die is removed from the parents stack. 490349cc55cSDimitry Andric } while (Parents.size() > 1); 4910b57cec5SDimitry Andric } 4920b57cec5SDimitry Andric 4938bcb0991SDimitry Andric void DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { 4948bcb0991SDimitry Andric if (Error e = tryExtractDIEsIfNeeded(CUDieOnly)) 4955ffd83dbSDimitry Andric Context.getRecoverableErrorHandler()(std::move(e)); 4968bcb0991SDimitry Andric } 4978bcb0991SDimitry Andric 4988bcb0991SDimitry Andric Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) { 4990b57cec5SDimitry Andric if ((CUDieOnly && !DieArray.empty()) || 5000b57cec5SDimitry Andric DieArray.size() > 1) 5018bcb0991SDimitry Andric return Error::success(); // Already parsed. 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric bool HasCUDie = !DieArray.empty(); 5040b57cec5SDimitry Andric extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray); 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andric if (DieArray.empty()) 5078bcb0991SDimitry Andric return Error::success(); 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric // If CU DIE was just parsed, copy several attribute values from it. 5108bcb0991SDimitry Andric if (HasCUDie) 5118bcb0991SDimitry Andric return Error::success(); 5128bcb0991SDimitry Andric 5138bcb0991SDimitry Andric DWARFDie UnitDie(this, &DieArray[0]); 514bdd1243dSDimitry Andric if (std::optional<uint64_t> DWOId = 515bdd1243dSDimitry Andric toUnsigned(UnitDie.find(DW_AT_GNU_dwo_id))) 5160b57cec5SDimitry Andric Header.setDWOId(*DWOId); 5170b57cec5SDimitry Andric if (!IsDWO) { 518bdd1243dSDimitry Andric assert(AddrOffsetSectionBase == std::nullopt); 5190b57cec5SDimitry Andric assert(RangeSectionBase == 0); 520480093f4SDimitry Andric assert(LocSectionBase == 0); 521480093f4SDimitry Andric AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_addr_base)); 5220b57cec5SDimitry Andric if (!AddrOffsetSectionBase) 5230b57cec5SDimitry Andric AddrOffsetSectionBase = 524480093f4SDimitry Andric toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base)); 5250b57cec5SDimitry Andric RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0); 526480093f4SDimitry Andric LocSectionBase = toSectionOffset(UnitDie.find(DW_AT_loclists_base), 0); 5270b57cec5SDimitry Andric } 5280b57cec5SDimitry Andric 5290b57cec5SDimitry Andric // In general, in DWARF v5 and beyond we derive the start of the unit's 5300b57cec5SDimitry Andric // contribution to the string offsets table from the unit DIE's 5310b57cec5SDimitry Andric // DW_AT_str_offsets_base attribute. Split DWARF units do not use this 5320b57cec5SDimitry Andric // attribute, so we assume that there is a contribution to the string 5330b57cec5SDimitry Andric // offsets table starting at offset 0 of the debug_str_offsets.dwo section. 5340b57cec5SDimitry Andric // In both cases we need to determine the format of the contribution, 5350b57cec5SDimitry Andric // which may differ from the unit's format. 5360b57cec5SDimitry Andric DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, 537bdd1243dSDimitry Andric IsLittleEndian, 0); 5380b57cec5SDimitry Andric if (IsDWO || getVersion() >= 5) { 5390b57cec5SDimitry Andric auto StringOffsetOrError = 5400b57cec5SDimitry Andric IsDWO ? determineStringOffsetsTableContributionDWO(DA) 5410b57cec5SDimitry Andric : determineStringOffsetsTableContribution(DA); 5428bcb0991SDimitry Andric if (!StringOffsetOrError) 5438bcb0991SDimitry Andric return createStringError(errc::invalid_argument, 5448bcb0991SDimitry Andric "invalid reference to or invalid content in " 5458bcb0991SDimitry Andric ".debug_str_offsets[.dwo]: " + 5468bcb0991SDimitry Andric toString(StringOffsetOrError.takeError())); 5478bcb0991SDimitry Andric 5480b57cec5SDimitry Andric StringOffsetsTableContribution = *StringOffsetOrError; 5490b57cec5SDimitry Andric } 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric // DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to 5520b57cec5SDimitry Andric // describe address ranges. 5530b57cec5SDimitry Andric if (getVersion() >= 5) { 5545ffd83dbSDimitry Andric // In case of DWP, the base offset from the index has to be added. 5555ffd83dbSDimitry Andric if (IsDWO) { 556e8d8bef9SDimitry Andric uint64_t ContributionBaseOffset = 0; 5575ffd83dbSDimitry Andric if (auto *IndexEntry = Header.getIndexEntry()) 5585ffd83dbSDimitry Andric if (auto *Contrib = IndexEntry->getContribution(DW_SECT_RNGLISTS)) 559bdd1243dSDimitry Andric ContributionBaseOffset = Contrib->getOffset(); 5605ffd83dbSDimitry Andric setRangesSection( 5615ffd83dbSDimitry Andric &Context.getDWARFObj().getRnglistsDWOSection(), 5625ffd83dbSDimitry Andric ContributionBaseOffset + 5635ffd83dbSDimitry Andric DWARFListTableHeader::getHeaderSize(Header.getFormat())); 5645ffd83dbSDimitry Andric } else 5650b57cec5SDimitry Andric setRangesSection(&Context.getDWARFObj().getRnglistsSection(), 566e8d8bef9SDimitry Andric toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 567e8d8bef9SDimitry Andric DWARFListTableHeader::getHeaderSize( 568e8d8bef9SDimitry Andric Header.getFormat()))); 5690b57cec5SDimitry Andric } 570480093f4SDimitry Andric 5715ffd83dbSDimitry Andric if (IsDWO) { 572e8d8bef9SDimitry Andric // If we are reading a package file, we need to adjust the location list 573e8d8bef9SDimitry Andric // data based on the index entries. 574e8d8bef9SDimitry Andric StringRef Data = Header.getVersion() >= 5 575e8d8bef9SDimitry Andric ? Context.getDWARFObj().getLoclistsDWOSection().Data 576e8d8bef9SDimitry Andric : Context.getDWARFObj().getLocDWOSection().Data; 5775ffd83dbSDimitry Andric if (auto *IndexEntry = Header.getIndexEntry()) 578e8d8bef9SDimitry Andric if (const auto *C = IndexEntry->getContribution( 579e8d8bef9SDimitry Andric Header.getVersion() >= 5 ? DW_SECT_LOCLISTS : DW_SECT_EXT_LOC)) 580bdd1243dSDimitry Andric Data = Data.substr(C->getOffset(), C->getLength()); 581e8d8bef9SDimitry Andric 582bdd1243dSDimitry Andric DWARFDataExtractor DWARFData(Data, IsLittleEndian, getAddressByteSize()); 583e8d8bef9SDimitry Andric LocTable = 584e8d8bef9SDimitry Andric std::make_unique<DWARFDebugLoclists>(DWARFData, Header.getVersion()); 585e8d8bef9SDimitry Andric LocSectionBase = DWARFListTableHeader::getHeaderSize(Header.getFormat()); 586e8d8bef9SDimitry Andric } else if (getVersion() >= 5) { 587e8d8bef9SDimitry Andric LocTable = std::make_unique<DWARFDebugLoclists>( 588e8d8bef9SDimitry Andric DWARFDataExtractor(Context.getDWARFObj(), 589e8d8bef9SDimitry Andric Context.getDWARFObj().getLoclistsSection(), 590bdd1243dSDimitry Andric IsLittleEndian, getAddressByteSize()), 591e8d8bef9SDimitry Andric getVersion()); 592e8d8bef9SDimitry Andric } else { 593e8d8bef9SDimitry Andric LocTable = std::make_unique<DWARFDebugLoc>(DWARFDataExtractor( 594e8d8bef9SDimitry Andric Context.getDWARFObj(), Context.getDWARFObj().getLocSection(), 595bdd1243dSDimitry Andric IsLittleEndian, getAddressByteSize())); 5960b57cec5SDimitry Andric } 5970b57cec5SDimitry Andric 5980b57cec5SDimitry Andric // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for 5990b57cec5SDimitry Andric // skeleton CU DIE, so that DWARF users not aware of it are not broken. 6008bcb0991SDimitry Andric return Error::success(); 6010b57cec5SDimitry Andric } 6020b57cec5SDimitry Andric 603bdd1243dSDimitry Andric bool DWARFUnit::parseDWO(StringRef DWOAlternativeLocation) { 6040b57cec5SDimitry Andric if (IsDWO) 6050b57cec5SDimitry Andric return false; 606bdd1243dSDimitry Andric if (DWO) 6070b57cec5SDimitry Andric return false; 6080b57cec5SDimitry Andric DWARFDie UnitDie = getUnitDIE(); 6090b57cec5SDimitry Andric if (!UnitDie) 6100b57cec5SDimitry Andric return false; 611480093f4SDimitry Andric auto DWOFileName = getVersion() >= 5 612480093f4SDimitry Andric ? dwarf::toString(UnitDie.find(DW_AT_dwo_name)) 613480093f4SDimitry Andric : dwarf::toString(UnitDie.find(DW_AT_GNU_dwo_name)); 6140b57cec5SDimitry Andric if (!DWOFileName) 6150b57cec5SDimitry Andric return false; 6160b57cec5SDimitry Andric auto CompilationDir = dwarf::toString(UnitDie.find(DW_AT_comp_dir)); 6170b57cec5SDimitry Andric SmallString<16> AbsolutePath; 6180b57cec5SDimitry Andric if (sys::path::is_relative(*DWOFileName) && CompilationDir && 6190b57cec5SDimitry Andric *CompilationDir) { 6200b57cec5SDimitry Andric sys::path::append(AbsolutePath, *CompilationDir); 6210b57cec5SDimitry Andric } 6220b57cec5SDimitry Andric sys::path::append(AbsolutePath, *DWOFileName); 6230b57cec5SDimitry Andric auto DWOId = getDWOId(); 6240b57cec5SDimitry Andric if (!DWOId) 6250b57cec5SDimitry Andric return false; 6260b57cec5SDimitry Andric auto DWOContext = Context.getDWOContext(AbsolutePath); 627bdd1243dSDimitry Andric if (!DWOContext) { 628bdd1243dSDimitry Andric // Use the alternative location to get the DWARF context for the DWO object. 629bdd1243dSDimitry Andric if (DWOAlternativeLocation.empty()) 630bdd1243dSDimitry Andric return false; 631bdd1243dSDimitry Andric // If the alternative context does not correspond to the original DWO object 632bdd1243dSDimitry Andric // (different hashes), the below 'getDWOCompileUnitForHash' call will catch 633bdd1243dSDimitry Andric // the issue, with a returned null context. 634bdd1243dSDimitry Andric DWOContext = Context.getDWOContext(DWOAlternativeLocation); 6350b57cec5SDimitry Andric if (!DWOContext) 6360b57cec5SDimitry Andric return false; 637bdd1243dSDimitry Andric } 6380b57cec5SDimitry Andric 6390b57cec5SDimitry Andric DWARFCompileUnit *DWOCU = DWOContext->getDWOCompileUnitForHash(*DWOId); 6400b57cec5SDimitry Andric if (!DWOCU) 6410b57cec5SDimitry Andric return false; 6420b57cec5SDimitry Andric DWO = std::shared_ptr<DWARFCompileUnit>(std::move(DWOContext), DWOCU); 643fe6060f1SDimitry Andric DWO->setSkeletonUnit(this); 6440b57cec5SDimitry Andric // Share .debug_addr and .debug_ranges section with compile unit in .dwo 645480093f4SDimitry Andric if (AddrOffsetSectionBase) 646480093f4SDimitry Andric DWO->setAddrOffsetSection(AddrOffsetSection, *AddrOffsetSectionBase); 647fe6060f1SDimitry Andric if (getVersion() == 4) { 6480b57cec5SDimitry Andric auto DWORangesBase = UnitDie.getRangesBaseAttribute(); 64981ad6265SDimitry Andric DWO->setRangesSection(RangeSection, DWORangesBase.value_or(0)); 6500b57cec5SDimitry Andric } 6510b57cec5SDimitry Andric 6520b57cec5SDimitry Andric return true; 6530b57cec5SDimitry Andric } 6540b57cec5SDimitry Andric 6550b57cec5SDimitry Andric void DWARFUnit::clearDIEs(bool KeepCUDie) { 656349cc55cSDimitry Andric // Do not use resize() + shrink_to_fit() to free memory occupied by dies. 657349cc55cSDimitry Andric // shrink_to_fit() is a *non-binding* request to reduce capacity() to size(). 658349cc55cSDimitry Andric // It depends on the implementation whether the request is fulfilled. 659349cc55cSDimitry Andric // Create a new vector with a small capacity and assign it to the DieArray to 660349cc55cSDimitry Andric // have previous contents freed. 661349cc55cSDimitry Andric DieArray = (KeepCUDie && !DieArray.empty()) 662349cc55cSDimitry Andric ? std::vector<DWARFDebugInfoEntry>({DieArray[0]}) 663349cc55cSDimitry Andric : std::vector<DWARFDebugInfoEntry>(); 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric Expected<DWARFAddressRangesVector> 6678bcb0991SDimitry Andric DWARFUnit::findRnglistFromOffset(uint64_t Offset) { 6680b57cec5SDimitry Andric if (getVersion() <= 4) { 6690b57cec5SDimitry Andric DWARFDebugRangeList RangeList; 6700b57cec5SDimitry Andric if (Error E = extractRangeList(Offset, RangeList)) 6710b57cec5SDimitry Andric return std::move(E); 6720b57cec5SDimitry Andric return RangeList.getAbsoluteRanges(getBaseAddress()); 6730b57cec5SDimitry Andric } 6740b57cec5SDimitry Andric DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, 675bdd1243dSDimitry Andric IsLittleEndian, Header.getAddressByteSize()); 676e8d8bef9SDimitry Andric DWARFDebugRnglistTable RnglistTable; 677e8d8bef9SDimitry Andric auto RangeListOrError = RnglistTable.findList(RangesData, Offset); 6780b57cec5SDimitry Andric if (RangeListOrError) 6790b57cec5SDimitry Andric return RangeListOrError.get().getAbsoluteRanges(getBaseAddress(), *this); 6800b57cec5SDimitry Andric return RangeListOrError.takeError(); 6810b57cec5SDimitry Andric } 6820b57cec5SDimitry Andric 6830b57cec5SDimitry Andric Expected<DWARFAddressRangesVector> 6840b57cec5SDimitry Andric DWARFUnit::findRnglistFromIndex(uint32_t Index) { 6850b57cec5SDimitry Andric if (auto Offset = getRnglistOffset(Index)) 686480093f4SDimitry Andric return findRnglistFromOffset(*Offset); 6870b57cec5SDimitry Andric 6880b57cec5SDimitry Andric return createStringError(errc::invalid_argument, 689e8d8bef9SDimitry Andric "invalid range list table index %d (possibly " 690e8d8bef9SDimitry Andric "missing the entire range list table)", 691e8d8bef9SDimitry Andric Index); 6920b57cec5SDimitry Andric } 6930b57cec5SDimitry Andric 6940b57cec5SDimitry Andric Expected<DWARFAddressRangesVector> DWARFUnit::collectAddressRanges() { 6950b57cec5SDimitry Andric DWARFDie UnitDie = getUnitDIE(); 6960b57cec5SDimitry Andric if (!UnitDie) 6970b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "No unit DIE"); 6980b57cec5SDimitry Andric 6990b57cec5SDimitry Andric // First, check if unit DIE describes address ranges for the whole unit. 7000b57cec5SDimitry Andric auto CUDIERangesOrError = UnitDie.getAddressRanges(); 7010b57cec5SDimitry Andric if (!CUDIERangesOrError) 7020b57cec5SDimitry Andric return createStringError(errc::invalid_argument, 7030b57cec5SDimitry Andric "decoding address ranges: %s", 7040b57cec5SDimitry Andric toString(CUDIERangesOrError.takeError()).c_str()); 7050b57cec5SDimitry Andric return *CUDIERangesOrError; 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric 708480093f4SDimitry Andric Expected<DWARFLocationExpressionsVector> 709480093f4SDimitry Andric DWARFUnit::findLoclistFromOffset(uint64_t Offset) { 710480093f4SDimitry Andric DWARFLocationExpressionsVector Result; 711480093f4SDimitry Andric 712480093f4SDimitry Andric Error InterpretationError = Error::success(); 713480093f4SDimitry Andric 714480093f4SDimitry Andric Error ParseError = getLocationTable().visitAbsoluteLocationList( 715480093f4SDimitry Andric Offset, getBaseAddress(), 716480093f4SDimitry Andric [this](uint32_t Index) { return getAddrOffsetSectionItem(Index); }, 717480093f4SDimitry Andric [&](Expected<DWARFLocationExpression> L) { 718480093f4SDimitry Andric if (L) 719480093f4SDimitry Andric Result.push_back(std::move(*L)); 720480093f4SDimitry Andric else 721480093f4SDimitry Andric InterpretationError = 722480093f4SDimitry Andric joinErrors(L.takeError(), std::move(InterpretationError)); 723480093f4SDimitry Andric return !InterpretationError; 724480093f4SDimitry Andric }); 725480093f4SDimitry Andric 726480093f4SDimitry Andric if (ParseError || InterpretationError) 727480093f4SDimitry Andric return joinErrors(std::move(ParseError), std::move(InterpretationError)); 728480093f4SDimitry Andric 729480093f4SDimitry Andric return Result; 730480093f4SDimitry Andric } 731480093f4SDimitry Andric 7320b57cec5SDimitry Andric void DWARFUnit::updateAddressDieMap(DWARFDie Die) { 7330b57cec5SDimitry Andric if (Die.isSubroutineDIE()) { 7340b57cec5SDimitry Andric auto DIERangesOrError = Die.getAddressRanges(); 7350b57cec5SDimitry Andric if (DIERangesOrError) { 7360b57cec5SDimitry Andric for (const auto &R : DIERangesOrError.get()) { 7370b57cec5SDimitry Andric // Ignore 0-sized ranges. 7380b57cec5SDimitry Andric if (R.LowPC == R.HighPC) 7390b57cec5SDimitry Andric continue; 7400b57cec5SDimitry Andric auto B = AddrDieMap.upper_bound(R.LowPC); 7410b57cec5SDimitry Andric if (B != AddrDieMap.begin() && R.LowPC < (--B)->second.first) { 7420b57cec5SDimitry Andric // The range is a sub-range of existing ranges, we need to split the 7430b57cec5SDimitry Andric // existing range. 7440b57cec5SDimitry Andric if (R.HighPC < B->second.first) 7450b57cec5SDimitry Andric AddrDieMap[R.HighPC] = B->second; 7460b57cec5SDimitry Andric if (R.LowPC > B->first) 7470b57cec5SDimitry Andric AddrDieMap[B->first].first = R.LowPC; 7480b57cec5SDimitry Andric } 7490b57cec5SDimitry Andric AddrDieMap[R.LowPC] = std::make_pair(R.HighPC, Die); 7500b57cec5SDimitry Andric } 7510b57cec5SDimitry Andric } else 7520b57cec5SDimitry Andric llvm::consumeError(DIERangesOrError.takeError()); 7530b57cec5SDimitry Andric } 7540b57cec5SDimitry Andric // Parent DIEs are added to the AddrDieMap prior to the Children DIEs to 7550b57cec5SDimitry Andric // simplify the logic to update AddrDieMap. The child's range will always 7560b57cec5SDimitry Andric // be equal or smaller than the parent's range. With this assumption, when 7570b57cec5SDimitry Andric // adding one range into the map, it will at most split a range into 3 7580b57cec5SDimitry Andric // sub-ranges. 7590b57cec5SDimitry Andric for (DWARFDie Child = Die.getFirstChild(); Child; Child = Child.getSibling()) 7600b57cec5SDimitry Andric updateAddressDieMap(Child); 7610b57cec5SDimitry Andric } 7620b57cec5SDimitry Andric 7630b57cec5SDimitry Andric DWARFDie DWARFUnit::getSubroutineForAddress(uint64_t Address) { 7640b57cec5SDimitry Andric extractDIEsIfNeeded(false); 7650b57cec5SDimitry Andric if (AddrDieMap.empty()) 7660b57cec5SDimitry Andric updateAddressDieMap(getUnitDIE()); 7670b57cec5SDimitry Andric auto R = AddrDieMap.upper_bound(Address); 7680b57cec5SDimitry Andric if (R == AddrDieMap.begin()) 7690b57cec5SDimitry Andric return DWARFDie(); 7700b57cec5SDimitry Andric // upper_bound's previous item contains Address. 7710b57cec5SDimitry Andric --R; 7720b57cec5SDimitry Andric if (Address >= R->second.first) 7730b57cec5SDimitry Andric return DWARFDie(); 7740b57cec5SDimitry Andric return R->second.second; 7750b57cec5SDimitry Andric } 7760b57cec5SDimitry Andric 77781ad6265SDimitry Andric void DWARFUnit::updateVariableDieMap(DWARFDie Die) { 77881ad6265SDimitry Andric for (DWARFDie Child : Die) { 77981ad6265SDimitry Andric if (isType(Child.getTag())) 78081ad6265SDimitry Andric continue; 78181ad6265SDimitry Andric updateVariableDieMap(Child); 78281ad6265SDimitry Andric } 78381ad6265SDimitry Andric 78481ad6265SDimitry Andric if (Die.getTag() != DW_TAG_variable) 78581ad6265SDimitry Andric return; 78681ad6265SDimitry Andric 78781ad6265SDimitry Andric Expected<DWARFLocationExpressionsVector> Locations = 78881ad6265SDimitry Andric Die.getLocations(DW_AT_location); 78981ad6265SDimitry Andric if (!Locations) { 79081ad6265SDimitry Andric // Missing DW_AT_location is fine here. 79181ad6265SDimitry Andric consumeError(Locations.takeError()); 79281ad6265SDimitry Andric return; 79381ad6265SDimitry Andric } 79481ad6265SDimitry Andric 79581ad6265SDimitry Andric uint64_t Address = UINT64_MAX; 79681ad6265SDimitry Andric 79781ad6265SDimitry Andric for (const DWARFLocationExpression &Location : *Locations) { 79881ad6265SDimitry Andric uint8_t AddressSize = getAddressByteSize(); 7995f757f3fSDimitry Andric DataExtractor Data(Location.Expr, isLittleEndian(), AddressSize); 80081ad6265SDimitry Andric DWARFExpression Expr(Data, AddressSize); 80181ad6265SDimitry Andric auto It = Expr.begin(); 80281ad6265SDimitry Andric if (It == Expr.end()) 80381ad6265SDimitry Andric continue; 80481ad6265SDimitry Andric 80581ad6265SDimitry Andric // Match exactly the main sequence used to describe global variables: 80681ad6265SDimitry Andric // `DW_OP_addr[x] [+ DW_OP_plus_uconst]`. Currently, this is the sequence 80781ad6265SDimitry Andric // that LLVM produces for DILocalVariables and DIGlobalVariables. If, in 80881ad6265SDimitry Andric // future, the DWARF producer (`DwarfCompileUnit::addLocationAttribute()` is 80981ad6265SDimitry Andric // a good starting point) is extended to use further expressions, this code 81081ad6265SDimitry Andric // needs to be updated. 81181ad6265SDimitry Andric uint64_t LocationAddr; 81281ad6265SDimitry Andric if (It->getCode() == dwarf::DW_OP_addr) { 81381ad6265SDimitry Andric LocationAddr = It->getRawOperand(0); 81481ad6265SDimitry Andric } else if (It->getCode() == dwarf::DW_OP_addrx) { 81581ad6265SDimitry Andric uint64_t DebugAddrOffset = It->getRawOperand(0); 81681ad6265SDimitry Andric if (auto Pointer = getAddrOffsetSectionItem(DebugAddrOffset)) { 81781ad6265SDimitry Andric LocationAddr = Pointer->Address; 81881ad6265SDimitry Andric } 81981ad6265SDimitry Andric } else { 82081ad6265SDimitry Andric continue; 82181ad6265SDimitry Andric } 82281ad6265SDimitry Andric 82381ad6265SDimitry Andric // Read the optional 2nd operand, a DW_OP_plus_uconst. 82481ad6265SDimitry Andric if (++It != Expr.end()) { 82581ad6265SDimitry Andric if (It->getCode() != dwarf::DW_OP_plus_uconst) 82681ad6265SDimitry Andric continue; 82781ad6265SDimitry Andric 82881ad6265SDimitry Andric LocationAddr += It->getRawOperand(0); 82981ad6265SDimitry Andric 83081ad6265SDimitry Andric // Probe for a 3rd operand, if it exists, bail. 83181ad6265SDimitry Andric if (++It != Expr.end()) 83281ad6265SDimitry Andric continue; 83381ad6265SDimitry Andric } 83481ad6265SDimitry Andric 83581ad6265SDimitry Andric Address = LocationAddr; 83681ad6265SDimitry Andric break; 83781ad6265SDimitry Andric } 83881ad6265SDimitry Andric 83981ad6265SDimitry Andric // Get the size of the global variable. If all else fails (i.e. the global has 84081ad6265SDimitry Andric // no type), then we use a size of one to still allow symbolization of the 84181ad6265SDimitry Andric // exact address. 84281ad6265SDimitry Andric uint64_t GVSize = 1; 8435f757f3fSDimitry Andric if (Die.getAttributeValueAsReferencedDie(DW_AT_type)) 844bdd1243dSDimitry Andric if (std::optional<uint64_t> Size = Die.getTypeSize(getAddressByteSize())) 84581ad6265SDimitry Andric GVSize = *Size; 84681ad6265SDimitry Andric 84781ad6265SDimitry Andric if (Address != UINT64_MAX) 84881ad6265SDimitry Andric VariableDieMap[Address] = {Address + GVSize, Die}; 84981ad6265SDimitry Andric } 85081ad6265SDimitry Andric 85181ad6265SDimitry Andric DWARFDie DWARFUnit::getVariableForAddress(uint64_t Address) { 85281ad6265SDimitry Andric extractDIEsIfNeeded(false); 85381ad6265SDimitry Andric 85481ad6265SDimitry Andric auto RootDie = getUnitDIE(); 85581ad6265SDimitry Andric 85681ad6265SDimitry Andric auto RootLookup = RootsParsedForVariables.insert(RootDie.getOffset()); 85781ad6265SDimitry Andric if (RootLookup.second) 85881ad6265SDimitry Andric updateVariableDieMap(RootDie); 85981ad6265SDimitry Andric 86081ad6265SDimitry Andric auto R = VariableDieMap.upper_bound(Address); 86181ad6265SDimitry Andric if (R == VariableDieMap.begin()) 86281ad6265SDimitry Andric return DWARFDie(); 86381ad6265SDimitry Andric 86481ad6265SDimitry Andric // upper_bound's previous item contains Address. 86581ad6265SDimitry Andric --R; 86681ad6265SDimitry Andric if (Address >= R->second.first) 86781ad6265SDimitry Andric return DWARFDie(); 86881ad6265SDimitry Andric return R->second.second; 86981ad6265SDimitry Andric } 87081ad6265SDimitry Andric 8710b57cec5SDimitry Andric void 8720b57cec5SDimitry Andric DWARFUnit::getInlinedChainForAddress(uint64_t Address, 8730b57cec5SDimitry Andric SmallVectorImpl<DWARFDie> &InlinedChain) { 8740b57cec5SDimitry Andric assert(InlinedChain.empty()); 8750b57cec5SDimitry Andric // Try to look for subprogram DIEs in the DWO file. 8760b57cec5SDimitry Andric parseDWO(); 8770b57cec5SDimitry Andric // First, find the subroutine that contains the given address (the leaf 8780b57cec5SDimitry Andric // of inlined chain). 8790b57cec5SDimitry Andric DWARFDie SubroutineDIE = 8800b57cec5SDimitry Andric (DWO ? *DWO : *this).getSubroutineForAddress(Address); 8810b57cec5SDimitry Andric 882fe6060f1SDimitry Andric while (SubroutineDIE) { 883fe6060f1SDimitry Andric if (SubroutineDIE.isSubprogramDIE()) { 884fe6060f1SDimitry Andric InlinedChain.push_back(SubroutineDIE); 8850b57cec5SDimitry Andric return; 886fe6060f1SDimitry Andric } 8870b57cec5SDimitry Andric if (SubroutineDIE.getTag() == DW_TAG_inlined_subroutine) 8880b57cec5SDimitry Andric InlinedChain.push_back(SubroutineDIE); 8890b57cec5SDimitry Andric SubroutineDIE = SubroutineDIE.getParent(); 8900b57cec5SDimitry Andric } 8910b57cec5SDimitry Andric } 8920b57cec5SDimitry Andric 8930b57cec5SDimitry Andric const DWARFUnitIndex &llvm::getDWARFUnitIndex(DWARFContext &Context, 8940b57cec5SDimitry Andric DWARFSectionKind Kind) { 8950b57cec5SDimitry Andric if (Kind == DW_SECT_INFO) 8960b57cec5SDimitry Andric return Context.getCUIndex(); 8975ffd83dbSDimitry Andric assert(Kind == DW_SECT_EXT_TYPES); 8980b57cec5SDimitry Andric return Context.getTUIndex(); 8990b57cec5SDimitry Andric } 9000b57cec5SDimitry Andric 9010b57cec5SDimitry Andric DWARFDie DWARFUnit::getParent(const DWARFDebugInfoEntry *Die) { 902bdd1243dSDimitry Andric if (const DWARFDebugInfoEntry *Entry = getParentEntry(Die)) 903bdd1243dSDimitry Andric return DWARFDie(this, Entry); 904349cc55cSDimitry Andric 905bdd1243dSDimitry Andric return DWARFDie(); 9060b57cec5SDimitry Andric } 907349cc55cSDimitry Andric 908bdd1243dSDimitry Andric const DWARFDebugInfoEntry * 909bdd1243dSDimitry Andric DWARFUnit::getParentEntry(const DWARFDebugInfoEntry *Die) const { 910bdd1243dSDimitry Andric if (!Die) 911bdd1243dSDimitry Andric return nullptr; 912bdd1243dSDimitry Andric assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size()); 913bdd1243dSDimitry Andric 914bdd1243dSDimitry Andric if (std::optional<uint32_t> ParentIdx = Die->getParentIdx()) { 915bdd1243dSDimitry Andric assert(*ParentIdx < DieArray.size() && 916bdd1243dSDimitry Andric "ParentIdx is out of DieArray boundaries"); 917bdd1243dSDimitry Andric return getDebugInfoEntry(*ParentIdx); 918bdd1243dSDimitry Andric } 919bdd1243dSDimitry Andric 920bdd1243dSDimitry Andric return nullptr; 9210b57cec5SDimitry Andric } 9220b57cec5SDimitry Andric 9230b57cec5SDimitry Andric DWARFDie DWARFUnit::getSibling(const DWARFDebugInfoEntry *Die) { 924bdd1243dSDimitry Andric if (const DWARFDebugInfoEntry *Sibling = getSiblingEntry(Die)) 925bdd1243dSDimitry Andric return DWARFDie(this, Sibling); 9260b57cec5SDimitry Andric 927bdd1243dSDimitry Andric return DWARFDie(); 9280b57cec5SDimitry Andric } 929349cc55cSDimitry Andric 930bdd1243dSDimitry Andric const DWARFDebugInfoEntry * 931bdd1243dSDimitry Andric DWARFUnit::getSiblingEntry(const DWARFDebugInfoEntry *Die) const { 932bdd1243dSDimitry Andric if (!Die) 933bdd1243dSDimitry Andric return nullptr; 934bdd1243dSDimitry Andric assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size()); 935bdd1243dSDimitry Andric 936bdd1243dSDimitry Andric if (std::optional<uint32_t> SiblingIdx = Die->getSiblingIdx()) { 937bdd1243dSDimitry Andric assert(*SiblingIdx < DieArray.size() && 938bdd1243dSDimitry Andric "SiblingIdx is out of DieArray boundaries"); 939bdd1243dSDimitry Andric return &DieArray[*SiblingIdx]; 940bdd1243dSDimitry Andric } 941bdd1243dSDimitry Andric 942bdd1243dSDimitry Andric return nullptr; 9430b57cec5SDimitry Andric } 9440b57cec5SDimitry Andric 9450b57cec5SDimitry Andric DWARFDie DWARFUnit::getPreviousSibling(const DWARFDebugInfoEntry *Die) { 946bdd1243dSDimitry Andric if (const DWARFDebugInfoEntry *Sibling = getPreviousSiblingEntry(Die)) 947bdd1243dSDimitry Andric return DWARFDie(this, Sibling); 948349cc55cSDimitry Andric 949bdd1243dSDimitry Andric return DWARFDie(); 950bdd1243dSDimitry Andric } 951bdd1243dSDimitry Andric 952bdd1243dSDimitry Andric const DWARFDebugInfoEntry * 953bdd1243dSDimitry Andric DWARFUnit::getPreviousSiblingEntry(const DWARFDebugInfoEntry *Die) const { 954bdd1243dSDimitry Andric if (!Die) 955bdd1243dSDimitry Andric return nullptr; 956bdd1243dSDimitry Andric assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size()); 957bdd1243dSDimitry Andric 958bdd1243dSDimitry Andric std::optional<uint32_t> ParentIdx = Die->getParentIdx(); 959349cc55cSDimitry Andric if (!ParentIdx) 960349cc55cSDimitry Andric // Die is a root die, there is no previous sibling. 961bdd1243dSDimitry Andric return nullptr; 9620b57cec5SDimitry Andric 963349cc55cSDimitry Andric assert(*ParentIdx < DieArray.size() && 964349cc55cSDimitry Andric "ParentIdx is out of DieArray boundaries"); 965349cc55cSDimitry Andric assert(getDIEIndex(Die) > 0 && "Die is a root die"); 966349cc55cSDimitry Andric 967349cc55cSDimitry Andric uint32_t PrevDieIdx = getDIEIndex(Die) - 1; 968349cc55cSDimitry Andric if (PrevDieIdx == *ParentIdx) 969349cc55cSDimitry Andric // Immediately previous node is parent, there is no previous sibling. 970bdd1243dSDimitry Andric return nullptr; 971349cc55cSDimitry Andric 972349cc55cSDimitry Andric while (DieArray[PrevDieIdx].getParentIdx() != *ParentIdx) { 973349cc55cSDimitry Andric PrevDieIdx = *DieArray[PrevDieIdx].getParentIdx(); 974349cc55cSDimitry Andric 975349cc55cSDimitry Andric assert(PrevDieIdx < DieArray.size() && 976349cc55cSDimitry Andric "PrevDieIdx is out of DieArray boundaries"); 977349cc55cSDimitry Andric assert(PrevDieIdx >= *ParentIdx && 978349cc55cSDimitry Andric "PrevDieIdx is not a child of parent of Die"); 9790b57cec5SDimitry Andric } 980349cc55cSDimitry Andric 981bdd1243dSDimitry Andric return &DieArray[PrevDieIdx]; 9820b57cec5SDimitry Andric } 9830b57cec5SDimitry Andric 9840b57cec5SDimitry Andric DWARFDie DWARFUnit::getFirstChild(const DWARFDebugInfoEntry *Die) { 985bdd1243dSDimitry Andric if (const DWARFDebugInfoEntry *Child = getFirstChildEntry(Die)) 986bdd1243dSDimitry Andric return DWARFDie(this, Child); 987bdd1243dSDimitry Andric 9880b57cec5SDimitry Andric return DWARFDie(); 989bdd1243dSDimitry Andric } 990bdd1243dSDimitry Andric 991bdd1243dSDimitry Andric const DWARFDebugInfoEntry * 992bdd1243dSDimitry Andric DWARFUnit::getFirstChildEntry(const DWARFDebugInfoEntry *Die) const { 993bdd1243dSDimitry Andric if (!Die) 994bdd1243dSDimitry Andric return nullptr; 995bdd1243dSDimitry Andric assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size()); 996bdd1243dSDimitry Andric 997bdd1243dSDimitry Andric if (!Die->hasChildren()) 998bdd1243dSDimitry Andric return nullptr; 9990b57cec5SDimitry Andric 1000349cc55cSDimitry Andric // TODO: Instead of checking here for invalid die we might reject 1001349cc55cSDimitry Andric // invalid dies at parsing stage(DWARFUnit::extractDIEsToVector). 10020b57cec5SDimitry Andric // We do not want access out of bounds when parsing corrupted debug data. 10030b57cec5SDimitry Andric size_t I = getDIEIndex(Die) + 1; 10040b57cec5SDimitry Andric if (I >= DieArray.size()) 1005bdd1243dSDimitry Andric return nullptr; 1006bdd1243dSDimitry Andric return &DieArray[I]; 10070b57cec5SDimitry Andric } 10080b57cec5SDimitry Andric 10090b57cec5SDimitry Andric DWARFDie DWARFUnit::getLastChild(const DWARFDebugInfoEntry *Die) { 1010bdd1243dSDimitry Andric if (const DWARFDebugInfoEntry *Child = getLastChildEntry(Die)) 1011bdd1243dSDimitry Andric return DWARFDie(this, Child); 10120b57cec5SDimitry Andric 1013bdd1243dSDimitry Andric return DWARFDie(); 1014bdd1243dSDimitry Andric } 1015bdd1243dSDimitry Andric 1016bdd1243dSDimitry Andric const DWARFDebugInfoEntry * 1017bdd1243dSDimitry Andric DWARFUnit::getLastChildEntry(const DWARFDebugInfoEntry *Die) const { 1018bdd1243dSDimitry Andric if (!Die) 1019bdd1243dSDimitry Andric return nullptr; 1020bdd1243dSDimitry Andric assert(Die >= DieArray.data() && Die < DieArray.data() + DieArray.size()); 1021bdd1243dSDimitry Andric 1022bdd1243dSDimitry Andric if (!Die->hasChildren()) 1023bdd1243dSDimitry Andric return nullptr; 1024bdd1243dSDimitry Andric 1025bdd1243dSDimitry Andric if (std::optional<uint32_t> SiblingIdx = Die->getSiblingIdx()) { 1026349cc55cSDimitry Andric assert(*SiblingIdx < DieArray.size() && 1027349cc55cSDimitry Andric "SiblingIdx is out of DieArray boundaries"); 1028349cc55cSDimitry Andric assert(DieArray[*SiblingIdx - 1].getTag() == dwarf::DW_TAG_null && 1029349cc55cSDimitry Andric "Bad end of children marker"); 1030bdd1243dSDimitry Andric return &DieArray[*SiblingIdx - 1]; 10310b57cec5SDimitry Andric } 1032349cc55cSDimitry Andric 1033349cc55cSDimitry Andric // If SiblingIdx is set for non-root dies we could be sure that DWARF is 1034349cc55cSDimitry Andric // correct and "end of children marker" must be found. For root die we do not 1035349cc55cSDimitry Andric // have such a guarantee(parsing root die might be stopped if "end of children 1036349cc55cSDimitry Andric // marker" is missing, SiblingIdx is always zero for root die). That is why we 1037349cc55cSDimitry Andric // do not use assertion for checking for "end of children marker" for root 1038349cc55cSDimitry Andric // die. 1039349cc55cSDimitry Andric 1040349cc55cSDimitry Andric // TODO: Instead of checking here for invalid die we might reject 1041349cc55cSDimitry Andric // invalid dies at parsing stage(DWARFUnit::extractDIEsToVector). 1042349cc55cSDimitry Andric if (getDIEIndex(Die) == 0 && DieArray.size() > 1 && 1043349cc55cSDimitry Andric DieArray.back().getTag() == dwarf::DW_TAG_null) { 1044349cc55cSDimitry Andric // For the unit die we might take last item from DieArray. 1045bdd1243dSDimitry Andric assert(getDIEIndex(Die) == 1046bdd1243dSDimitry Andric getDIEIndex(const_cast<DWARFUnit *>(this)->getUnitDIE()) && 1047bdd1243dSDimitry Andric "Bad unit die"); 1048bdd1243dSDimitry Andric return &DieArray.back(); 1049349cc55cSDimitry Andric } 1050349cc55cSDimitry Andric 1051bdd1243dSDimitry Andric return nullptr; 10520b57cec5SDimitry Andric } 10530b57cec5SDimitry Andric 10540b57cec5SDimitry Andric const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const { 105506c3fb27SDimitry Andric if (!Abbrevs) { 105606c3fb27SDimitry Andric Expected<const DWARFAbbreviationDeclarationSet *> AbbrevsOrError = 105706c3fb27SDimitry Andric Abbrev->getAbbreviationDeclarationSet(getAbbreviationsOffset()); 105806c3fb27SDimitry Andric if (!AbbrevsOrError) { 105906c3fb27SDimitry Andric // FIXME: We should propagate this error upwards. 106006c3fb27SDimitry Andric consumeError(AbbrevsOrError.takeError()); 106106c3fb27SDimitry Andric return nullptr; 106206c3fb27SDimitry Andric } 106306c3fb27SDimitry Andric Abbrevs = *AbbrevsOrError; 106406c3fb27SDimitry Andric } 10650b57cec5SDimitry Andric return Abbrevs; 10660b57cec5SDimitry Andric } 10670b57cec5SDimitry Andric 1068bdd1243dSDimitry Andric std::optional<object::SectionedAddress> DWARFUnit::getBaseAddress() { 10690b57cec5SDimitry Andric if (BaseAddr) 10700b57cec5SDimitry Andric return BaseAddr; 10710b57cec5SDimitry Andric 107206c3fb27SDimitry Andric DWARFDie UnitDie = (SU ? SU : this)->getUnitDIE(); 1073bdd1243dSDimitry Andric std::optional<DWARFFormValue> PC = 1074bdd1243dSDimitry Andric UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc}); 10750b57cec5SDimitry Andric BaseAddr = toSectionedAddress(PC); 10760b57cec5SDimitry Andric return BaseAddr; 10770b57cec5SDimitry Andric } 10780b57cec5SDimitry Andric 10790b57cec5SDimitry Andric Expected<StrOffsetsContributionDescriptor> 10800b57cec5SDimitry Andric StrOffsetsContributionDescriptor::validateContributionSize( 10810b57cec5SDimitry Andric DWARFDataExtractor &DA) { 10820b57cec5SDimitry Andric uint8_t EntrySize = getDwarfOffsetByteSize(); 10830b57cec5SDimitry Andric // In order to ensure that we don't read a partial record at the end of 10840b57cec5SDimitry Andric // the section we validate for a multiple of the entry size. 10850b57cec5SDimitry Andric uint64_t ValidationSize = alignTo(Size, EntrySize); 10860b57cec5SDimitry Andric // Guard against overflow. 10870b57cec5SDimitry Andric if (ValidationSize >= Size) 10880b57cec5SDimitry Andric if (DA.isValidOffsetForDataOfSize((uint32_t)Base, ValidationSize)) 10890b57cec5SDimitry Andric return *this; 10900b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "length exceeds section size"); 10910b57cec5SDimitry Andric } 10920b57cec5SDimitry Andric 10930b57cec5SDimitry Andric // Look for a DWARF64-formatted contribution to the string offsets table 10940b57cec5SDimitry Andric // starting at a given offset and record it in a descriptor. 10950b57cec5SDimitry Andric static Expected<StrOffsetsContributionDescriptor> 10968bcb0991SDimitry Andric parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint64_t Offset) { 10970b57cec5SDimitry Andric if (!DA.isValidOffsetForDataOfSize(Offset, 16)) 10980b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "section offset exceeds section size"); 10990b57cec5SDimitry Andric 11008bcb0991SDimitry Andric if (DA.getU32(&Offset) != dwarf::DW_LENGTH_DWARF64) 11010b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "32 bit contribution referenced from a 64 bit unit"); 11020b57cec5SDimitry Andric 11030b57cec5SDimitry Andric uint64_t Size = DA.getU64(&Offset); 11040b57cec5SDimitry Andric uint8_t Version = DA.getU16(&Offset); 11050b57cec5SDimitry Andric (void)DA.getU16(&Offset); // padding 11060b57cec5SDimitry Andric // The encoded length includes the 2-byte version field and the 2-byte 11070b57cec5SDimitry Andric // padding, so we need to subtract them out when we populate the descriptor. 11080b57cec5SDimitry Andric return StrOffsetsContributionDescriptor(Offset, Size - 4, Version, DWARF64); 11090b57cec5SDimitry Andric } 11100b57cec5SDimitry Andric 11110b57cec5SDimitry Andric // Look for a DWARF32-formatted contribution to the string offsets table 11120b57cec5SDimitry Andric // starting at a given offset and record it in a descriptor. 11130b57cec5SDimitry Andric static Expected<StrOffsetsContributionDescriptor> 11148bcb0991SDimitry Andric parseDWARF32StringOffsetsTableHeader(DWARFDataExtractor &DA, uint64_t Offset) { 11150b57cec5SDimitry Andric if (!DA.isValidOffsetForDataOfSize(Offset, 8)) 11160b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "section offset exceeds section size"); 11170b57cec5SDimitry Andric 11180b57cec5SDimitry Andric uint32_t ContributionSize = DA.getU32(&Offset); 11198bcb0991SDimitry Andric if (ContributionSize >= dwarf::DW_LENGTH_lo_reserved) 11200b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "invalid length"); 11210b57cec5SDimitry Andric 11220b57cec5SDimitry Andric uint8_t Version = DA.getU16(&Offset); 11230b57cec5SDimitry Andric (void)DA.getU16(&Offset); // padding 11240b57cec5SDimitry Andric // The encoded length includes the 2-byte version field and the 2-byte 11250b57cec5SDimitry Andric // padding, so we need to subtract them out when we populate the descriptor. 11260b57cec5SDimitry Andric return StrOffsetsContributionDescriptor(Offset, ContributionSize - 4, Version, 11270b57cec5SDimitry Andric DWARF32); 11280b57cec5SDimitry Andric } 11290b57cec5SDimitry Andric 11300b57cec5SDimitry Andric static Expected<StrOffsetsContributionDescriptor> 11310b57cec5SDimitry Andric parseDWARFStringOffsetsTableHeader(DWARFDataExtractor &DA, 11320b57cec5SDimitry Andric llvm::dwarf::DwarfFormat Format, 11330b57cec5SDimitry Andric uint64_t Offset) { 11340b57cec5SDimitry Andric StrOffsetsContributionDescriptor Desc; 11350b57cec5SDimitry Andric switch (Format) { 11360b57cec5SDimitry Andric case dwarf::DwarfFormat::DWARF64: { 11370b57cec5SDimitry Andric if (Offset < 16) 11380b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "insufficient space for 64 bit header prefix"); 11398bcb0991SDimitry Andric auto DescOrError = parseDWARF64StringOffsetsTableHeader(DA, Offset - 16); 11400b57cec5SDimitry Andric if (!DescOrError) 11410b57cec5SDimitry Andric return DescOrError.takeError(); 11420b57cec5SDimitry Andric Desc = *DescOrError; 11430b57cec5SDimitry Andric break; 11440b57cec5SDimitry Andric } 11450b57cec5SDimitry Andric case dwarf::DwarfFormat::DWARF32: { 11460b57cec5SDimitry Andric if (Offset < 8) 11470b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "insufficient space for 32 bit header prefix"); 11488bcb0991SDimitry Andric auto DescOrError = parseDWARF32StringOffsetsTableHeader(DA, Offset - 8); 11490b57cec5SDimitry Andric if (!DescOrError) 11500b57cec5SDimitry Andric return DescOrError.takeError(); 11510b57cec5SDimitry Andric Desc = *DescOrError; 11520b57cec5SDimitry Andric break; 11530b57cec5SDimitry Andric } 11540b57cec5SDimitry Andric } 11550b57cec5SDimitry Andric return Desc.validateContributionSize(DA); 11560b57cec5SDimitry Andric } 11570b57cec5SDimitry Andric 1158bdd1243dSDimitry Andric Expected<std::optional<StrOffsetsContributionDescriptor>> 11590b57cec5SDimitry Andric DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA) { 11605ffd83dbSDimitry Andric assert(!IsDWO); 11610b57cec5SDimitry Andric auto OptOffset = toSectionOffset(getUnitDIE().find(DW_AT_str_offsets_base)); 11620b57cec5SDimitry Andric if (!OptOffset) 1163bdd1243dSDimitry Andric return std::nullopt; 11645ffd83dbSDimitry Andric auto DescOrError = 11655ffd83dbSDimitry Andric parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), *OptOffset); 11660b57cec5SDimitry Andric if (!DescOrError) 11670b57cec5SDimitry Andric return DescOrError.takeError(); 11680b57cec5SDimitry Andric return *DescOrError; 11690b57cec5SDimitry Andric } 11700b57cec5SDimitry Andric 1171bdd1243dSDimitry Andric Expected<std::optional<StrOffsetsContributionDescriptor>> 11720b57cec5SDimitry Andric DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor &DA) { 11735ffd83dbSDimitry Andric assert(IsDWO); 11740b57cec5SDimitry Andric uint64_t Offset = 0; 11750b57cec5SDimitry Andric auto IndexEntry = Header.getIndexEntry(); 11760b57cec5SDimitry Andric const auto *C = 11775ffd83dbSDimitry Andric IndexEntry ? IndexEntry->getContribution(DW_SECT_STR_OFFSETS) : nullptr; 11780b57cec5SDimitry Andric if (C) 1179bdd1243dSDimitry Andric Offset = C->getOffset(); 11800b57cec5SDimitry Andric if (getVersion() >= 5) { 11810b57cec5SDimitry Andric if (DA.getData().data() == nullptr) 1182bdd1243dSDimitry Andric return std::nullopt; 11830b57cec5SDimitry Andric Offset += Header.getFormat() == dwarf::DwarfFormat::DWARF32 ? 8 : 16; 11840b57cec5SDimitry Andric // Look for a valid contribution at the given offset. 11850b57cec5SDimitry Andric auto DescOrError = parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), Offset); 11860b57cec5SDimitry Andric if (!DescOrError) 11870b57cec5SDimitry Andric return DescOrError.takeError(); 11880b57cec5SDimitry Andric return *DescOrError; 11890b57cec5SDimitry Andric } 11900b57cec5SDimitry Andric // Prior to DWARF v5, we derive the contribution size from the 11910b57cec5SDimitry Andric // index table (in a package file). In a .dwo file it is simply 11920b57cec5SDimitry Andric // the length of the string offsets section. 1193e8d8bef9SDimitry Andric StrOffsetsContributionDescriptor Desc; 11940b57cec5SDimitry Andric if (C) 1195bdd1243dSDimitry Andric Desc = StrOffsetsContributionDescriptor(C->getOffset(), C->getLength(), 4, 1196e8d8bef9SDimitry Andric Header.getFormat()); 1197e8d8bef9SDimitry Andric else if (!IndexEntry && !StringOffsetSection.Data.empty()) 1198e8d8bef9SDimitry Andric Desc = StrOffsetsContributionDescriptor(0, StringOffsetSection.Data.size(), 1199e8d8bef9SDimitry Andric 4, Header.getFormat()); 1200e8d8bef9SDimitry Andric else 1201bdd1243dSDimitry Andric return std::nullopt; 1202e8d8bef9SDimitry Andric auto DescOrError = Desc.validateContributionSize(DA); 1203e8d8bef9SDimitry Andric if (!DescOrError) 1204e8d8bef9SDimitry Andric return DescOrError.takeError(); 1205e8d8bef9SDimitry Andric return *DescOrError; 1206e8d8bef9SDimitry Andric } 1207e8d8bef9SDimitry Andric 1208bdd1243dSDimitry Andric std::optional<uint64_t> DWARFUnit::getRnglistOffset(uint32_t Index) { 1209bdd1243dSDimitry Andric DataExtractor RangesData(RangeSection->Data, IsLittleEndian, 1210e8d8bef9SDimitry Andric getAddressByteSize()); 1211e8d8bef9SDimitry Andric DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection, 1212bdd1243dSDimitry Andric IsLittleEndian, 0); 1213bdd1243dSDimitry Andric if (std::optional<uint64_t> Off = llvm::DWARFListTableHeader::getOffsetEntry( 1214e8d8bef9SDimitry Andric RangesData, RangeSectionBase, getFormat(), Index)) 1215e8d8bef9SDimitry Andric return *Off + RangeSectionBase; 1216bdd1243dSDimitry Andric return std::nullopt; 1217e8d8bef9SDimitry Andric } 1218e8d8bef9SDimitry Andric 1219bdd1243dSDimitry Andric std::optional<uint64_t> DWARFUnit::getLoclistOffset(uint32_t Index) { 1220bdd1243dSDimitry Andric if (std::optional<uint64_t> Off = llvm::DWARFListTableHeader::getOffsetEntry( 1221e8d8bef9SDimitry Andric LocTable->getData(), LocSectionBase, getFormat(), Index)) 1222e8d8bef9SDimitry Andric return *Off + LocSectionBase; 1223bdd1243dSDimitry Andric return std::nullopt; 12240b57cec5SDimitry Andric } 1225