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" 120b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" 130b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" 140b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h" 150b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" 160b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" 170b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" 180b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDie.h" 190b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 200b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" 210b57cec5SDimitry Andric #include "llvm/Support/DataExtractor.h" 220b57cec5SDimitry Andric #include "llvm/Support/Errc.h" 230b57cec5SDimitry Andric #include "llvm/Support/Path.h" 240b57cec5SDimitry Andric #include <algorithm> 250b57cec5SDimitry Andric #include <cassert> 260b57cec5SDimitry Andric #include <cstddef> 270b57cec5SDimitry Andric #include <cstdint> 280b57cec5SDimitry Andric #include <cstdio> 290b57cec5SDimitry Andric #include <utility> 300b57cec5SDimitry Andric #include <vector> 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric using namespace llvm; 330b57cec5SDimitry Andric using namespace dwarf; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric void DWARFUnitVector::addUnitsForSection(DWARFContext &C, 360b57cec5SDimitry Andric const DWARFSection &Section, 370b57cec5SDimitry Andric DWARFSectionKind SectionKind) { 380b57cec5SDimitry Andric const DWARFObject &D = C.getDWARFObj(); 398bcb0991SDimitry Andric addUnitsImpl(C, D, Section, C.getDebugAbbrev(), &D.getRangesSection(), 408bcb0991SDimitry Andric &D.getLocSection(), D.getStrSection(), 418bcb0991SDimitry Andric D.getStrOffsetsSection(), &D.getAddrSection(), 420b57cec5SDimitry Andric D.getLineSection(), D.isLittleEndian(), false, false, 430b57cec5SDimitry Andric SectionKind); 440b57cec5SDimitry Andric } 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric void DWARFUnitVector::addUnitsForDWOSection(DWARFContext &C, 470b57cec5SDimitry Andric const DWARFSection &DWOSection, 480b57cec5SDimitry Andric DWARFSectionKind SectionKind, 490b57cec5SDimitry Andric bool Lazy) { 500b57cec5SDimitry Andric const DWARFObject &D = C.getDWARFObj(); 518bcb0991SDimitry Andric addUnitsImpl(C, D, DWOSection, C.getDebugAbbrevDWO(), &D.getRangesDWOSection(), 528bcb0991SDimitry Andric &D.getLocDWOSection(), D.getStrDWOSection(), 538bcb0991SDimitry Andric D.getStrOffsetsDWOSection(), &D.getAddrSection(), 540b57cec5SDimitry Andric D.getLineDWOSection(), C.isLittleEndian(), true, Lazy, 550b57cec5SDimitry Andric SectionKind); 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric void DWARFUnitVector::addUnitsImpl( 590b57cec5SDimitry Andric DWARFContext &Context, const DWARFObject &Obj, const DWARFSection &Section, 600b57cec5SDimitry Andric const DWARFDebugAbbrev *DA, const DWARFSection *RS, 610b57cec5SDimitry Andric const DWARFSection *LocSection, StringRef SS, const DWARFSection &SOS, 620b57cec5SDimitry Andric const DWARFSection *AOS, const DWARFSection &LS, bool LE, bool IsDWO, 630b57cec5SDimitry Andric bool Lazy, DWARFSectionKind SectionKind) { 640b57cec5SDimitry Andric DWARFDataExtractor Data(Obj, Section, LE, 0); 650b57cec5SDimitry Andric // Lazy initialization of Parser, now that we have all section info. 660b57cec5SDimitry Andric if (!Parser) { 670b57cec5SDimitry Andric Parser = [=, &Context, &Obj, &Section, &SOS, 688bcb0991SDimitry Andric &LS](uint64_t Offset, DWARFSectionKind SectionKind, 690b57cec5SDimitry Andric const DWARFSection *CurSection, 700b57cec5SDimitry Andric const DWARFUnitIndex::Entry *IndexEntry) 710b57cec5SDimitry Andric -> std::unique_ptr<DWARFUnit> { 720b57cec5SDimitry Andric const DWARFSection &InfoSection = CurSection ? *CurSection : Section; 730b57cec5SDimitry Andric DWARFDataExtractor Data(Obj, InfoSection, LE, 0); 740b57cec5SDimitry Andric if (!Data.isValidOffset(Offset)) 750b57cec5SDimitry Andric return nullptr; 760b57cec5SDimitry Andric DWARFUnitHeader Header; 775ffd83dbSDimitry Andric if (!Header.extract(Context, Data, &Offset, SectionKind)) 785ffd83dbSDimitry Andric return nullptr; 795ffd83dbSDimitry Andric if (!IndexEntry && IsDWO) { 805ffd83dbSDimitry Andric const DWARFUnitIndex &Index = getDWARFUnitIndex( 815ffd83dbSDimitry Andric Context, Header.isTypeUnit() ? DW_SECT_EXT_TYPES : DW_SECT_INFO); 825ffd83dbSDimitry Andric IndexEntry = Index.getFromOffset(Header.getOffset()); 835ffd83dbSDimitry Andric } 845ffd83dbSDimitry Andric if (IndexEntry && !Header.applyIndexEntry(IndexEntry)) 850b57cec5SDimitry Andric return nullptr; 860b57cec5SDimitry Andric std::unique_ptr<DWARFUnit> U; 870b57cec5SDimitry Andric if (Header.isTypeUnit()) 888bcb0991SDimitry Andric U = std::make_unique<DWARFTypeUnit>(Context, InfoSection, Header, DA, 890b57cec5SDimitry Andric RS, LocSection, SS, SOS, AOS, LS, 900b57cec5SDimitry Andric LE, IsDWO, *this); 910b57cec5SDimitry Andric else 928bcb0991SDimitry Andric U = std::make_unique<DWARFCompileUnit>(Context, InfoSection, Header, 930b57cec5SDimitry Andric DA, RS, LocSection, SS, SOS, 940b57cec5SDimitry Andric AOS, LS, LE, IsDWO, *this); 950b57cec5SDimitry Andric return U; 960b57cec5SDimitry Andric }; 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric if (Lazy) 990b57cec5SDimitry Andric return; 1000b57cec5SDimitry Andric // Find a reasonable insertion point within the vector. We skip over 1010b57cec5SDimitry Andric // (a) units from a different section, (b) units from the same section 1020b57cec5SDimitry Andric // but with lower offset-within-section. This keeps units in order 1030b57cec5SDimitry Andric // within a section, although not necessarily within the object file, 1040b57cec5SDimitry Andric // even if we do lazy parsing. 1050b57cec5SDimitry Andric auto I = this->begin(); 1068bcb0991SDimitry Andric uint64_t Offset = 0; 1070b57cec5SDimitry Andric while (Data.isValidOffset(Offset)) { 1080b57cec5SDimitry Andric if (I != this->end() && 1090b57cec5SDimitry Andric (&(*I)->getInfoSection() != &Section || (*I)->getOffset() == Offset)) { 1100b57cec5SDimitry Andric ++I; 1110b57cec5SDimitry Andric continue; 1120b57cec5SDimitry Andric } 1130b57cec5SDimitry Andric auto U = Parser(Offset, SectionKind, &Section, nullptr); 1140b57cec5SDimitry Andric // If parsing failed, we're done with this section. 1150b57cec5SDimitry Andric if (!U) 1160b57cec5SDimitry Andric break; 1170b57cec5SDimitry Andric Offset = U->getNextUnitOffset(); 1180b57cec5SDimitry Andric I = std::next(this->insert(I, std::move(U))); 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric DWARFUnit *DWARFUnitVector::addUnit(std::unique_ptr<DWARFUnit> Unit) { 1230b57cec5SDimitry Andric auto I = std::upper_bound(begin(), end(), Unit, 1240b57cec5SDimitry Andric [](const std::unique_ptr<DWARFUnit> &LHS, 1250b57cec5SDimitry Andric const std::unique_ptr<DWARFUnit> &RHS) { 1260b57cec5SDimitry Andric return LHS->getOffset() < RHS->getOffset(); 1270b57cec5SDimitry Andric }); 1280b57cec5SDimitry Andric return this->insert(I, std::move(Unit))->get(); 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 1318bcb0991SDimitry Andric DWARFUnit *DWARFUnitVector::getUnitForOffset(uint64_t Offset) const { 1320b57cec5SDimitry Andric auto end = begin() + getNumInfoUnits(); 1330b57cec5SDimitry Andric auto *CU = 1340b57cec5SDimitry Andric std::upper_bound(begin(), end, Offset, 1358bcb0991SDimitry Andric [](uint64_t LHS, const std::unique_ptr<DWARFUnit> &RHS) { 1360b57cec5SDimitry Andric return LHS < RHS->getNextUnitOffset(); 1370b57cec5SDimitry Andric }); 1380b57cec5SDimitry Andric if (CU != end && (*CU)->getOffset() <= Offset) 1390b57cec5SDimitry Andric return CU->get(); 1400b57cec5SDimitry Andric return nullptr; 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric DWARFUnit * 1440b57cec5SDimitry Andric DWARFUnitVector::getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) { 1455ffd83dbSDimitry Andric const auto *CUOff = E.getContribution(DW_SECT_INFO); 1460b57cec5SDimitry Andric if (!CUOff) 1470b57cec5SDimitry Andric return nullptr; 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric auto Offset = CUOff->Offset; 1500b57cec5SDimitry Andric auto end = begin() + getNumInfoUnits(); 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric auto *CU = 1530b57cec5SDimitry Andric std::upper_bound(begin(), end, CUOff->Offset, 1548bcb0991SDimitry Andric [](uint64_t LHS, const std::unique_ptr<DWARFUnit> &RHS) { 1550b57cec5SDimitry Andric return LHS < RHS->getNextUnitOffset(); 1560b57cec5SDimitry Andric }); 1570b57cec5SDimitry Andric if (CU != end && (*CU)->getOffset() <= Offset) 1580b57cec5SDimitry Andric return CU->get(); 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric if (!Parser) 1610b57cec5SDimitry Andric return nullptr; 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andric auto U = Parser(Offset, DW_SECT_INFO, nullptr, &E); 1640b57cec5SDimitry Andric if (!U) 1650b57cec5SDimitry Andric U = nullptr; 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric auto *NewCU = U.get(); 1680b57cec5SDimitry Andric this->insert(CU, std::move(U)); 1690b57cec5SDimitry Andric ++NumInfoUnits; 1700b57cec5SDimitry Andric return NewCU; 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section, 1740b57cec5SDimitry Andric const DWARFUnitHeader &Header, const DWARFDebugAbbrev *DA, 1750b57cec5SDimitry Andric const DWARFSection *RS, const DWARFSection *LocSection, 1760b57cec5SDimitry Andric StringRef SS, const DWARFSection &SOS, 1770b57cec5SDimitry Andric const DWARFSection *AOS, const DWARFSection &LS, bool LE, 1780b57cec5SDimitry Andric bool IsDWO, const DWARFUnitVector &UnitVector) 1790b57cec5SDimitry Andric : Context(DC), InfoSection(Section), Header(Header), Abbrev(DA), 180480093f4SDimitry Andric RangeSection(RS), LineSection(LS), StringSection(SS), 181480093f4SDimitry Andric StringOffsetSection(SOS), AddrOffsetSection(AOS), isLittleEndian(LE), 182480093f4SDimitry Andric IsDWO(IsDWO), UnitVector(UnitVector) { 1830b57cec5SDimitry Andric clear(); 1840b57cec5SDimitry Andric if (IsDWO) { 185480093f4SDimitry Andric // If we are reading a package file, we need to adjust the location list 186480093f4SDimitry Andric // data based on the index entries. 1875ffd83dbSDimitry Andric StringRef Data = Header.getVersion() >= 5 1885ffd83dbSDimitry Andric ? Context.getDWARFObj().getLoclistsDWOSection().Data 1895ffd83dbSDimitry Andric : LocSection->Data; 1900b57cec5SDimitry Andric if (auto *IndexEntry = Header.getIndexEntry()) 1915ffd83dbSDimitry Andric if (const auto *C = IndexEntry->getContribution( 1925ffd83dbSDimitry Andric Header.getVersion() >= 5 ? DW_SECT_LOCLISTS : DW_SECT_EXT_LOC)) 193480093f4SDimitry Andric Data = Data.substr(C->Offset, C->Length); 194480093f4SDimitry Andric 1955ffd83dbSDimitry Andric DWARFDataExtractor DWARFData(Data, isLittleEndian, getAddressByteSize()); 196480093f4SDimitry Andric LocTable = 197480093f4SDimitry Andric std::make_unique<DWARFDebugLoclists>(DWARFData, Header.getVersion()); 198480093f4SDimitry Andric } else if (Header.getVersion() >= 5) { 199480093f4SDimitry Andric LocTable = std::make_unique<DWARFDebugLoclists>( 200480093f4SDimitry Andric DWARFDataExtractor(Context.getDWARFObj(), 201480093f4SDimitry Andric Context.getDWARFObj().getLoclistsSection(), 202480093f4SDimitry Andric isLittleEndian, getAddressByteSize()), 203480093f4SDimitry Andric Header.getVersion()); 204480093f4SDimitry Andric } else { 205480093f4SDimitry Andric LocTable = std::make_unique<DWARFDebugLoc>( 206480093f4SDimitry Andric DWARFDataExtractor(Context.getDWARFObj(), *LocSection, isLittleEndian, 207480093f4SDimitry Andric getAddressByteSize())); 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric } 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric DWARFUnit::~DWARFUnit() = default; 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric DWARFDataExtractor DWARFUnit::getDebugInfoExtractor() const { 2140b57cec5SDimitry Andric return DWARFDataExtractor(Context.getDWARFObj(), InfoSection, isLittleEndian, 2150b57cec5SDimitry Andric getAddressByteSize()); 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric Optional<object::SectionedAddress> 2190b57cec5SDimitry Andric DWARFUnit::getAddrOffsetSectionItem(uint32_t Index) const { 2200b57cec5SDimitry Andric if (IsDWO) { 2210b57cec5SDimitry Andric auto R = Context.info_section_units(); 2220b57cec5SDimitry Andric auto I = R.begin(); 2230b57cec5SDimitry Andric // Surprising if a DWO file has more than one skeleton unit in it - this 2240b57cec5SDimitry Andric // probably shouldn't be valid, but if a use case is found, here's where to 2250b57cec5SDimitry Andric // support it (probably have to linearly search for the matching skeleton CU 2260b57cec5SDimitry Andric // here) 2270b57cec5SDimitry Andric if (I != R.end() && std::next(I) == R.end()) 2280b57cec5SDimitry Andric return (*I)->getAddrOffsetSectionItem(Index); 2290b57cec5SDimitry Andric } 230480093f4SDimitry Andric if (!AddrOffsetSectionBase) 231480093f4SDimitry Andric return None; 232480093f4SDimitry Andric uint64_t Offset = *AddrOffsetSectionBase + Index * getAddressByteSize(); 2330b57cec5SDimitry Andric if (AddrOffsetSection->Data.size() < Offset + getAddressByteSize()) 2340b57cec5SDimitry Andric return None; 2350b57cec5SDimitry Andric DWARFDataExtractor DA(Context.getDWARFObj(), *AddrOffsetSection, 2360b57cec5SDimitry Andric isLittleEndian, getAddressByteSize()); 2370b57cec5SDimitry Andric uint64_t Section; 2380b57cec5SDimitry Andric uint64_t Address = DA.getRelocatedAddress(&Offset, &Section); 2390b57cec5SDimitry Andric return {{Address, Section}}; 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric Optional<uint64_t> DWARFUnit::getStringOffsetSectionItem(uint32_t Index) const { 2430b57cec5SDimitry Andric if (!StringOffsetsTableContribution) 2440b57cec5SDimitry Andric return None; 2450b57cec5SDimitry Andric unsigned ItemSize = getDwarfStringOffsetsByteSize(); 2468bcb0991SDimitry Andric uint64_t Offset = getStringOffsetsBase() + Index * ItemSize; 2470b57cec5SDimitry Andric if (StringOffsetSection.Data.size() < Offset + ItemSize) 2480b57cec5SDimitry Andric return None; 2490b57cec5SDimitry Andric DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, 2500b57cec5SDimitry Andric isLittleEndian, 0); 2510b57cec5SDimitry Andric return DA.getRelocatedValue(ItemSize, &Offset); 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric bool 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 287480093f4SDimitry Andric if (errorToBool(std::move(Err))) 288480093f4SDimitry Andric return false; 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric // Header fields all parsed, capture the size of this unit header. 2910b57cec5SDimitry Andric assert(*offset_ptr - Offset <= 255 && "unexpected header size"); 2920b57cec5SDimitry Andric Size = uint8_t(*offset_ptr - Offset); 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric // Type offset is unit-relative; should be after the header and before 2950b57cec5SDimitry Andric // the end of the current unit. 2960b57cec5SDimitry Andric bool TypeOffsetOK = 2970b57cec5SDimitry Andric !isTypeUnit() 2980b57cec5SDimitry Andric ? true 2998bcb0991SDimitry Andric : TypeOffset >= Size && 3008bcb0991SDimitry Andric TypeOffset < getLength() + getUnitLengthFieldByteSize(); 3010b57cec5SDimitry Andric bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); 3020b57cec5SDimitry Andric bool VersionOK = DWARFContext::isSupportedVersion(getVersion()); 3035ffd83dbSDimitry Andric bool AddrSizeOK = DWARFContext::isAddressSizeSupported(getAddressByteSize()); 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric if (!LengthOK || !VersionOK || !AddrSizeOK || !TypeOffsetOK) 3060b57cec5SDimitry Andric return false; 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric // Keep track of the highest DWARF version we encounter across all units. 3090b57cec5SDimitry Andric Context.setMaxVersionIfGreater(getVersion()); 3100b57cec5SDimitry Andric return true; 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric 3135ffd83dbSDimitry Andric bool DWARFUnitHeader::applyIndexEntry(const DWARFUnitIndex::Entry *Entry) { 3145ffd83dbSDimitry Andric assert(Entry); 3155ffd83dbSDimitry Andric assert(!IndexEntry); 3165ffd83dbSDimitry Andric IndexEntry = Entry; 3175ffd83dbSDimitry Andric if (AbbrOffset) 3185ffd83dbSDimitry Andric return false; 3195ffd83dbSDimitry Andric auto *UnitContrib = IndexEntry->getContribution(); 3205ffd83dbSDimitry Andric if (!UnitContrib || 3215ffd83dbSDimitry Andric UnitContrib->Length != (getLength() + getUnitLengthFieldByteSize())) 3225ffd83dbSDimitry Andric return false; 3235ffd83dbSDimitry Andric auto *AbbrEntry = IndexEntry->getContribution(DW_SECT_ABBREV); 3245ffd83dbSDimitry Andric if (!AbbrEntry) 3255ffd83dbSDimitry Andric return false; 3265ffd83dbSDimitry Andric AbbrOffset = AbbrEntry->Offset; 3275ffd83dbSDimitry Andric return true; 3285ffd83dbSDimitry Andric } 3295ffd83dbSDimitry Andric 3300b57cec5SDimitry Andric // Parse the rangelist table header, including the optional array of offsets 3310b57cec5SDimitry Andric // following it (DWARF v5 and later). 332480093f4SDimitry Andric template<typename ListTableType> 333480093f4SDimitry Andric static Expected<ListTableType> 334480093f4SDimitry Andric parseListTableHeader(DWARFDataExtractor &DA, uint64_t Offset, 3358bcb0991SDimitry Andric DwarfFormat Format) { 3360b57cec5SDimitry Andric // We are expected to be called with Offset 0 or pointing just past the table 3378bcb0991SDimitry Andric // header. Correct Offset in the latter case so that it points to the start 3388bcb0991SDimitry Andric // of the header. 3390b57cec5SDimitry Andric if (Offset > 0) { 3408bcb0991SDimitry Andric uint64_t HeaderSize = DWARFListTableHeader::getHeaderSize(Format); 3418bcb0991SDimitry Andric if (Offset < HeaderSize) 342480093f4SDimitry Andric return createStringError(errc::invalid_argument, "did not detect a valid" 343480093f4SDimitry Andric " list table with base = 0x%" PRIx64 "\n", 3440b57cec5SDimitry Andric Offset); 3458bcb0991SDimitry Andric Offset -= HeaderSize; 3460b57cec5SDimitry Andric } 347480093f4SDimitry Andric ListTableType Table; 3480b57cec5SDimitry Andric if (Error E = Table.extractHeaderAndOffsets(DA, &Offset)) 3490b57cec5SDimitry Andric return std::move(E); 3500b57cec5SDimitry Andric return Table; 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric 3538bcb0991SDimitry Andric Error DWARFUnit::extractRangeList(uint64_t RangeListOffset, 3540b57cec5SDimitry Andric DWARFDebugRangeList &RangeList) const { 3550b57cec5SDimitry Andric // Require that compile unit is extracted. 3560b57cec5SDimitry Andric assert(!DieArray.empty()); 3570b57cec5SDimitry Andric DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, 3580b57cec5SDimitry Andric isLittleEndian, getAddressByteSize()); 3598bcb0991SDimitry Andric uint64_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; 3600b57cec5SDimitry Andric return RangeList.extract(RangesData, &ActualRangeListOffset); 3610b57cec5SDimitry Andric } 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric void DWARFUnit::clear() { 3640b57cec5SDimitry Andric Abbrevs = nullptr; 3650b57cec5SDimitry Andric BaseAddr.reset(); 3660b57cec5SDimitry Andric RangeSectionBase = 0; 367480093f4SDimitry Andric LocSectionBase = 0; 368480093f4SDimitry Andric AddrOffsetSectionBase = None; 3690b57cec5SDimitry Andric clearDIEs(false); 3700b57cec5SDimitry Andric DWO.reset(); 3710b57cec5SDimitry Andric } 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric const char *DWARFUnit::getCompilationDir() { 3740b57cec5SDimitry Andric return dwarf::toString(getUnitDIE().find(DW_AT_comp_dir), nullptr); 3750b57cec5SDimitry Andric } 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric void DWARFUnit::extractDIEsToVector( 3780b57cec5SDimitry Andric bool AppendCUDie, bool AppendNonCUDies, 3790b57cec5SDimitry Andric std::vector<DWARFDebugInfoEntry> &Dies) const { 3800b57cec5SDimitry Andric if (!AppendCUDie && !AppendNonCUDies) 3810b57cec5SDimitry Andric return; 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric // Set the offset to that of the first DIE and calculate the start of the 3840b57cec5SDimitry Andric // next compilation unit header. 3858bcb0991SDimitry Andric uint64_t DIEOffset = getOffset() + getHeaderSize(); 3868bcb0991SDimitry Andric uint64_t NextCUOffset = getNextUnitOffset(); 3870b57cec5SDimitry Andric DWARFDebugInfoEntry DIE; 3880b57cec5SDimitry Andric DWARFDataExtractor DebugInfoData = getDebugInfoExtractor(); 3890b57cec5SDimitry Andric uint32_t Depth = 0; 3900b57cec5SDimitry Andric bool IsCUDie = true; 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric while (DIE.extractFast(*this, &DIEOffset, DebugInfoData, NextCUOffset, 3930b57cec5SDimitry Andric Depth)) { 3940b57cec5SDimitry Andric if (IsCUDie) { 3950b57cec5SDimitry Andric if (AppendCUDie) 3960b57cec5SDimitry Andric Dies.push_back(DIE); 3970b57cec5SDimitry Andric if (!AppendNonCUDies) 3980b57cec5SDimitry Andric break; 3990b57cec5SDimitry Andric // The average bytes per DIE entry has been seen to be 4000b57cec5SDimitry Andric // around 14-20 so let's pre-reserve the needed memory for 4010b57cec5SDimitry Andric // our DIE entries accordingly. 4020b57cec5SDimitry Andric Dies.reserve(Dies.size() + getDebugInfoSize() / 14); 4030b57cec5SDimitry Andric IsCUDie = false; 4040b57cec5SDimitry Andric } else { 4050b57cec5SDimitry Andric Dies.push_back(DIE); 4060b57cec5SDimitry Andric } 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric if (const DWARFAbbreviationDeclaration *AbbrDecl = 4090b57cec5SDimitry Andric DIE.getAbbreviationDeclarationPtr()) { 4100b57cec5SDimitry Andric // Normal DIE 4110b57cec5SDimitry Andric if (AbbrDecl->hasChildren()) 4120b57cec5SDimitry Andric ++Depth; 4130b57cec5SDimitry Andric } else { 4140b57cec5SDimitry Andric // NULL DIE. 4150b57cec5SDimitry Andric if (Depth > 0) 4160b57cec5SDimitry Andric --Depth; 4170b57cec5SDimitry Andric if (Depth == 0) 4180b57cec5SDimitry Andric break; // We are done with this compile unit! 4190b57cec5SDimitry Andric } 4200b57cec5SDimitry Andric } 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric // Give a little bit of info if we encounter corrupt DWARF (our offset 4230b57cec5SDimitry Andric // should always terminate at or before the start of the next compilation 4240b57cec5SDimitry Andric // unit header). 4250b57cec5SDimitry Andric if (DIEOffset > NextCUOffset) 4265ffd83dbSDimitry Andric Context.getWarningHandler()( 4275ffd83dbSDimitry Andric createStringError(errc::invalid_argument, 4285ffd83dbSDimitry Andric "DWARF compile unit extends beyond its " 4298bcb0991SDimitry Andric "bounds cu 0x%8.8" PRIx64 " " 4308bcb0991SDimitry Andric "at 0x%8.8" PRIx64 "\n", 4315ffd83dbSDimitry Andric getOffset(), DIEOffset)); 4320b57cec5SDimitry Andric } 4330b57cec5SDimitry Andric 4348bcb0991SDimitry Andric void DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { 4358bcb0991SDimitry Andric if (Error e = tryExtractDIEsIfNeeded(CUDieOnly)) 4365ffd83dbSDimitry Andric Context.getRecoverableErrorHandler()(std::move(e)); 4378bcb0991SDimitry Andric } 4388bcb0991SDimitry Andric 4398bcb0991SDimitry Andric Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) { 4400b57cec5SDimitry Andric if ((CUDieOnly && !DieArray.empty()) || 4410b57cec5SDimitry Andric DieArray.size() > 1) 4428bcb0991SDimitry Andric return Error::success(); // Already parsed. 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric bool HasCUDie = !DieArray.empty(); 4450b57cec5SDimitry Andric extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray); 4460b57cec5SDimitry Andric 4470b57cec5SDimitry Andric if (DieArray.empty()) 4488bcb0991SDimitry Andric return Error::success(); 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric // If CU DIE was just parsed, copy several attribute values from it. 4518bcb0991SDimitry Andric if (HasCUDie) 4528bcb0991SDimitry Andric return Error::success(); 4538bcb0991SDimitry Andric 4548bcb0991SDimitry Andric DWARFDie UnitDie(this, &DieArray[0]); 4550b57cec5SDimitry Andric if (Optional<uint64_t> DWOId = toUnsigned(UnitDie.find(DW_AT_GNU_dwo_id))) 4560b57cec5SDimitry Andric Header.setDWOId(*DWOId); 4570b57cec5SDimitry Andric if (!IsDWO) { 458480093f4SDimitry Andric assert(AddrOffsetSectionBase == None); 4590b57cec5SDimitry Andric assert(RangeSectionBase == 0); 460480093f4SDimitry Andric assert(LocSectionBase == 0); 461480093f4SDimitry Andric AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_addr_base)); 4620b57cec5SDimitry Andric if (!AddrOffsetSectionBase) 4630b57cec5SDimitry Andric AddrOffsetSectionBase = 464480093f4SDimitry Andric toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base)); 4650b57cec5SDimitry Andric RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0); 466480093f4SDimitry Andric LocSectionBase = toSectionOffset(UnitDie.find(DW_AT_loclists_base), 0); 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric // In general, in DWARF v5 and beyond we derive the start of the unit's 4700b57cec5SDimitry Andric // contribution to the string offsets table from the unit DIE's 4710b57cec5SDimitry Andric // DW_AT_str_offsets_base attribute. Split DWARF units do not use this 4720b57cec5SDimitry Andric // attribute, so we assume that there is a contribution to the string 4730b57cec5SDimitry Andric // offsets table starting at offset 0 of the debug_str_offsets.dwo section. 4740b57cec5SDimitry Andric // In both cases we need to determine the format of the contribution, 4750b57cec5SDimitry Andric // which may differ from the unit's format. 4760b57cec5SDimitry Andric DWARFDataExtractor DA(Context.getDWARFObj(), StringOffsetSection, 4770b57cec5SDimitry Andric isLittleEndian, 0); 4780b57cec5SDimitry Andric if (IsDWO || getVersion() >= 5) { 4790b57cec5SDimitry Andric auto StringOffsetOrError = 4800b57cec5SDimitry Andric IsDWO ? determineStringOffsetsTableContributionDWO(DA) 4810b57cec5SDimitry Andric : determineStringOffsetsTableContribution(DA); 4828bcb0991SDimitry Andric if (!StringOffsetOrError) 4838bcb0991SDimitry Andric return createStringError(errc::invalid_argument, 4848bcb0991SDimitry Andric "invalid reference to or invalid content in " 4858bcb0991SDimitry Andric ".debug_str_offsets[.dwo]: " + 4868bcb0991SDimitry Andric toString(StringOffsetOrError.takeError())); 4878bcb0991SDimitry Andric 4880b57cec5SDimitry Andric StringOffsetsTableContribution = *StringOffsetOrError; 4890b57cec5SDimitry Andric } 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric // DWARF v5 uses the .debug_rnglists and .debug_rnglists.dwo sections to 4920b57cec5SDimitry Andric // describe address ranges. 4930b57cec5SDimitry Andric if (getVersion() >= 5) { 4945ffd83dbSDimitry Andric // In case of DWP, the base offset from the index has to be added. 4955ffd83dbSDimitry Andric uint64_t ContributionBaseOffset = 0; 4965ffd83dbSDimitry Andric if (IsDWO) { 4975ffd83dbSDimitry Andric if (auto *IndexEntry = Header.getIndexEntry()) 4985ffd83dbSDimitry Andric if (auto *Contrib = IndexEntry->getContribution(DW_SECT_RNGLISTS)) 4995ffd83dbSDimitry Andric ContributionBaseOffset = Contrib->Offset; 5005ffd83dbSDimitry Andric setRangesSection( 5015ffd83dbSDimitry Andric &Context.getDWARFObj().getRnglistsDWOSection(), 5025ffd83dbSDimitry Andric ContributionBaseOffset + 5035ffd83dbSDimitry Andric DWARFListTableHeader::getHeaderSize(Header.getFormat())); 5045ffd83dbSDimitry Andric } else 5050b57cec5SDimitry Andric setRangesSection(&Context.getDWARFObj().getRnglistsSection(), 5060b57cec5SDimitry Andric toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0)); 5070b57cec5SDimitry Andric if (RangeSection->Data.size()) { 5080b57cec5SDimitry Andric // Parse the range list table header. Individual range lists are 5090b57cec5SDimitry Andric // extracted lazily. 5100b57cec5SDimitry Andric DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection, 5110b57cec5SDimitry Andric isLittleEndian, 0); 512480093f4SDimitry Andric auto TableOrError = parseListTableHeader<DWARFDebugRnglistTable>( 513480093f4SDimitry Andric RangesDA, RangeSectionBase, Header.getFormat()); 5148bcb0991SDimitry Andric if (!TableOrError) 5158bcb0991SDimitry Andric return createStringError(errc::invalid_argument, 5168bcb0991SDimitry Andric "parsing a range list table: " + 5178bcb0991SDimitry Andric toString(TableOrError.takeError())); 5188bcb0991SDimitry Andric 5190b57cec5SDimitry Andric RngListTable = TableOrError.get(); 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric // In a split dwarf unit, there is no DW_AT_rnglists_base attribute. 5220b57cec5SDimitry Andric // Adjust RangeSectionBase to point past the table header. 5230b57cec5SDimitry Andric if (IsDWO && RngListTable) 5245ffd83dbSDimitry Andric RangeSectionBase = 5255ffd83dbSDimitry Andric ContributionBaseOffset + RngListTable->getHeaderSize(); 5260b57cec5SDimitry Andric } 527480093f4SDimitry Andric 528480093f4SDimitry Andric // In a split dwarf unit, there is no DW_AT_loclists_base attribute. 529480093f4SDimitry Andric // Setting LocSectionBase to point past the table header. 5305ffd83dbSDimitry Andric if (IsDWO) { 5315ffd83dbSDimitry Andric auto &DWOSection = Context.getDWARFObj().getLoclistsDWOSection(); 5325ffd83dbSDimitry Andric if (DWOSection.Data.empty()) 5335ffd83dbSDimitry Andric return Error::success(); 5345ffd83dbSDimitry Andric setLocSection(&DWOSection, 535480093f4SDimitry Andric DWARFListTableHeader::getHeaderSize(Header.getFormat())); 5365ffd83dbSDimitry Andric } else if (auto X = UnitDie.find(DW_AT_loclists_base)) { 537480093f4SDimitry Andric setLocSection(&Context.getDWARFObj().getLoclistsSection(), 5385ffd83dbSDimitry Andric toSectionOffset(X, 0)); 5395ffd83dbSDimitry Andric } else { 5405ffd83dbSDimitry Andric return Error::success(); 5415ffd83dbSDimitry Andric } 542480093f4SDimitry Andric 5435ffd83dbSDimitry Andric if (LocSection) { 544480093f4SDimitry Andric if (IsDWO) 545480093f4SDimitry Andric LoclistTableHeader.emplace(".debug_loclists.dwo", "locations"); 546480093f4SDimitry Andric else 547480093f4SDimitry Andric LoclistTableHeader.emplace(".debug_loclists", "locations"); 548480093f4SDimitry Andric 549480093f4SDimitry Andric uint64_t HeaderSize = DWARFListTableHeader::getHeaderSize(Header.getFormat()); 550480093f4SDimitry Andric uint64_t Offset = getLocSectionBase(); 551480093f4SDimitry Andric DWARFDataExtractor Data(Context.getDWARFObj(), *LocSection, 552480093f4SDimitry Andric isLittleEndian, getAddressByteSize()); 553480093f4SDimitry Andric if (Offset < HeaderSize) 554480093f4SDimitry Andric return createStringError(errc::invalid_argument, 555480093f4SDimitry Andric "did not detect a valid" 556480093f4SDimitry Andric " list table with base = 0x%" PRIx64 "\n", 557480093f4SDimitry Andric Offset); 558480093f4SDimitry Andric Offset -= HeaderSize; 5595ffd83dbSDimitry Andric if (auto *IndexEntry = Header.getIndexEntry()) 5605ffd83dbSDimitry Andric if (const auto *Contrib = IndexEntry->getContribution(DW_SECT_LOCLISTS)) 5615ffd83dbSDimitry Andric Offset += Contrib->Offset; 562480093f4SDimitry Andric if (Error E = LoclistTableHeader->extract(Data, &Offset)) 563480093f4SDimitry Andric return createStringError(errc::invalid_argument, 564480093f4SDimitry Andric "parsing a loclist table: " + 565480093f4SDimitry Andric toString(std::move(E))); 566480093f4SDimitry Andric } 5670b57cec5SDimitry Andric } 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for 5700b57cec5SDimitry Andric // skeleton CU DIE, so that DWARF users not aware of it are not broken. 5718bcb0991SDimitry Andric return Error::success(); 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric bool DWARFUnit::parseDWO() { 5750b57cec5SDimitry Andric if (IsDWO) 5760b57cec5SDimitry Andric return false; 5770b57cec5SDimitry Andric if (DWO.get()) 5780b57cec5SDimitry Andric return false; 5790b57cec5SDimitry Andric DWARFDie UnitDie = getUnitDIE(); 5800b57cec5SDimitry Andric if (!UnitDie) 5810b57cec5SDimitry Andric return false; 582480093f4SDimitry Andric auto DWOFileName = getVersion() >= 5 583480093f4SDimitry Andric ? dwarf::toString(UnitDie.find(DW_AT_dwo_name)) 584480093f4SDimitry Andric : dwarf::toString(UnitDie.find(DW_AT_GNU_dwo_name)); 5850b57cec5SDimitry Andric if (!DWOFileName) 5860b57cec5SDimitry Andric return false; 5870b57cec5SDimitry Andric auto CompilationDir = dwarf::toString(UnitDie.find(DW_AT_comp_dir)); 5880b57cec5SDimitry Andric SmallString<16> AbsolutePath; 5890b57cec5SDimitry Andric if (sys::path::is_relative(*DWOFileName) && CompilationDir && 5900b57cec5SDimitry Andric *CompilationDir) { 5910b57cec5SDimitry Andric sys::path::append(AbsolutePath, *CompilationDir); 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric sys::path::append(AbsolutePath, *DWOFileName); 5940b57cec5SDimitry Andric auto DWOId = getDWOId(); 5950b57cec5SDimitry Andric if (!DWOId) 5960b57cec5SDimitry Andric return false; 5970b57cec5SDimitry Andric auto DWOContext = Context.getDWOContext(AbsolutePath); 5980b57cec5SDimitry Andric if (!DWOContext) 5990b57cec5SDimitry Andric return false; 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andric DWARFCompileUnit *DWOCU = DWOContext->getDWOCompileUnitForHash(*DWOId); 6020b57cec5SDimitry Andric if (!DWOCU) 6030b57cec5SDimitry Andric return false; 6040b57cec5SDimitry Andric DWO = std::shared_ptr<DWARFCompileUnit>(std::move(DWOContext), DWOCU); 6050b57cec5SDimitry Andric // Share .debug_addr and .debug_ranges section with compile unit in .dwo 606480093f4SDimitry Andric if (AddrOffsetSectionBase) 607480093f4SDimitry Andric DWO->setAddrOffsetSection(AddrOffsetSection, *AddrOffsetSectionBase); 6080b57cec5SDimitry Andric if (getVersion() >= 5) { 6090b57cec5SDimitry Andric DWO->setRangesSection(&Context.getDWARFObj().getRnglistsDWOSection(), 0); 6100b57cec5SDimitry Andric DWARFDataExtractor RangesDA(Context.getDWARFObj(), *RangeSection, 6110b57cec5SDimitry Andric isLittleEndian, 0); 612480093f4SDimitry Andric if (auto TableOrError = parseListTableHeader<DWARFDebugRnglistTable>( 613480093f4SDimitry Andric RangesDA, RangeSectionBase, Header.getFormat())) 6140b57cec5SDimitry Andric DWO->RngListTable = TableOrError.get(); 6150b57cec5SDimitry Andric else 6165ffd83dbSDimitry Andric Context.getRecoverableErrorHandler()(createStringError( 6175ffd83dbSDimitry Andric errc::invalid_argument, "parsing a range list table: %s", 6185ffd83dbSDimitry Andric toString(TableOrError.takeError()).c_str())); 6195ffd83dbSDimitry Andric 6200b57cec5SDimitry Andric if (DWO->RngListTable) 6210b57cec5SDimitry Andric DWO->RangeSectionBase = DWO->RngListTable->getHeaderSize(); 6220b57cec5SDimitry Andric } else { 6230b57cec5SDimitry Andric auto DWORangesBase = UnitDie.getRangesBaseAttribute(); 6240b57cec5SDimitry Andric DWO->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); 6250b57cec5SDimitry Andric } 6260b57cec5SDimitry Andric 6270b57cec5SDimitry Andric return true; 6280b57cec5SDimitry Andric } 6290b57cec5SDimitry Andric 6300b57cec5SDimitry Andric void DWARFUnit::clearDIEs(bool KeepCUDie) { 6310b57cec5SDimitry Andric if (DieArray.size() > (unsigned)KeepCUDie) { 6320b57cec5SDimitry Andric DieArray.resize((unsigned)KeepCUDie); 6330b57cec5SDimitry Andric DieArray.shrink_to_fit(); 6340b57cec5SDimitry Andric } 6350b57cec5SDimitry Andric } 6360b57cec5SDimitry Andric 6370b57cec5SDimitry Andric Expected<DWARFAddressRangesVector> 6388bcb0991SDimitry Andric DWARFUnit::findRnglistFromOffset(uint64_t Offset) { 6390b57cec5SDimitry Andric if (getVersion() <= 4) { 6400b57cec5SDimitry Andric DWARFDebugRangeList RangeList; 6410b57cec5SDimitry Andric if (Error E = extractRangeList(Offset, RangeList)) 6420b57cec5SDimitry Andric return std::move(E); 6430b57cec5SDimitry Andric return RangeList.getAbsoluteRanges(getBaseAddress()); 6440b57cec5SDimitry Andric } 6450b57cec5SDimitry Andric if (RngListTable) { 6460b57cec5SDimitry Andric DWARFDataExtractor RangesData(Context.getDWARFObj(), *RangeSection, 6470b57cec5SDimitry Andric isLittleEndian, RngListTable->getAddrSize()); 6480b57cec5SDimitry Andric auto RangeListOrError = RngListTable->findList(RangesData, Offset); 6490b57cec5SDimitry Andric if (RangeListOrError) 6500b57cec5SDimitry Andric return RangeListOrError.get().getAbsoluteRanges(getBaseAddress(), *this); 6510b57cec5SDimitry Andric return RangeListOrError.takeError(); 6520b57cec5SDimitry Andric } 6530b57cec5SDimitry Andric 6540b57cec5SDimitry Andric return createStringError(errc::invalid_argument, 6550b57cec5SDimitry Andric "missing or invalid range list table"); 6560b57cec5SDimitry Andric } 6570b57cec5SDimitry Andric 6580b57cec5SDimitry Andric Expected<DWARFAddressRangesVector> 6590b57cec5SDimitry Andric DWARFUnit::findRnglistFromIndex(uint32_t Index) { 6600b57cec5SDimitry Andric if (auto Offset = getRnglistOffset(Index)) 661480093f4SDimitry Andric return findRnglistFromOffset(*Offset); 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric if (RngListTable) 6640b57cec5SDimitry Andric return createStringError(errc::invalid_argument, 6650b57cec5SDimitry Andric "invalid range list table index %d", Index); 6668bcb0991SDimitry Andric 6670b57cec5SDimitry Andric return createStringError(errc::invalid_argument, 6680b57cec5SDimitry Andric "missing or invalid range list table"); 6690b57cec5SDimitry Andric } 6700b57cec5SDimitry Andric 6710b57cec5SDimitry Andric Expected<DWARFAddressRangesVector> DWARFUnit::collectAddressRanges() { 6720b57cec5SDimitry Andric DWARFDie UnitDie = getUnitDIE(); 6730b57cec5SDimitry Andric if (!UnitDie) 6740b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "No unit DIE"); 6750b57cec5SDimitry Andric 6760b57cec5SDimitry Andric // First, check if unit DIE describes address ranges for the whole unit. 6770b57cec5SDimitry Andric auto CUDIERangesOrError = UnitDie.getAddressRanges(); 6780b57cec5SDimitry Andric if (!CUDIERangesOrError) 6790b57cec5SDimitry Andric return createStringError(errc::invalid_argument, 6800b57cec5SDimitry Andric "decoding address ranges: %s", 6810b57cec5SDimitry Andric toString(CUDIERangesOrError.takeError()).c_str()); 6820b57cec5SDimitry Andric return *CUDIERangesOrError; 6830b57cec5SDimitry Andric } 6840b57cec5SDimitry Andric 685480093f4SDimitry Andric Expected<DWARFLocationExpressionsVector> 686480093f4SDimitry Andric DWARFUnit::findLoclistFromOffset(uint64_t Offset) { 687480093f4SDimitry Andric DWARFLocationExpressionsVector Result; 688480093f4SDimitry Andric 689480093f4SDimitry Andric Error InterpretationError = Error::success(); 690480093f4SDimitry Andric 691480093f4SDimitry Andric Error ParseError = getLocationTable().visitAbsoluteLocationList( 692480093f4SDimitry Andric Offset, getBaseAddress(), 693480093f4SDimitry Andric [this](uint32_t Index) { return getAddrOffsetSectionItem(Index); }, 694480093f4SDimitry Andric [&](Expected<DWARFLocationExpression> L) { 695480093f4SDimitry Andric if (L) 696480093f4SDimitry Andric Result.push_back(std::move(*L)); 697480093f4SDimitry Andric else 698480093f4SDimitry Andric InterpretationError = 699480093f4SDimitry Andric joinErrors(L.takeError(), std::move(InterpretationError)); 700480093f4SDimitry Andric return !InterpretationError; 701480093f4SDimitry Andric }); 702480093f4SDimitry Andric 703480093f4SDimitry Andric if (ParseError || InterpretationError) 704480093f4SDimitry Andric return joinErrors(std::move(ParseError), std::move(InterpretationError)); 705480093f4SDimitry Andric 706480093f4SDimitry Andric return Result; 707480093f4SDimitry Andric } 708480093f4SDimitry Andric 7090b57cec5SDimitry Andric void DWARFUnit::updateAddressDieMap(DWARFDie Die) { 7100b57cec5SDimitry Andric if (Die.isSubroutineDIE()) { 7110b57cec5SDimitry Andric auto DIERangesOrError = Die.getAddressRanges(); 7120b57cec5SDimitry Andric if (DIERangesOrError) { 7130b57cec5SDimitry Andric for (const auto &R : DIERangesOrError.get()) { 7140b57cec5SDimitry Andric // Ignore 0-sized ranges. 7150b57cec5SDimitry Andric if (R.LowPC == R.HighPC) 7160b57cec5SDimitry Andric continue; 7170b57cec5SDimitry Andric auto B = AddrDieMap.upper_bound(R.LowPC); 7180b57cec5SDimitry Andric if (B != AddrDieMap.begin() && R.LowPC < (--B)->second.first) { 7190b57cec5SDimitry Andric // The range is a sub-range of existing ranges, we need to split the 7200b57cec5SDimitry Andric // existing range. 7210b57cec5SDimitry Andric if (R.HighPC < B->second.first) 7220b57cec5SDimitry Andric AddrDieMap[R.HighPC] = B->second; 7230b57cec5SDimitry Andric if (R.LowPC > B->first) 7240b57cec5SDimitry Andric AddrDieMap[B->first].first = R.LowPC; 7250b57cec5SDimitry Andric } 7260b57cec5SDimitry Andric AddrDieMap[R.LowPC] = std::make_pair(R.HighPC, Die); 7270b57cec5SDimitry Andric } 7280b57cec5SDimitry Andric } else 7290b57cec5SDimitry Andric llvm::consumeError(DIERangesOrError.takeError()); 7300b57cec5SDimitry Andric } 7310b57cec5SDimitry Andric // Parent DIEs are added to the AddrDieMap prior to the Children DIEs to 7320b57cec5SDimitry Andric // simplify the logic to update AddrDieMap. The child's range will always 7330b57cec5SDimitry Andric // be equal or smaller than the parent's range. With this assumption, when 7340b57cec5SDimitry Andric // adding one range into the map, it will at most split a range into 3 7350b57cec5SDimitry Andric // sub-ranges. 7360b57cec5SDimitry Andric for (DWARFDie Child = Die.getFirstChild(); Child; Child = Child.getSibling()) 7370b57cec5SDimitry Andric updateAddressDieMap(Child); 7380b57cec5SDimitry Andric } 7390b57cec5SDimitry Andric 7400b57cec5SDimitry Andric DWARFDie DWARFUnit::getSubroutineForAddress(uint64_t Address) { 7410b57cec5SDimitry Andric extractDIEsIfNeeded(false); 7420b57cec5SDimitry Andric if (AddrDieMap.empty()) 7430b57cec5SDimitry Andric updateAddressDieMap(getUnitDIE()); 7440b57cec5SDimitry Andric auto R = AddrDieMap.upper_bound(Address); 7450b57cec5SDimitry Andric if (R == AddrDieMap.begin()) 7460b57cec5SDimitry Andric return DWARFDie(); 7470b57cec5SDimitry Andric // upper_bound's previous item contains Address. 7480b57cec5SDimitry Andric --R; 7490b57cec5SDimitry Andric if (Address >= R->second.first) 7500b57cec5SDimitry Andric return DWARFDie(); 7510b57cec5SDimitry Andric return R->second.second; 7520b57cec5SDimitry Andric } 7530b57cec5SDimitry Andric 7540b57cec5SDimitry Andric void 7550b57cec5SDimitry Andric DWARFUnit::getInlinedChainForAddress(uint64_t Address, 7560b57cec5SDimitry Andric SmallVectorImpl<DWARFDie> &InlinedChain) { 7570b57cec5SDimitry Andric assert(InlinedChain.empty()); 7580b57cec5SDimitry Andric // Try to look for subprogram DIEs in the DWO file. 7590b57cec5SDimitry Andric parseDWO(); 7600b57cec5SDimitry Andric // First, find the subroutine that contains the given address (the leaf 7610b57cec5SDimitry Andric // of inlined chain). 7620b57cec5SDimitry Andric DWARFDie SubroutineDIE = 7630b57cec5SDimitry Andric (DWO ? *DWO : *this).getSubroutineForAddress(Address); 7640b57cec5SDimitry Andric 7650b57cec5SDimitry Andric if (!SubroutineDIE) 7660b57cec5SDimitry Andric return; 7670b57cec5SDimitry Andric 7680b57cec5SDimitry Andric while (!SubroutineDIE.isSubprogramDIE()) { 7690b57cec5SDimitry Andric if (SubroutineDIE.getTag() == DW_TAG_inlined_subroutine) 7700b57cec5SDimitry Andric InlinedChain.push_back(SubroutineDIE); 7710b57cec5SDimitry Andric SubroutineDIE = SubroutineDIE.getParent(); 7720b57cec5SDimitry Andric } 7730b57cec5SDimitry Andric InlinedChain.push_back(SubroutineDIE); 7740b57cec5SDimitry Andric } 7750b57cec5SDimitry Andric 7760b57cec5SDimitry Andric const DWARFUnitIndex &llvm::getDWARFUnitIndex(DWARFContext &Context, 7770b57cec5SDimitry Andric DWARFSectionKind Kind) { 7780b57cec5SDimitry Andric if (Kind == DW_SECT_INFO) 7790b57cec5SDimitry Andric return Context.getCUIndex(); 7805ffd83dbSDimitry Andric assert(Kind == DW_SECT_EXT_TYPES); 7810b57cec5SDimitry Andric return Context.getTUIndex(); 7820b57cec5SDimitry Andric } 7830b57cec5SDimitry Andric 7840b57cec5SDimitry Andric DWARFDie DWARFUnit::getParent(const DWARFDebugInfoEntry *Die) { 7850b57cec5SDimitry Andric if (!Die) 7860b57cec5SDimitry Andric return DWARFDie(); 7870b57cec5SDimitry Andric const uint32_t Depth = Die->getDepth(); 7880b57cec5SDimitry Andric // Unit DIEs always have a depth of zero and never have parents. 7890b57cec5SDimitry Andric if (Depth == 0) 7900b57cec5SDimitry Andric return DWARFDie(); 7910b57cec5SDimitry Andric // Depth of 1 always means parent is the compile/type unit. 7920b57cec5SDimitry Andric if (Depth == 1) 7930b57cec5SDimitry Andric return getUnitDIE(); 7940b57cec5SDimitry Andric // Look for previous DIE with a depth that is one less than the Die's depth. 7950b57cec5SDimitry Andric const uint32_t ParentDepth = Depth - 1; 7960b57cec5SDimitry Andric for (uint32_t I = getDIEIndex(Die) - 1; I > 0; --I) { 7970b57cec5SDimitry Andric if (DieArray[I].getDepth() == ParentDepth) 7980b57cec5SDimitry Andric return DWARFDie(this, &DieArray[I]); 7990b57cec5SDimitry Andric } 8000b57cec5SDimitry Andric return DWARFDie(); 8010b57cec5SDimitry Andric } 8020b57cec5SDimitry Andric 8030b57cec5SDimitry Andric DWARFDie DWARFUnit::getSibling(const DWARFDebugInfoEntry *Die) { 8040b57cec5SDimitry Andric if (!Die) 8050b57cec5SDimitry Andric return DWARFDie(); 8060b57cec5SDimitry Andric uint32_t Depth = Die->getDepth(); 8070b57cec5SDimitry Andric // Unit DIEs always have a depth of zero and never have siblings. 8080b57cec5SDimitry Andric if (Depth == 0) 8090b57cec5SDimitry Andric return DWARFDie(); 8100b57cec5SDimitry Andric // NULL DIEs don't have siblings. 8110b57cec5SDimitry Andric if (Die->getAbbreviationDeclarationPtr() == nullptr) 8120b57cec5SDimitry Andric return DWARFDie(); 8130b57cec5SDimitry Andric 8140b57cec5SDimitry Andric // Find the next DIE whose depth is the same as the Die's depth. 8150b57cec5SDimitry Andric for (size_t I = getDIEIndex(Die) + 1, EndIdx = DieArray.size(); I < EndIdx; 8160b57cec5SDimitry Andric ++I) { 8170b57cec5SDimitry Andric if (DieArray[I].getDepth() == Depth) 8180b57cec5SDimitry Andric return DWARFDie(this, &DieArray[I]); 8190b57cec5SDimitry Andric } 8200b57cec5SDimitry Andric return DWARFDie(); 8210b57cec5SDimitry Andric } 8220b57cec5SDimitry Andric 8230b57cec5SDimitry Andric DWARFDie DWARFUnit::getPreviousSibling(const DWARFDebugInfoEntry *Die) { 8240b57cec5SDimitry Andric if (!Die) 8250b57cec5SDimitry Andric return DWARFDie(); 8260b57cec5SDimitry Andric uint32_t Depth = Die->getDepth(); 8270b57cec5SDimitry Andric // Unit DIEs always have a depth of zero and never have siblings. 8280b57cec5SDimitry Andric if (Depth == 0) 8290b57cec5SDimitry Andric return DWARFDie(); 8300b57cec5SDimitry Andric 8310b57cec5SDimitry Andric // Find the previous DIE whose depth is the same as the Die's depth. 8320b57cec5SDimitry Andric for (size_t I = getDIEIndex(Die); I > 0;) { 8330b57cec5SDimitry Andric --I; 8340b57cec5SDimitry Andric if (DieArray[I].getDepth() == Depth - 1) 8350b57cec5SDimitry Andric return DWARFDie(); 8360b57cec5SDimitry Andric if (DieArray[I].getDepth() == Depth) 8370b57cec5SDimitry Andric return DWARFDie(this, &DieArray[I]); 8380b57cec5SDimitry Andric } 8390b57cec5SDimitry Andric return DWARFDie(); 8400b57cec5SDimitry Andric } 8410b57cec5SDimitry Andric 8420b57cec5SDimitry Andric DWARFDie DWARFUnit::getFirstChild(const DWARFDebugInfoEntry *Die) { 8430b57cec5SDimitry Andric if (!Die->hasChildren()) 8440b57cec5SDimitry Andric return DWARFDie(); 8450b57cec5SDimitry Andric 8460b57cec5SDimitry Andric // We do not want access out of bounds when parsing corrupted debug data. 8470b57cec5SDimitry Andric size_t I = getDIEIndex(Die) + 1; 8480b57cec5SDimitry Andric if (I >= DieArray.size()) 8490b57cec5SDimitry Andric return DWARFDie(); 8500b57cec5SDimitry Andric return DWARFDie(this, &DieArray[I]); 8510b57cec5SDimitry Andric } 8520b57cec5SDimitry Andric 8530b57cec5SDimitry Andric DWARFDie DWARFUnit::getLastChild(const DWARFDebugInfoEntry *Die) { 8540b57cec5SDimitry Andric if (!Die->hasChildren()) 8550b57cec5SDimitry Andric return DWARFDie(); 8560b57cec5SDimitry Andric 8570b57cec5SDimitry Andric uint32_t Depth = Die->getDepth(); 8580b57cec5SDimitry Andric for (size_t I = getDIEIndex(Die) + 1, EndIdx = DieArray.size(); I < EndIdx; 8590b57cec5SDimitry Andric ++I) { 8600b57cec5SDimitry Andric if (DieArray[I].getDepth() == Depth + 1 && 8610b57cec5SDimitry Andric DieArray[I].getTag() == dwarf::DW_TAG_null) 8620b57cec5SDimitry Andric return DWARFDie(this, &DieArray[I]); 8630b57cec5SDimitry Andric assert(DieArray[I].getDepth() > Depth && "Not processing children?"); 8640b57cec5SDimitry Andric } 8650b57cec5SDimitry Andric return DWARFDie(); 8660b57cec5SDimitry Andric } 8670b57cec5SDimitry Andric 8680b57cec5SDimitry Andric const DWARFAbbreviationDeclarationSet *DWARFUnit::getAbbreviations() const { 8690b57cec5SDimitry Andric if (!Abbrevs) 8700b57cec5SDimitry Andric Abbrevs = Abbrev->getAbbreviationDeclarationSet(Header.getAbbrOffset()); 8710b57cec5SDimitry Andric return Abbrevs; 8720b57cec5SDimitry Andric } 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric llvm::Optional<object::SectionedAddress> DWARFUnit::getBaseAddress() { 8750b57cec5SDimitry Andric if (BaseAddr) 8760b57cec5SDimitry Andric return BaseAddr; 8770b57cec5SDimitry Andric 8780b57cec5SDimitry Andric DWARFDie UnitDie = getUnitDIE(); 8790b57cec5SDimitry Andric Optional<DWARFFormValue> PC = UnitDie.find({DW_AT_low_pc, DW_AT_entry_pc}); 8800b57cec5SDimitry Andric BaseAddr = toSectionedAddress(PC); 8810b57cec5SDimitry Andric return BaseAddr; 8820b57cec5SDimitry Andric } 8830b57cec5SDimitry Andric 8840b57cec5SDimitry Andric Expected<StrOffsetsContributionDescriptor> 8850b57cec5SDimitry Andric StrOffsetsContributionDescriptor::validateContributionSize( 8860b57cec5SDimitry Andric DWARFDataExtractor &DA) { 8870b57cec5SDimitry Andric uint8_t EntrySize = getDwarfOffsetByteSize(); 8880b57cec5SDimitry Andric // In order to ensure that we don't read a partial record at the end of 8890b57cec5SDimitry Andric // the section we validate for a multiple of the entry size. 8900b57cec5SDimitry Andric uint64_t ValidationSize = alignTo(Size, EntrySize); 8910b57cec5SDimitry Andric // Guard against overflow. 8920b57cec5SDimitry Andric if (ValidationSize >= Size) 8930b57cec5SDimitry Andric if (DA.isValidOffsetForDataOfSize((uint32_t)Base, ValidationSize)) 8940b57cec5SDimitry Andric return *this; 8950b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "length exceeds section size"); 8960b57cec5SDimitry Andric } 8970b57cec5SDimitry Andric 8980b57cec5SDimitry Andric // Look for a DWARF64-formatted contribution to the string offsets table 8990b57cec5SDimitry Andric // starting at a given offset and record it in a descriptor. 9000b57cec5SDimitry Andric static Expected<StrOffsetsContributionDescriptor> 9018bcb0991SDimitry Andric parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint64_t Offset) { 9020b57cec5SDimitry Andric if (!DA.isValidOffsetForDataOfSize(Offset, 16)) 9030b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "section offset exceeds section size"); 9040b57cec5SDimitry Andric 9058bcb0991SDimitry Andric if (DA.getU32(&Offset) != dwarf::DW_LENGTH_DWARF64) 9060b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "32 bit contribution referenced from a 64 bit unit"); 9070b57cec5SDimitry Andric 9080b57cec5SDimitry Andric uint64_t Size = DA.getU64(&Offset); 9090b57cec5SDimitry Andric uint8_t Version = DA.getU16(&Offset); 9100b57cec5SDimitry Andric (void)DA.getU16(&Offset); // padding 9110b57cec5SDimitry Andric // The encoded length includes the 2-byte version field and the 2-byte 9120b57cec5SDimitry Andric // padding, so we need to subtract them out when we populate the descriptor. 9130b57cec5SDimitry Andric return StrOffsetsContributionDescriptor(Offset, Size - 4, Version, DWARF64); 9140b57cec5SDimitry Andric } 9150b57cec5SDimitry Andric 9160b57cec5SDimitry Andric // Look for a DWARF32-formatted contribution to the string offsets table 9170b57cec5SDimitry Andric // starting at a given offset and record it in a descriptor. 9180b57cec5SDimitry Andric static Expected<StrOffsetsContributionDescriptor> 9198bcb0991SDimitry Andric parseDWARF32StringOffsetsTableHeader(DWARFDataExtractor &DA, uint64_t Offset) { 9200b57cec5SDimitry Andric if (!DA.isValidOffsetForDataOfSize(Offset, 8)) 9210b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "section offset exceeds section size"); 9220b57cec5SDimitry Andric 9230b57cec5SDimitry Andric uint32_t ContributionSize = DA.getU32(&Offset); 9248bcb0991SDimitry Andric if (ContributionSize >= dwarf::DW_LENGTH_lo_reserved) 9250b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "invalid length"); 9260b57cec5SDimitry Andric 9270b57cec5SDimitry Andric uint8_t Version = DA.getU16(&Offset); 9280b57cec5SDimitry Andric (void)DA.getU16(&Offset); // padding 9290b57cec5SDimitry Andric // The encoded length includes the 2-byte version field and the 2-byte 9300b57cec5SDimitry Andric // padding, so we need to subtract them out when we populate the descriptor. 9310b57cec5SDimitry Andric return StrOffsetsContributionDescriptor(Offset, ContributionSize - 4, Version, 9320b57cec5SDimitry Andric DWARF32); 9330b57cec5SDimitry Andric } 9340b57cec5SDimitry Andric 9350b57cec5SDimitry Andric static Expected<StrOffsetsContributionDescriptor> 9360b57cec5SDimitry Andric parseDWARFStringOffsetsTableHeader(DWARFDataExtractor &DA, 9370b57cec5SDimitry Andric llvm::dwarf::DwarfFormat Format, 9380b57cec5SDimitry Andric uint64_t Offset) { 9390b57cec5SDimitry Andric StrOffsetsContributionDescriptor Desc; 9400b57cec5SDimitry Andric switch (Format) { 9410b57cec5SDimitry Andric case dwarf::DwarfFormat::DWARF64: { 9420b57cec5SDimitry Andric if (Offset < 16) 9430b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "insufficient space for 64 bit header prefix"); 9448bcb0991SDimitry Andric auto DescOrError = parseDWARF64StringOffsetsTableHeader(DA, Offset - 16); 9450b57cec5SDimitry Andric if (!DescOrError) 9460b57cec5SDimitry Andric return DescOrError.takeError(); 9470b57cec5SDimitry Andric Desc = *DescOrError; 9480b57cec5SDimitry Andric break; 9490b57cec5SDimitry Andric } 9500b57cec5SDimitry Andric case dwarf::DwarfFormat::DWARF32: { 9510b57cec5SDimitry Andric if (Offset < 8) 9520b57cec5SDimitry Andric return createStringError(errc::invalid_argument, "insufficient space for 32 bit header prefix"); 9538bcb0991SDimitry Andric auto DescOrError = parseDWARF32StringOffsetsTableHeader(DA, Offset - 8); 9540b57cec5SDimitry Andric if (!DescOrError) 9550b57cec5SDimitry Andric return DescOrError.takeError(); 9560b57cec5SDimitry Andric Desc = *DescOrError; 9570b57cec5SDimitry Andric break; 9580b57cec5SDimitry Andric } 9590b57cec5SDimitry Andric } 9600b57cec5SDimitry Andric return Desc.validateContributionSize(DA); 9610b57cec5SDimitry Andric } 9620b57cec5SDimitry Andric 9630b57cec5SDimitry Andric Expected<Optional<StrOffsetsContributionDescriptor>> 9640b57cec5SDimitry Andric DWARFUnit::determineStringOffsetsTableContribution(DWARFDataExtractor &DA) { 9655ffd83dbSDimitry Andric assert(!IsDWO); 9660b57cec5SDimitry Andric auto OptOffset = toSectionOffset(getUnitDIE().find(DW_AT_str_offsets_base)); 9670b57cec5SDimitry Andric if (!OptOffset) 9680b57cec5SDimitry Andric return None; 9695ffd83dbSDimitry Andric auto DescOrError = 9705ffd83dbSDimitry Andric parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), *OptOffset); 9710b57cec5SDimitry Andric if (!DescOrError) 9720b57cec5SDimitry Andric return DescOrError.takeError(); 9730b57cec5SDimitry Andric return *DescOrError; 9740b57cec5SDimitry Andric } 9750b57cec5SDimitry Andric 9760b57cec5SDimitry Andric Expected<Optional<StrOffsetsContributionDescriptor>> 9770b57cec5SDimitry Andric DWARFUnit::determineStringOffsetsTableContributionDWO(DWARFDataExtractor & DA) { 9785ffd83dbSDimitry Andric assert(IsDWO); 9790b57cec5SDimitry Andric uint64_t Offset = 0; 9800b57cec5SDimitry Andric auto IndexEntry = Header.getIndexEntry(); 9810b57cec5SDimitry Andric const auto *C = 9825ffd83dbSDimitry Andric IndexEntry ? IndexEntry->getContribution(DW_SECT_STR_OFFSETS) : nullptr; 9830b57cec5SDimitry Andric if (C) 9840b57cec5SDimitry Andric Offset = C->Offset; 9850b57cec5SDimitry Andric if (getVersion() >= 5) { 9860b57cec5SDimitry Andric if (DA.getData().data() == nullptr) 9870b57cec5SDimitry Andric return None; 9880b57cec5SDimitry Andric Offset += Header.getFormat() == dwarf::DwarfFormat::DWARF32 ? 8 : 16; 9890b57cec5SDimitry Andric // Look for a valid contribution at the given offset. 9900b57cec5SDimitry Andric auto DescOrError = parseDWARFStringOffsetsTableHeader(DA, Header.getFormat(), Offset); 9910b57cec5SDimitry Andric if (!DescOrError) 9920b57cec5SDimitry Andric return DescOrError.takeError(); 9930b57cec5SDimitry Andric return *DescOrError; 9940b57cec5SDimitry Andric } 9950b57cec5SDimitry Andric // Prior to DWARF v5, we derive the contribution size from the 9960b57cec5SDimitry Andric // index table (in a package file). In a .dwo file it is simply 9970b57cec5SDimitry Andric // the length of the string offsets section. 9980b57cec5SDimitry Andric if (!IndexEntry) 9995ffd83dbSDimitry Andric return {Optional<StrOffsetsContributionDescriptor>( 10005ffd83dbSDimitry Andric {0, StringOffsetSection.Data.size(), 4, Header.getFormat()})}; 10010b57cec5SDimitry Andric if (C) 10020b57cec5SDimitry Andric return {Optional<StrOffsetsContributionDescriptor>( 10035ffd83dbSDimitry Andric {C->Offset, C->Length, 4, Header.getFormat()})}; 10040b57cec5SDimitry Andric return None; 10050b57cec5SDimitry Andric } 1006